From 319732dde379ac27225d04e2c641e496ac2c9840 Mon Sep 17 00:00:00 2001
From: Ivan Borshchov
Date: Wed, 3 Jul 2024 12:31:53 +0300
Subject: [PATCH] Deploy website - based on
f39402ba4f81e937686c5ab9320ad8c1c44fe209
---
404.html | 2 +-
assets/js/0058754d.0dc70dcf.js | 1 +
assets/js/0058754d.5a65823b.js | 1 -
assets/js/322eff50.eac3ea2e.js | 1 -
assets/js/322eff50.fe38aa95.js | 1 +
assets/js/813b1aa0.a50518e8.js | 1 +
assets/js/813b1aa0.e330a24c.js | 1 -
...~main.f9ad0425.js => runtime~main.6a4e2ffc.js} | 2 +-
blog/archive/index.html | 2 +-
blog/first-blog-post/index.html | 2 +-
blog/index.html | 2 +-
blog/long-blog-post/index.html | 2 +-
blog/mdx-blog-post/index.html | 2 +-
blog/tags/docusaurus/index.html | 2 +-
blog/tags/facebook/index.html | 2 +-
blog/tags/hello/index.html | 2 +-
blog/tags/hola/index.html | 2 +-
blog/tags/index.html | 2 +-
blog/welcome/index.html | 2 +-
docs/api/index.html | 2 +-
docs/api/plugins/AuditLogPlugin/types/index.html | 2 +-
.../types/type-aliases/PluginOptions/index.html | 2 +-
.../ForeignInlineListPlugin/types/index.html | 2 +-
.../types/type-aliases/PluginOptions/index.html | 2 +-
.../enumerations/ActionCheckSource/index.html | 2 +-
.../enumerations/AdminForthDataTypes/index.html | 2 +-
.../AdminForthFilterOperators/index.html | 2 +-
.../enumerations/AdminForthMenuTypes/index.html | 2 +-
.../AdminForthResourcePages/index.html | 2 +-
.../AdminForthSortDirections/index.html | 2 +-
.../enumerations/AllowedActionsEnum/index.html | 2 +-
docs/api/types/AdminForthConfig/index.html | 2 +-
.../interfaces/AdminForthClass/index.html | 2 +-
.../AdminForthDataSourceConnector/index.html | 2 +-
.../index.html | 2 +-
.../interfaces/AdminForthPluginType/index.html | 2 +-
.../interfaces/CodeInjectorType/index.html | 2 +-
.../interfaces/ExpressHttpServer/index.html | 2 +-
.../interfaces/GenericHttpServer/index.html | 2 +-
.../AdminForthColumnEnumItem/index.html | 2 +-
.../AdminForthComponentDeclaration/index.html | 2 +-
.../AdminForthComponentDeclarationFull/index.html | 2 +-
.../type-aliases/AdminForthConfig/index.html | 2 +-
.../AdminForthConfigMenuItem/index.html | 2 +-
.../type-aliases/AdminForthDataSource/index.html | 2 +-
.../AdminForthFieldComponents/index.html | 2 +-
.../AdminForthForeignResource/index.html | 2 +-
.../type-aliases/AdminForthResource/index.html | 2 +-
.../AdminForthResourceColumn/index.html | 2 +-
.../type-aliases/AdminUser/index.html | 2 +-
.../AfterDataSourceResponseFunction/index.html | 2 +-
.../type-aliases/AfterSaveFunction/index.html | 2 +-
.../type-aliases/AllowedActionValue/index.html | 2 +-
.../type-aliases/AllowedActions/index.html | 2 +-
.../BeforeDataSourceRequestFunction/index.html | 2 +-
.../type-aliases/BeforeSaveFunction/index.html | 2 +-
.../type-aliases/ValidationObject/index.html | 2 +-
.../enumerations/AlertVariant/index.html | 2 +-
docs/api/types/FrontendAPI/index.html | 2 +-
.../interfaces/FrontendAPIInterface/index.html | 2 +-
.../type-aliases/AlertParams/index.html | 2 +-
.../type-aliases/ConfirmParams/index.html | 2 +-
docs/tutorial/Customization/alert/index.html | 2 +-
docs/tutorial/Customization/branding/index.html | 2 +-
.../tutorial/Customization/bulkActions/index.html | 2 +-
.../Customization/customFieldRendering/index.html | 2 +-
.../tutorial/Customization/customPages/index.html | 2 +-
docs/tutorial/Customization/hooks/index.html | 2 +-
.../Customization/limitingAccess/index.html | 2 +-
.../Customization/pageInjections/index.html | 2 +-
.../Customization/virtualColumns/index.html | 2 +-
docs/tutorial/Plugins/AuditLog/index.html | 15 +++++++++------
.../tutorial/Plugins/ForeignInlineList/index.html | 4 ++--
docs/tutorial/deploy/index.html | 2 +-
docs/tutorial/gettingStarted/index.html | 6 +++---
docs/tutorial/glossary/index.html | 2 +-
index.html | 2 +-
markdown-page/index.html | 2 +-
search/index.html | 2 +-
79 files changed, 87 insertions(+), 84 deletions(-)
create mode 100644 assets/js/0058754d.0dc70dcf.js
delete mode 100644 assets/js/0058754d.5a65823b.js
delete mode 100644 assets/js/322eff50.eac3ea2e.js
create mode 100644 assets/js/322eff50.fe38aa95.js
create mode 100644 assets/js/813b1aa0.a50518e8.js
delete mode 100644 assets/js/813b1aa0.e330a24c.js
rename assets/js/{runtime~main.f9ad0425.js => runtime~main.6a4e2ffc.js} (97%)
diff --git a/404.html b/404.html
index 010a77a12..1f11f8eaa 100644
--- a/404.html
+++ b/404.html
@@ -13,7 +13,7 @@
-
+
diff --git a/assets/js/0058754d.0dc70dcf.js b/assets/js/0058754d.0dc70dcf.js
new file mode 100644
index 000000000..b91162caa
--- /dev/null
+++ b/assets/js/0058754d.0dc70dcf.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[3800],{2681:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>a});var s=i(4848),t=i(8453);const o={},r=void 0,l={id:"tutorial/Plugins/ForeignInlineList",title:"ForeignInlineList",description:"Foreign inline list plugin allows to display a list (table) of items from a foreign table in the show view.",source:"@site/docs/tutorial/Plugins/ForeignInlineList.md",sourceDirName:"tutorial/Plugins",slug:"/tutorial/Plugins/ForeignInlineList",permalink:"/docs/tutorial/Plugins/ForeignInlineList",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"AuditLog",permalink:"/docs/tutorial/Plugins/AuditLog"}},d={},a=[{value:"Usage",id:"usage",level:2}];function c(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Foreign inline list plugin allows to display a list (table) of items from a foreign table in the show view."}),"\n",(0,s.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,s.jsx)(n.p,{children:"Import plugin:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import ForeignInlineListPlugin from 'adminforth/plugins/ForeignInlineListPlugin';\n"})}),"\n",(0,s.jsx)(n.p,{children:"If you are using pure Node without TypeScript, you can use the following code:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import ForeignInlineListPlugin from 'adminforth/dist/plugins/ForeignInlineListPlugin/index.js';\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In ",(0,s.jsx)(n.a,{href:"/docs/tutorial/gettingStarted",children:"Getting Started"})," we created a ",(0,s.jsx)(n.code,{children:"'aparts'"})," resource which has a field ",(0,s.jsx)(n.code,{children:"'realtor_id'"}),".\nThis field refers to record from ",(0,s.jsx)(n.code,{children:"'users'"})," resource. This means that we can display a list of appartments in the user's show view."]}),"\n",(0,s.jsxs)(n.p,{children:["Add to your ",(0,s.jsx)(n.code,{children:"'users'"})," resource configuration (which we created in ), plugin instance:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",metastring:'title="./index.ts"',children:"{ \n ...\n resourceId: 'users',\n ...\n//diff-add\n plugins: [\n//diff-add\n new ForeignInlineListPlugin({\n//diff-add\n foreignResourceId: 'aparts',\n//diff-add\n modifyTableResourceConfig: (resourceConfig: AdminForthResource) => {\n//diff-add\n // hide column 'square_meter' from both 'list' and 'filter'\n//diff-add\n const column = resourceConfig.columns.find((c: AdminForthResourceColumn) => c.name === 'square_meter')!.showIn = [];\n//diff-add\n resourceConfig.options!.listPageSize = 1;\n//diff-add\n // feel free to console.log and edit resourceConfig as you need\n//diff-add\n },\n//diff-add\n }),\n//diff-add\n ],\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use ",(0,s.jsx)(n.code,{children:"modifyTableResourceConfig"})," callback to modify what columns to show in the list and filter of the foreign table."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"alt text",src:i(3986).A+"",width:"3670",height:"2044"})}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions",children:"API Reference"})," for more all options."]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},3986:(e,n,i)=>{i.d(n,{A:()=>s});const s=i.p+"assets/images/localhost_3500_resource_users_show_08dpfh-a8f5bd63bb09e071c67a13d7121e95fd.png"},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var s=i(6540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/0058754d.5a65823b.js b/assets/js/0058754d.5a65823b.js
deleted file mode 100644
index 965a34e83..000000000
--- a/assets/js/0058754d.5a65823b.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[3800],{2681:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var s=i(4848),t=i(8453);const o={},r=void 0,l={id:"tutorial/Plugins/ForeignInlineList",title:"ForeignInlineList",description:"Foreign inline list plugin allows to display a list (table) of items from a foreign table in the show view.",source:"@site/docs/tutorial/Plugins/ForeignInlineList.md",sourceDirName:"tutorial/Plugins",slug:"/tutorial/Plugins/ForeignInlineList",permalink:"/docs/tutorial/Plugins/ForeignInlineList",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"AuditLog",permalink:"/docs/tutorial/Plugins/AuditLog"}},a={},c=[{value:"Usage",id:"usage",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Foreign inline list plugin allows to display a list (table) of items from a foreign table in the show view."}),"\n",(0,s.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,s.jsx)(n.p,{children:"Import plugin:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import ForeignInlineListPlugin from 'adminforth/plugins/ForeignInlineListPlugin';\n"})}),"\n",(0,s.jsx)(n.p,{children:"If you are using pure Node without TypeScript, you can use the following code:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import ForeignInlineListPlugin from 'adminforth/dist/plugins/ForeignInlineListPlugin/index.js';\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In ",(0,s.jsx)(n.a,{href:"/docs/tutorial/gettingStarted",children:"Getting Started"})," we created a ",(0,s.jsx)(n.code,{children:"'aparts'"})," resource which has a field ",(0,s.jsx)(n.code,{children:"'realtor_id'"}),".\nThis field refers to record from ",(0,s.jsx)(n.code,{children:"'users'"})," resource. This means that we can display a list of appartments in the user's show view."]}),"\n",(0,s.jsxs)(n.p,{children:["Add to your ",(0,s.jsx)(n.code,{children:"'users'"})," resource configuration (which we created in ), plugin instance:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"{ \n ...\n resourceId: 'users',\n ...\n plugins: [\n new ForeignInlineListPlugin({\n foreignResourceId: 'aparts',\n modifyTableResourceConfig: (resourceConfig: AdminForthResource) => {\n // hide column 'square_meter' from both 'list' and 'filter'\n const column = resourceConfig.columns.find((c: AdminForthResourceColumn) => c.name === 'square_meter')!.showIn = [];\n resourceConfig.options!.listPageSize = 1;\n\n // feel free to console.log and edit resourceConfig as you need\n },\n }),\n ],\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use ",(0,s.jsx)(n.code,{children:"modifyTableResourceConfig"})," callback to modify what columns to show in the list and filter of the foreign table."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"alt text",src:i(3986).A+"",width:"3670",height:"2044"})}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions",children:"API Reference"})," for more all options."]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},3986:(e,n,i)=>{i.d(n,{A:()=>s});const s=i.p+"assets/images/localhost_3500_resource_users_show_08dpfh-a8f5bd63bb09e071c67a13d7121e95fd.png"},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var s=i(6540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/322eff50.eac3ea2e.js b/assets/js/322eff50.eac3ea2e.js
deleted file mode 100644
index b1d9fb561..000000000
--- a/assets/js/322eff50.eac3ea2e.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[6956],{2143:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=t(4848),r=t(8453);const s={},i="Getting Started",o={id:"tutorial/gettingStarted",title:"Getting Started",description:"Prerequisites",source:"@site/docs/tutorial/01-gettingStarted.md",sourceDirName:"tutorial",slug:"/tutorial/gettingStarted",permalink:"/docs/tutorial/gettingStarted",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{},sidebar:"tutorialSidebar",next:{title:"Glossary",permalink:"/docs/tutorial/glossary"}},l={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Basic Philosophy",id:"basic-philosophy",level:2},{value:"Setting up a first demo",id:"setting-up-a-first-demo",level:2},{value:"Possible configuration options",id:"possible-configuration-options",level:2}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",img:"img",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"getting-started",children:"Getting Started"}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(n.p,{children:"We recommend using Node v18 and higher:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"nvm install 18\nnvm alias default 18\nnvm use 18\n"})}),"\n",(0,a.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"mkdir myadmin\ncd myadmin\nnpm install adminforth\n"})}),"\n",(0,a.jsxs)(n.p,{children:["AdminForth does not provide own HTTP server, but can add own listeners over exisitng ",(0,a.jsx)(n.a,{href:"https://expressjs.com/",children:"Express"})," server (Fastify support is planned in future). This allows to create custom APIs for backoffice in a way you know."]}),"\n",(0,a.jsx)(n.p,{children:"Let's install express:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install express@4.19.2\n"})}),"\n",(0,a.jsx)(n.p,{children:"For demo purposes we will use SQLite data source. You can use postgress, Mongo or Clickhouse as well."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install better-sqlite3@10.0.0\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can use adminforth in pure Node, but we recommend using TypeScript for better development experience:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install typescript@5.4.5 tsx@4.11.2 --save-dev\n"})}),"\n",(0,a.jsx)(n.h2,{id:"basic-philosophy",children:"Basic Philosophy"}),"\n",(0,a.jsx)(n.p,{children:"AdminForth connects to existing databases and provides a backoffice for managing data including CRUD operations, filtering, sorting, and more."}),"\n",(0,a.jsx)(n.p,{children:"Database should be already created by using any database management tool, ORM or migrator. AdminForth does not provide a way to create tables or columns in the database."}),"\n",(0,a.jsx)(n.p,{children:'Once you have a database, you pass a connection string to AdminForth and define resources(tables) and columns you would like to see in backoffice. For most DB AdminForth can "discover" column types and constraints (e.g. max-length) by connecting to DB. However you can redefine them in AdminForth configuration. Type and constraints definition are take precedence over DB schema.'}),"\n",(0,a.jsx)(n.p,{children:'Also in AdminForth you can define in "Vue" way how each field will be rendered, and create own pages e.g. Dashboards.'}),"\n",(0,a.jsxs)(n.p,{children:["In the demo we will create a simple database with 2 tables: ",(0,a.jsx)(n.code,{children:"apartments"})," and ",(0,a.jsx)(n.code,{children:"users"}),". We will just use plain SQL to create tables and insert some fake data."]}),"\n",(0,a.jsx)(n.p,{children:"Users table will be used to store a credentials for login into backoffice itself."}),"\n",(0,a.jsx)(n.h2,{id:"setting-up-a-first-demo",children:"Setting up a first demo"}),"\n",(0,a.jsxs)(n.p,{children:["Open ",(0,a.jsx)(n.code,{children:"package.json"}),", set ",(0,a.jsx)(n.code,{children:"type"})," to ",(0,a.jsx)(n.code,{children:"module"})," and add ",(0,a.jsx)(n.code,{children:"start"})," script:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n ...\n "type": "module",\n "scripts": {\n ...\n "start": "ADMINFORTH_SECRET=CHANGE_ME_IN_PRODUCTION NODE_ENV=development tsx watch index.ts"\n },\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Create ",(0,a.jsx)(n.code,{children:"index.ts"})," file in root directory with following content:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",children:"import betterSqlite3 from 'better-sqlite3';\nimport express from 'express';\nimport AdminForth from 'adminforth';\n\nconst DB_FILE = 'test.sqlite';\nlet db;\n\nconst ADMIN_BASE_URL = '';\n\nexport const admin = new AdminForth({\n baseUrl : ADMIN_BASE_URL,\n rootUser: {\n username: 'adminforth', // use these as credentials to login\n password: 'adminforth',\n },\n auth: {\n resourceId: 'users', // resource for getting user\n usernameField: 'email',\n passwordHashField: 'password_hash',\n },\n customization: {\n brandName: 'My Admin',\n datesFormat: 'D MMM YY HH:mm:ss',\n emptyFieldPlaceholder: '-',\n },\n\n dataSources: [\n {\n id: 'maindb',\n url: `sqlite://${DB_FILE}`\n },\n ],\n resources: [\n {\n dataSource: 'maindb', \n table: 'apartments',\n resourceId: 'aparts', // resourceId is defaulted to table name but you can change it e.g. \n // in case of same table names from different data sources\n label: 'Apartments', // label is defaulted to table name but you can change it\n recordLabel: (r) => `\ud83c\udfe1 ${r.title}`,\n columns: [\n { \n name: 'id', \n label: 'Identifier', // if you wish you can redefine label\n showIn: ['filter', 'show'], // show in filter and in show page\n primaryKey: true,\n fillOnCreate: ({initialRecord, adminUser}) => Math.random().toString(36).substring(7), // initialRecord is values user entered, adminUser object of user who creates record\n },\n { \n name: 'title',\n required: true,\n showIn: ['list', 'create', 'edit', 'filter', 'show'], // the default is full set\n maxLength: 255, // you can set max length for string fields\n minLength: 3, // you can set min length for string fields\n }, \n {\n name: 'created_at',\n type: AdminForth.Types.DATETIME ,\n allowMinMaxQuery: true,\n showIn: ['list', 'filter', 'show', 'edit'],\n fillOnCreate: ({initialRecord, adminUser}) => (new Date()).toISOString(),\n },\n { \n name: 'price',\n min: 10,\n max: 10000.12,\n allowMinMaxQuery: true, // use better experience for filtering e.g. date range, set it only if you have index on this column or if there will be low number of rows\n editingNote: 'Price is in USD', // you can appear note on editing or creating page\n },\n { \n name: 'square_meter', \n label: 'Square', \n allowMinMaxQuery: true,\n minValue: 1, // you can set min /max value for number fields\n maxValue: 1000,\n },\n { \n name: 'number_of_rooms',\n allowMinMaxQuery: true,\n enum: [\n { value: 1, label: '1 room' },\n { value: 2, label: '2 rooms' },\n { value: 3, label: '3 rooms' },\n { value: 4, label: '4 rooms' },\n { value: 5, label: '5 rooms' },\n ],\n },\n { \n name: 'description',\n sortable: false,\n showIn: ['show', 'edit', 'create', 'filter'],\n },\n {\n name: 'country',\n enum: [{\n value: 'US',\n label: 'United States'\n }, {\n value: 'DE',\n label: 'Germany'\n }, {\n value: 'FR',\n label: 'France'\n }, {\n value: 'UK',\n label: 'United Kingdom'\n }, {\n value:'NL',\n label: 'Netherlands'\n }, {\n value: 'IT',\n label: 'Italy'\n }, {\n value: 'ES',\n label: 'Spain'\n }, {\n value: 'DK',\n label: 'Denmark'\n }, {\n value: 'PL',\n label: 'Poland'\n }, {\n value: 'UA',\n label: 'Ukraine'\n }, {\n value: null,\n label: 'Not defined'\n }],\n },\n {\n name: 'listed',\n required: true, // will be required on create/edit\n },\n {\n name: 'realtor_id',\n foreignResource: {\n resourceId: 'users',\n }\n }\n ],\n options: {\n listPageSize: 12,\n allowedActions:{\n edit: true,\n delete: true,\n show: true,\n filter: true,\n },\n },\n },\n { \n dataSource: 'maindb', \n table: 'users',\n resourceId: 'users',\n label: 'Users', \n recordLabel: (r) => `\ud83d\udc64 ${r.email}`,\n columns: [\n { \n name: 'id', \n primaryKey: true,\n fillOnCreate: ({initialRecord, adminUser}) => Math.random().toString(36).substring(7),\n showIn: ['list', 'filter', 'show'],\n },\n { \n name: 'email', \n required: true,\n isUnique: true,\n validation: [\n {\n regExp: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}$',\n message: 'Email is not valid, must be in format example@test.com'\n },\n ]\n },\n { \n name: 'created_at', \n type: AdminForth.Types.DATETIME,\n showIn: ['list', 'filter', 'show'],\n fillOnCreate: ({initialRecord, adminUser}) => (new Date()).toISOString(),\n },\n {\n name: 'role',\n enum: [\n { value: 'superadmin', label: 'Super Admin' },\n { value: 'user', label: 'User' },\n ]\n },\n {\n name: 'password',\n virtual: true, // field will not be persisted into db\n required: { create: true }, // make required only on create page\n editingNote: { edit: 'Leave empty to keep password unchanged' },\n minLength: 8,\n type: AdminForth.Types.STRING,\n showIn: ['create', 'edit'], // to show field only on create and edit pages\n masked: true, // to show stars in input field\n }\n ],\n hooks: {\n create: {\n beforeSave: async ({ record, adminUser, resource }) => {\n record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);\n return { ok: true };\n }\n },\n edit: {\n beforeSave: async ({ record, adminUser, resource}) => {\n if (record.password) {\n record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);\n }\n return { ok: true }\n },\n },\n }\n },\n ],\n menu: [\n {\n label: 'Core',\n icon: 'flowbite:brain-solid', // any icon from iconify supported in format :, e.g. from here https://icon-sets.iconify.design/flowbite/\n open: true,\n children: [\n {\n homepage: true,\n label: 'Appartments',\n icon: 'flowbite:home-solid',\n resourceId: 'aparts',\n },\n ]\n },\n {\n type: 'gap'\n },\n {\n type: 'divider'\n },\n {\n type: 'heading',\n label: 'SYSTEM',\n },\n {\n label: 'Users',\n icon: 'flowbite:user-solid',\n resourceId: 'users',\n }\n ],\n});\n\n\nasync function initDataBase() {\n db = betterSqlite3(DB_FILE);\n\n const tableExists = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='apartments';`).get();\n if (!tableExists) {\n // if no table - create couple of tables and fill them with some mock data\n await db.prepare(`\n CREATE TABLE apartments (\n id VARCHAR(20) PRIMARY KEY NOT NULL,\n title VARCHAR(255) NOT NULL,\n square_meter REAL,\n price DECIMAL(10, 2) NOT NULL,\n number_of_rooms INT,\n description TEXT,\n country VARCHAR(2),\n listed BOOLEAN DEFAULT FALSE,\n created_at TIMESTAMP,\n realtor_id VARCHAR(255)\n );`).run();\n\n await db.prepare(`\n CREATE TABLE users (\n id VARCHAR(255) PRIMARY KEY NOT NULL,\n email VARCHAR(255) NOT NULL,\n password_hash VARCHAR(255) NOT NULL,\n created_at VARCHAR(255) NOT NULL,\n role VARCHAR(255) NOT NULL\n );`).run();\n\n for (let i = 0; i < 100; i++) {\n await db.prepare(`\n INSERT INTO apartments (\n id, title, square_meter, price, \n number_of_rooms, description, \n created_at, listed, \n country\n ) VALUES (\n '${i}', 'Apartment ${i}', ${(Math.random() * 100).toFixed(1)}, ${(Math.random() * 10000).toFixed(2)}, \n ${ Math.floor(Math.random() * 5) }, 'Next gen apartments', \n ${ Date.now() / 1000 - Math.random() * 14 * 60 * 60 * 24 }, ${i % 2 == 0}, \n '${['US', 'DE', 'FR', 'UK', 'NL', 'IT', 'ES', 'DK', 'PL', 'UA'][Math.floor(Math.random() * 10)]}'\n )`).run();\n }\n }\n}\n\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n // if script is executed directly e.g. node index.ts or npm start\n\n await initDataBase();\n\n const app = express()\n app.use(express.json());\n const port = 3500;\n\n (async () => {\n // needed to compile SPA. Call it here or from a build script e.g. in Docker build time to reduce downtime\n await admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development'});\n console.log('Bundling AdminForth done. For faster serving consider calling bundleNow() from a build script.');\n })();\n\n\n // serve after you added all api\n admin.express.serve(app)\n admin.discoverDatabases();\n\n\n app.listen(port, () => {\n console.log(`Example app listening at http://localhost:${port}`)\n console.log(`\\n\u26a1 AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\\n`)\n });\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Now you can run your app:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm start\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Open ",(0,a.jsx)(n.a,{href:"http://localhost:3500",children:"http://localhost:3500"})," in your browser and login with credentials ",(0,a.jsx)(n.code,{children:"adminforth"})," / ",(0,a.jsx)(n.code,{children:"adminforth"}),"."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"alt text",src:t(8332).A+"",width:"2428",height:"1932"})}),"\n",(0,a.jsxs)(n.p,{children:["After Login you should see:\n",(0,a.jsx)(n.img,{alt:"alt text",src:t(4973).A+"",width:"3700",height:"1932"})]}),"\n",(0,a.jsx)(n.h2,{id:"possible-configuration-options",children:"Possible configuration options"}),"\n",(0,a.jsx)(n.p,{children:"We will use schema with different column types for apartments to show many of AdminForth features."}),"\n",(0,a.jsxs)(n.p,{children:["Check ",(0,a.jsx)(n.a,{href:"/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig",children:"AdminForthConfig"})," for all possible options."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8332:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/localhost_3500_login-22b59511349c51948267c9a4080e4d87.png"},4973:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/localhost_3500_resource_aparts-dddac951816a2a7b58c84b6348828ecb.png"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>o});var a=t(6540);const r={},s=a.createContext(r);function i(e){const n=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/322eff50.fe38aa95.js b/assets/js/322eff50.fe38aa95.js
new file mode 100644
index 000000000..ec357d48e
--- /dev/null
+++ b/assets/js/322eff50.fe38aa95.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[6956],{2143:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=t(4848),r=t(8453);const s={},i="Getting Started",o={id:"tutorial/gettingStarted",title:"Getting Started",description:"Prerequisites",source:"@site/docs/tutorial/01-gettingStarted.md",sourceDirName:"tutorial",slug:"/tutorial/gettingStarted",permalink:"/docs/tutorial/gettingStarted",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{},sidebar:"tutorialSidebar",next:{title:"Glossary",permalink:"/docs/tutorial/glossary"}},l={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Basic Philosophy",id:"basic-philosophy",level:2},{value:"Setting up a first demo",id:"setting-up-a-first-demo",level:2},{value:"Possible configuration options",id:"possible-configuration-options",level:2}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",img:"img",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"getting-started",children:"Getting Started"}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(n.p,{children:"We recommend using Node v18 and higher:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"nvm install 18\nnvm alias default 18\nnvm use 18\n"})}),"\n",(0,a.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"mkdir myadmin\ncd myadmin\nnpm install adminforth\n"})}),"\n",(0,a.jsxs)(n.p,{children:["AdminForth does not provide own HTTP server, but can add own listeners over exisitng ",(0,a.jsx)(n.a,{href:"https://expressjs.com/",children:"Express"})," server (Fastify support is planned in future). This allows to create custom APIs for backoffice in a way you know."]}),"\n",(0,a.jsx)(n.p,{children:"Let's install express:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install express@4.19.2\n"})}),"\n",(0,a.jsx)(n.p,{children:"For demo purposes we will use SQLite data source. You can use postgress, Mongo or Clickhouse as well."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install better-sqlite3@10.0.0\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can use adminforth in pure Node, but we recommend using TypeScript for better development experience:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm install typescript@5.4.5 tsx@4.11.2 --save-dev\n"})}),"\n",(0,a.jsx)(n.h2,{id:"basic-philosophy",children:"Basic Philosophy"}),"\n",(0,a.jsx)(n.p,{children:"AdminForth connects to existing databases and provides a backoffice for managing data including CRUD operations, filtering, sorting, and more."}),"\n",(0,a.jsx)(n.p,{children:"Database should be already created by using any database management tool, ORM or migrator. AdminForth does not provide a way to create tables or columns in the database."}),"\n",(0,a.jsx)(n.p,{children:'Once you have a database, you pass a connection string to AdminForth and define resources(tables) and columns you would like to see in backoffice. For most DB AdminForth can "discover" column types and constraints (e.g. max-length) by connecting to DB. However you can redefine them in AdminForth configuration. Type and constraints definition are take precedence over DB schema.'}),"\n",(0,a.jsx)(n.p,{children:'Also in AdminForth you can define in "Vue" way how each field will be rendered, and create own pages e.g. Dashboards.'}),"\n",(0,a.jsxs)(n.p,{children:["In the demo we will create a simple database with 2 tables: ",(0,a.jsx)(n.code,{children:"apartments"})," and ",(0,a.jsx)(n.code,{children:"users"}),". We will just use plain SQL to create tables and insert some fake data."]}),"\n",(0,a.jsx)(n.p,{children:"Users table will be used to store a credentials for login into backoffice itself."}),"\n",(0,a.jsx)(n.h2,{id:"setting-up-a-first-demo",children:"Setting up a first demo"}),"\n",(0,a.jsxs)(n.p,{children:["Open ",(0,a.jsx)(n.code,{children:"package.json"}),", set ",(0,a.jsx)(n.code,{children:"type"})," to ",(0,a.jsx)(n.code,{children:"module"})," and add ",(0,a.jsx)(n.code,{children:"start"})," script:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",metastring:'title="./package.json"',children:'{\n ...\n//diff-add\n "type": "module",\n "scripts": {\n ...\n//diff-add\n "start": "ADMINFORTH_SECRET=CHANGE_ME_IN_PRODUCTION NODE_ENV=development tsx watch index.ts"\n },\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Create ",(0,a.jsx)(n.code,{children:"index.ts"})," file in root directory with following content:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",metastring:'title="./index.ts"',children:"import betterSqlite3 from 'better-sqlite3';\nimport express from 'express';\nimport AdminForth from 'adminforth';\n\nconst DB_FILE = 'test.sqlite';\nlet db;\n\nconst ADMIN_BASE_URL = '';\n\nexport const admin = new AdminForth({\n baseUrl : ADMIN_BASE_URL,\n rootUser: {\n username: 'adminforth', // use these as credentials to login\n password: 'adminforth',\n },\n auth: {\n resourceId: 'users', // resource for getting user\n usernameField: 'email',\n passwordHashField: 'password_hash',\n },\n customization: {\n brandName: 'My Admin',\n datesFormat: 'D MMM YY HH:mm:ss',\n emptyFieldPlaceholder: '-',\n },\n\n dataSources: [\n {\n id: 'maindb',\n url: `sqlite://${DB_FILE}`\n },\n ],\n resources: [\n {\n dataSource: 'maindb', \n table: 'apartments',\n resourceId: 'aparts', // resourceId is defaulted to table name but you can change it e.g. \n // in case of same table names from different data sources\n label: 'Apartments', // label is defaulted to table name but you can change it\n recordLabel: (r) => `\ud83c\udfe1 ${r.title}`,\n columns: [\n { \n name: 'id', \n label: 'Identifier', // if you wish you can redefine label\n showIn: ['filter', 'show'], // show in filter and in show page\n primaryKey: true,\n fillOnCreate: ({initialRecord, adminUser}) => Math.random().toString(36).substring(7), // initialRecord is values user entered, adminUser object of user who creates record\n },\n { \n name: 'title',\n required: true,\n showIn: ['list', 'create', 'edit', 'filter', 'show'], // the default is full set\n maxLength: 255, // you can set max length for string fields\n minLength: 3, // you can set min length for string fields\n }, \n {\n name: 'created_at',\n type: AdminForth.Types.DATETIME ,\n allowMinMaxQuery: true,\n showIn: ['list', 'filter', 'show', 'edit'],\n fillOnCreate: ({initialRecord, adminUser}) => (new Date()).toISOString(),\n },\n { \n name: 'price',\n min: 10,\n max: 10000.12,\n allowMinMaxQuery: true, // use better experience for filtering e.g. date range, set it only if you have index on this column or if there will be low number of rows\n editingNote: 'Price is in USD', // you can appear note on editing or creating page\n },\n { \n name: 'square_meter', \n label: 'Square', \n allowMinMaxQuery: true,\n minValue: 1, // you can set min /max value for number fields\n maxValue: 1000,\n },\n { \n name: 'number_of_rooms',\n allowMinMaxQuery: true,\n enum: [\n { value: 1, label: '1 room' },\n { value: 2, label: '2 rooms' },\n { value: 3, label: '3 rooms' },\n { value: 4, label: '4 rooms' },\n { value: 5, label: '5 rooms' },\n ],\n },\n { \n name: 'description',\n sortable: false,\n showIn: ['show', 'edit', 'create', 'filter'],\n },\n {\n name: 'country',\n enum: [{\n value: 'US',\n label: 'United States'\n }, {\n value: 'DE',\n label: 'Germany'\n }, {\n value: 'FR',\n label: 'France'\n }, {\n value: 'UK',\n label: 'United Kingdom'\n }, {\n value:'NL',\n label: 'Netherlands'\n }, {\n value: 'IT',\n label: 'Italy'\n }, {\n value: 'ES',\n label: 'Spain'\n }, {\n value: 'DK',\n label: 'Denmark'\n }, {\n value: 'PL',\n label: 'Poland'\n }, {\n value: 'UA',\n label: 'Ukraine'\n }, {\n value: null,\n label: 'Not defined'\n }],\n },\n {\n name: 'listed',\n required: true, // will be required on create/edit\n },\n {\n name: 'realtor_id',\n foreignResource: {\n resourceId: 'users',\n }\n }\n ],\n options: {\n listPageSize: 12,\n allowedActions:{\n edit: true,\n delete: true,\n show: true,\n filter: true,\n },\n },\n },\n { \n dataSource: 'maindb', \n table: 'users',\n resourceId: 'users',\n label: 'Users', \n recordLabel: (r) => `\ud83d\udc64 ${r.email}`,\n columns: [\n { \n name: 'id', \n primaryKey: true,\n fillOnCreate: ({initialRecord, adminUser}) => Math.random().toString(36).substring(7),\n showIn: ['list', 'filter', 'show'],\n },\n { \n name: 'email', \n required: true,\n isUnique: true,\n validation: [\n {\n regExp: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}$',\n message: 'Email is not valid, must be in format example@test.com'\n },\n ]\n },\n { \n name: 'created_at', \n type: AdminForth.Types.DATETIME,\n showIn: ['list', 'filter', 'show'],\n fillOnCreate: ({initialRecord, adminUser}) => (new Date()).toISOString(),\n },\n {\n name: 'role',\n enum: [\n { value: 'superadmin', label: 'Super Admin' },\n { value: 'user', label: 'User' },\n ]\n },\n {\n name: 'password',\n virtual: true, // field will not be persisted into db\n required: { create: true }, // make required only on create page\n editingNote: { edit: 'Leave empty to keep password unchanged' },\n minLength: 8,\n type: AdminForth.Types.STRING,\n showIn: ['create', 'edit'], // to show field only on create and edit pages\n masked: true, // to show stars in input field\n }\n ],\n hooks: {\n create: {\n beforeSave: async ({ record, adminUser, resource }) => {\n record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);\n return { ok: true };\n }\n },\n edit: {\n beforeSave: async ({ record, adminUser, resource}) => {\n if (record.password) {\n record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);\n }\n return { ok: true }\n },\n },\n }\n },\n ],\n menu: [\n {\n label: 'Core',\n icon: 'flowbite:brain-solid', // any icon from iconify supported in format :, e.g. from here https://icon-sets.iconify.design/flowbite/\n open: true,\n children: [\n {\n homepage: true,\n label: 'Appartments',\n icon: 'flowbite:home-solid',\n resourceId: 'aparts',\n },\n ]\n },\n {\n type: 'gap'\n },\n {\n type: 'divider'\n },\n {\n type: 'heading',\n label: 'SYSTEM',\n },\n {\n label: 'Users',\n icon: 'flowbite:user-solid',\n resourceId: 'users',\n }\n ],\n});\n\n\nasync function initDataBase() {\n db = betterSqlite3(DB_FILE);\n\n const tableExists = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='apartments';`).get();\n if (!tableExists) {\n // if no table - create couple of tables and fill them with some mock data\n await db.prepare(`\n CREATE TABLE apartments (\n id VARCHAR(20) PRIMARY KEY NOT NULL,\n title VARCHAR(255) NOT NULL,\n square_meter REAL,\n price DECIMAL(10, 2) NOT NULL,\n number_of_rooms INT,\n description TEXT,\n country VARCHAR(2),\n listed BOOLEAN DEFAULT FALSE,\n created_at TIMESTAMP,\n realtor_id VARCHAR(255)\n );`).run();\n\n await db.prepare(`\n CREATE TABLE users (\n id VARCHAR(255) PRIMARY KEY NOT NULL,\n email VARCHAR(255) NOT NULL,\n password_hash VARCHAR(255) NOT NULL,\n created_at VARCHAR(255) NOT NULL,\n role VARCHAR(255) NOT NULL\n );`).run();\n\n for (let i = 0; i < 100; i++) {\n await db.prepare(`\n INSERT INTO apartments (\n id, title, square_meter, price, \n number_of_rooms, description, \n created_at, listed, \n country\n ) VALUES (\n '${i}', 'Apartment ${i}', ${(Math.random() * 100).toFixed(1)}, ${(Math.random() * 10000).toFixed(2)}, \n ${ Math.floor(Math.random() * 5) }, 'Next gen apartments', \n ${ Date.now() / 1000 - Math.random() * 14 * 60 * 60 * 24 }, ${i % 2 == 0}, \n '${['US', 'DE', 'FR', 'UK', 'NL', 'IT', 'ES', 'DK', 'PL', 'UA'][Math.floor(Math.random() * 10)]}'\n )`).run();\n }\n }\n}\n\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n // if script is executed directly e.g. node index.ts or npm start\n\n await initDataBase();\n\n const app = express()\n app.use(express.json());\n const port = 3500;\n\n (async () => {\n // needed to compile SPA. Call it here or from a build script e.g. in Docker build time to reduce downtime\n await admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development'});\n console.log('Bundling AdminForth done. For faster serving consider calling bundleNow() from a build script.');\n })();\n\n\n // serve after you added all api\n admin.express.serve(app)\n admin.discoverDatabases();\n\n\n app.listen(port, () => {\n console.log(`Example app listening at http://localhost:${port}`)\n console.log(`\\n\u26a1 AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\\n`)\n });\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Now you can run your app:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"npm start\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Open ",(0,a.jsx)(n.a,{href:"http://localhost:3500",children:"http://localhost:3500"})," in your browser and login with credentials ",(0,a.jsx)(n.code,{children:"adminforth"})," / ",(0,a.jsx)(n.code,{children:"adminforth"}),"."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"alt text",src:t(8332).A+"",width:"2428",height:"1932"})}),"\n",(0,a.jsxs)(n.p,{children:["After Login you should see:\n",(0,a.jsx)(n.img,{alt:"alt text",src:t(4973).A+"",width:"3700",height:"1932"})]}),"\n",(0,a.jsx)(n.h2,{id:"possible-configuration-options",children:"Possible configuration options"}),"\n",(0,a.jsx)(n.p,{children:"We will use schema with different column types for apartments to show many of AdminForth features."}),"\n",(0,a.jsxs)(n.p,{children:["Check ",(0,a.jsx)(n.a,{href:"/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig",children:"AdminForthConfig"})," for all possible options."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8332:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/localhost_3500_login-22b59511349c51948267c9a4080e4d87.png"},4973:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/localhost_3500_resource_aparts-dddac951816a2a7b58c84b6348828ecb.png"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>o});var a=t(6540);const r={},s=a.createContext(r);function i(e){const n=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/813b1aa0.a50518e8.js b/assets/js/813b1aa0.a50518e8.js
new file mode 100644
index 000000000..5920236aa
--- /dev/null
+++ b/assets/js/813b1aa0.a50518e8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[9996],{7276:(e,n,d)=>{d.r(n),d.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var i=d(4848),t=d(8453);const a={},r=void 0,s={id:"tutorial/Plugins/AuditLog",title:"AuditLog",description:"AuditLog plugin allows to limit access to the resource actions (list, show, create, update, delete) based on custom callback.",source:"@site/docs/tutorial/Plugins/AuditLog.md",sourceDirName:"tutorial/Plugins",slug:"/tutorial/Plugins/AuditLog",permalink:"/docs/tutorial/Plugins/AuditLog",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Deploy in Docker",permalink:"/docs/tutorial/deploy"},next:{title:"ForeignInlineList",permalink:"/docs/tutorial/Plugins/ForeignInlineList"}},o={},l=[{value:"Installation",id:"installation",level:2},{value:"Creating table for storing activity data",id:"creating-table-for-storing-activity-data",level:2},{value:"Setting up the resource and dataSource for plugin",id:"setting-up-the-resource-and-datasource-for-plugin",level:2}];function c(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["AuditLog plugin allows to limit access to the resource actions (list, show, create, update, delete) based on custom callback.\nCallback accepts ",(0,i.jsx)(n.a,{href:"/docs/api/types/AdminForthConfig/type-aliases/AdminUser/",children:"AdminUser"})," which you can use to define access rules."]}),"\n",(0,i.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsx)(n.p,{children:"Plugin is already installed into adminforth, to import:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"import AuditLogPlugin from 'adminforth/plugins/AuditLogPlugin';\n"})}),"\n",(0,i.jsx)(n.p,{children:"If yu are using pure Node without TypeScript, you can use the following code:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:"import AuditLogPlugin from 'adminforth/dist/plugins/AuditLogPlugin/index.ts';\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"/docs/tutorial/gettingStarted",children:"Getting Started"})," will be used as base for this example."]}),"\n",(0,i.jsx)(n.h2,{id:"creating-table-for-storing-activity-data",children:"Creating table for storing activity data"}),"\n",(0,i.jsx)(n.p,{children:"For the first, to track records changes, we need to set up the database and table with certain fields inside where tracked data will be stored."}),"\n",(0,i.jsxs)(n.p,{children:["First of all you should create this table in your own database. In our example we will continue using SQLite database we created\nin ",(0,i.jsx)(n.a,{href:"/docs/tutorial/gettingStarted",children:"Getting Started"}),". Just add the following code to the end of ",(0,i.jsx)(n.code,{children:"initDataBase"})," function in ",(0,i.jsx)(n.code,{children:"index.ts"})," file:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",metastring:"title='./index.ts'",children:"async function initDataBase() {\n ...\n//diff-add\n const auditTableExists = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='audit_logs';`).get();\n//diff-add\n if (!auditTableExists) {\n//diff-add\n await db.prepare(`\n//diff-add\n CREATE TABLE audit_logs (\n//diff-add\n id uuid NOT NULL, -- identifier of applied change record \n//diff-add\n created_at timestamp without time zone, -- timestamp of applied change\n//diff-add\n resource_id varchar(255), -- identifier of resource where change were applied\n//diff-add\n user_id uuid, -- identifier of user who made the changes\n//diff-add\n \"action\" varchar(255), -- type of change (create, edit, delete)\n//diff-add\n diff text, -- delta betwen before/after versions\n//diff-add\n record_id varchar, -- identifier of record that been changed\n//diff-add\n PRIMARY KEY(id)\n//diff-add\n );`).run();\n//diff-add\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Also to make this code start"}),"\n",(0,i.jsx)(n.h2,{id:"setting-up-the-resource-and-datasource-for-plugin",children:"Setting up the resource and dataSource for plugin"}),"\n",(0,i.jsx)(n.p,{children:'Logger sets up for all the resources by default. But you can exclude unwanted resources with option "excludeResourceIds". In this example, we\'ll exclude resource "users" from logging.'}),"\n",(0,i.jsx)(n.p,{children:"Also, it excludes itself to avoid infinte logging loop."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",metastring:"title='./index.ts'",children:" resources: [\n ...\n//diff-add\n {\n//diff-add\n dataSource: 'maindb', \n//diff-add\n table: 'audit_logs',\n//diff-add\n columns: [\n//diff-add\n { name: 'id', primaryKey: true, required: false, fillOnCreate: ({initialRecord}: any) => uuid() },\n//diff-add\n { name: 'created_at', required: false },\n//diff-add\n { name: 'resource_id', required: false },\n//diff-add\n { name: 'user_id', required: false },\n//diff-add\n { name: 'action', required: false },\n//diff-add\n { name: 'diff', required: false },\n//diff-add\n { name: 'record_id', required: false },\n//diff-add\n ],\n//diff-add\n options: {\n//diff-add\n allowedActions: {\n//diff-add\n edit: false,\n//diff-add\n delete: false,\n//diff-add\n }\n//diff-add\n },\n//diff-add\n plugins: [\n//diff-add\n new AuditLogPlugin({\n//diff-add\n // if you want to exclude some resources from logging\n//diff-add\n //excludeResourceIds: ['users'],\n//diff-add\n resourceColumns: {\n//diff-add\n resourceIdColumnName: 'resource_id',\n//diff-add\n resourceActionColumnName: 'action',\n//diff-add\n resourceDataColumnName: 'diff',\n//diff-add\n resourceUserIdColumnName: 'user_id',\n//diff-add\n resourceRecordIdColumnName: 'record_id',\n//diff-add\n resourceCreatedColumnName: 'created_at'\n//diff-add\n }\n//diff-add\n }),\n//diff-add\n ],\n//diff-add\n }\n ]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Also, we need to add it to menu:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"menu: [\n ...\n//diff-add\n {\n//diff-add\n label: 'Audit Logs',\n//diff-add\n icon: 'flowbite:search-outline',\n//diff-add\n resourceId: 'audit_logs',\n//diff-add\n }\n]\n"})}),"\n",(0,i.jsx)(n.p,{children:"That's it! Now you can see the logs in the table"}),"\n",(0,i.jsxs)(n.p,{children:['< replace this screenshot, make same but "Audit Logs" should be in menu >\n',(0,i.jsx)(n.img,{alt:"alt text",src:d(6746).A+"",width:"3811",height:"1251"})]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions",children:"API Reference"})," for more all options."]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},6746:(e,n,d)=>{d.d(n,{A:()=>i});const i=d.p+"assets/images/localhost_3500_resource_audit_logs-8996765a6d534b48c3e52b9949e4cc89.png"},8453:(e,n,d)=>{d.d(n,{R:()=>r,x:()=>s});var i=d(6540);const t={},a=i.createContext(t);function r(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/813b1aa0.e330a24c.js b/assets/js/813b1aa0.e330a24c.js
deleted file mode 100644
index ce6401c30..000000000
--- a/assets/js/813b1aa0.e330a24c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkadminforth=self.webpackChunkadminforth||[]).push([[9996],{7276:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var i=t(4848),r=t(8453);const a={},s=void 0,o={id:"tutorial/Plugins/AuditLog",title:"AuditLog",description:"AuditLog plugin allows to limit access to the resource actions (list, show, create, update, delete) based on custom callback.",source:"@site/docs/tutorial/Plugins/AuditLog.md",sourceDirName:"tutorial/Plugins",slug:"/tutorial/Plugins/AuditLog",permalink:"/docs/tutorial/Plugins/AuditLog",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Deploy in Docker",permalink:"/docs/tutorial/deploy"},next:{title:"ForeignInlineList",permalink:"/docs/tutorial/Plugins/ForeignInlineList"}},l={},d=[{value:"Installation",id:"installation",level:2},{value:"Creating table for storing activity data",id:"creating-table-for-storing-activity-data",level:2},{value:"Setting up the resource and dataSource for plugin",id:"setting-up-the-resource-and-datasource-for-plugin",level:2}];function c(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["AuditLog plugin allows to limit access to the resource actions (list, show, create, update, delete) based on custom callback.\nCallback accepts ",(0,i.jsx)(n.a,{href:"/docs/api/types/AdminForthConfig/type-aliases/AdminUser/",children:"AdminUser"})," which you can use to define access rules."]}),"\n",(0,i.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsx)(n.p,{children:"Plugin is already installed into adminforth, to import:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"import AuditLogPlugin from 'adminforth/plugins/AuditLogPlugin';\n"})}),"\n",(0,i.jsx)(n.p,{children:"If yu are using pure Node without TypeScript, you can use the following code:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:"import AuditLogPlugin from 'adminforth/dist/plugins/AuditLogPlugin/index.ts';\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"/docs/tutorial/gettingStarted",children:"Getting Started"})," will be used as base for this example."]}),"\n",(0,i.jsx)(n.h2,{id:"creating-table-for-storing-activity-data",children:"Creating table for storing activity data"}),"\n",(0,i.jsx)(n.p,{children:"For the first, to track records changes, we need to set up the database and table with certain fields inside where tracked data will be stored."}),"\n",(0,i.jsx)(n.p,{children:"In this example, you should create this table in your own database:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:'CREATE TABLE audit_logs(\n id uuid NOT NULL, -- identifier of applied change record \n created_at timestamp without time zone, -- timestamp of applied change\n resource_id varchar(255), -- identifier of resource where change were applied\n user_id uuid, -- identifier of user who made the changes\n "action" varchar(255), -- type of change (create, edit, delete)\n diff text, -- delta betwen before/after versions\n record_id varchar, -- identifier of record that been changed\n PRIMARY KEY(id)\n);\n'})}),"\n",(0,i.jsx)(n.h2,{id:"setting-up-the-resource-and-datasource-for-plugin",children:"Setting up the resource and dataSource for plugin"}),"\n",(0,i.jsx)(n.p,{children:'Logger sets up for all the resources by default. But you can exclude unwanted resources with option "excludeResourceIds". In this example, we\'ll exclude resource "users" from logging.'}),"\n",(0,i.jsx)(n.p,{children:"Also, it excludes itself to avoid infinte logging loop."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:" dataSources: [\n ...\n {\n id: 'db2',\n url: '',\n },\n ],\n resources: [\n ...\n {\n dataSource: 'db2', table: 'audit_logs',\n columns: [\n { name: 'id', primaryKey: true, required: false, fillOnCreate: ({initialRecord}: any) => uuid() },\n { name: 'created_at', required: false },\n { name: 'resource_id', required: false },\n { name: 'user_id', required: false },\n { name: 'action', required: false },\n { name: 'diff', required: false },\n { name: 'record_id', required: false },\n ],\n options: {\n allowedActions: {\n edit: false,\n delete: false,\n }\n },\n plugins: [\n new AuditLogPlugin({\n excludeResourceIds: ['users'],\n resourceColumns: {\n resourceIdColumnName: 'resource_id',\n resourceActionColumnName: 'action',\n resourceDataColumnName: 'diff',\n resourceUserIdColumnName: 'user_id',\n resourceRecordIdColumnName: 'record_id',\n resourceCreatedColumnName: 'created_at'\n }\n }),\n ],\n }\n ]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Also, we need to add it to menu:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"{\n label: 'Logs',\n icon: 'flowbite:search-outline',\n resourceId: 'audit_logs',\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"That's it! Now you can see the logs in the table"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"alt text",src:t(6746).A+"",width:"3811",height:"1251"})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions",children:"API Reference"})," for more all options."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},6746:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/localhost_3500_resource_audit_logs-8996765a6d534b48c3e52b9949e4cc89.png"},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>o});var i=t(6540);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/runtime~main.f9ad0425.js b/assets/js/runtime~main.6a4e2ffc.js
similarity index 97%
rename from assets/js/runtime~main.f9ad0425.js
rename to assets/js/runtime~main.6a4e2ffc.js
index 9ecdd09f5..857a121be 100644
--- a/assets/js/runtime~main.f9ad0425.js
+++ b/assets/js/runtime~main.6a4e2ffc.js
@@ -1 +1 @@
-(()=>{"use strict";var e,a,f,c,d,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,c,d)=>{if(!f){var b=1/0;for(i=0;i=d)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,d0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[f,c,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var b={};a=a||[null,f({}),f([]),f(f)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(d,b),d},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({72:"325586e3",191:"096dedec",381:"485ec31e",406:"9c41ee96",594:"5e8c322a",845:"e2509f05",849:"0058b4c6",957:"c141421f",1101:"a2d8571d",1122:"ed5bf3ae",1235:"a7456010",1259:"ce9294c7",1339:"e401bd4d",1343:"695ba452",1485:"3ccf3569",1768:"0f6f7c87",1903:"acecf23e",1972:"73664a40",2138:"1a4e3797",2262:"e6fecdbd",2409:"02ba3073",2452:"d63a007d",2467:"0963d772",2560:"3b483d89",2583:"c89cbdb5",2711:"9e4087bc",2925:"857d4e3f",3212:"d4284aa7",3249:"ccc49370",3276:"e5aefb32",3403:"a74188c8",3520:"322a4173",3531:"f5a78775",3637:"f4f34a3a",3694:"8717b14a",3738:"c40bfeb3",3755:"8b12d01d",3800:"0058754d",3896:"7b6accd5",3919:"bbbca958",3925:"a4048931",3976:"bb00feff",4134:"393be207",4196:"af5821cc",4346:"f995d61e",4583:"1df93b7f",4584:"f82cd581",4813:"6875c492",5064:"fbaff884",5557:"d9f32620",5742:"aba21aa0",6061:"1f391b9e",6190:"6480425b",6352:"7bbf514f",6354:"3b4d2dbf",6507:"1bb47565",6594:"35105669",6708:"afb10fe8",6956:"322eff50",6991:"5e825ac7",7098:"a7bd4aaa",7184:"1e563bf9",7472:"814f3328",7556:"c401fedd",7643:"a6aa9e1f",7758:"bb551ae2",7865:"024de627",7930:"50bcd713",8025:"5e90a9b3",8121:"3a2db09e",8130:"f81c1134",8146:"c15d9823",8209:"01a85c17",8246:"9faee089",8266:"953f1d2e",8275:"694c912d",8401:"17896441",8462:"3217192f",8609:"925b3f96",8737:"7661071f",8830:"45d7547e",8910:"8a5469a7",9048:"a94703ab",9088:"6edf06a3",9325:"59362658",9328:"e273c56f",9647:"5e95c892",9729:"f87cbaa6",9773:"347ca734",9858:"36994c47",9873:"ca1b7bc1",9996:"813b1aa0"}[e]||e)+"."+{72:"2140e734",191:"30379ecf",381:"3b8764e1",406:"0bc9789f",416:"8fe0370d",594:"27078a25",845:"4ca4b571",849:"fa2156de",957:"534e51bb",1101:"569688b7",1122:"ce9fb296",1235:"01c51c11",1259:"f9970bc7",1339:"21be5ca2",1343:"49e6d7bb",1485:"7e6f0b85",1768:"c6cf02a5",1903:"408603ab",1972:"1dbb218a",2138:"3b9f1811",2237:"964ba571",2262:"73bb9dd1",2409:"5186eff1",2452:"705f2514",2467:"593cf592",2560:"528eda14",2583:"5aa3eaf2",2711:"594ee1b1",2925:"3bbe26c4",3212:"81d46ac2",3242:"eff6ba00",3249:"e48ced1d",3276:"074405ba",3403:"f942db12",3520:"52711a4b",3531:"dd9cc360",3637:"f878fecd",3694:"defcb0a0",3738:"d1baf258",3755:"3541dc88",3800:"5a65823b",3896:"6478b48e",3919:"13ea875d",3925:"3c625ea2",3976:"65d19b50",4134:"eb56c4bb",4196:"e4f3bb8b",4346:"79f390d6",4583:"b24c0f41",4584:"f58dc1df",4813:"6d49a07f",5064:"b7f7a2be",5557:"64356def",5742:"5b35ab57",6061:"d8686820",6190:"eed7dcce",6352:"73b26f58",6354:"f165ea6c",6507:"e54fee76",6594:"573430e0",6708:"7b643256",6956:"eac3ea2e",6991:"9f8d5c5e",7098:"1ccb7c00",7184:"d24d8c92",7472:"7b603e5e",7556:"83af0b6b",7643:"848cc9ea",7758:"1ad75dcd",7865:"8360fc62",7930:"46c0faad",8025:"eeeb6ef1",8121:"70c9a4ae",8130:"6e2c5413",8146:"3e8fd083",8209:"e63d16a5",8246:"9857c5d5",8266:"94c28e4e",8275:"f68d2bc2",8401:"50ee32b7",8462:"9a878f15",8498:"28fb9d4d",8609:"7d402955",8737:"bdcf50cf",8830:"36b76f50",8910:"8d0addb0",8913:"a57d5824",9048:"672a973b",9088:"8fb9bf65",9325:"8c339f08",9328:"2490c944",9462:"12b53926",9647:"757d1c74",9729:"e10aa3f9",9773:"9270cf4a",9858:"e2f41c0d",9873:"c5ad8a65",9996:"e330a24c"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},d="adminforth:",r.l=(e,a,f,b)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var d=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",35105669:"6594",59362658:"9325","325586e3":"72","096dedec":"191","485ec31e":"381","9c41ee96":"406","5e8c322a":"594",e2509f05:"845","0058b4c6":"849",c141421f:"957",a2d8571d:"1101",ed5bf3ae:"1122",a7456010:"1235",ce9294c7:"1259",e401bd4d:"1339","695ba452":"1343","3ccf3569":"1485","0f6f7c87":"1768",acecf23e:"1903","73664a40":"1972","1a4e3797":"2138",e6fecdbd:"2262","02ba3073":"2409",d63a007d:"2452","0963d772":"2467","3b483d89":"2560",c89cbdb5:"2583","9e4087bc":"2711","857d4e3f":"2925",d4284aa7:"3212",ccc49370:"3249",e5aefb32:"3276",a74188c8:"3403","322a4173":"3520",f5a78775:"3531",f4f34a3a:"3637","8717b14a":"3694",c40bfeb3:"3738","8b12d01d":"3755","0058754d":"3800","7b6accd5":"3896",bbbca958:"3919",a4048931:"3925",bb00feff:"3976","393be207":"4134",af5821cc:"4196",f995d61e:"4346","1df93b7f":"4583",f82cd581:"4584","6875c492":"4813",fbaff884:"5064",d9f32620:"5557",aba21aa0:"5742","1f391b9e":"6061","6480425b":"6190","7bbf514f":"6352","3b4d2dbf":"6354","1bb47565":"6507",afb10fe8:"6708","322eff50":"6956","5e825ac7":"6991",a7bd4aaa:"7098","1e563bf9":"7184","814f3328":"7472",c401fedd:"7556",a6aa9e1f:"7643",bb551ae2:"7758","024de627":"7865","50bcd713":"7930","5e90a9b3":"8025","3a2db09e":"8121",f81c1134:"8130",c15d9823:"8146","01a85c17":"8209","9faee089":"8246","953f1d2e":"8266","694c912d":"8275","3217192f":"8462","925b3f96":"8609","7661071f":"8737","45d7547e":"8830","8a5469a7":"8910",a94703ab:"9048","6edf06a3":"9088",e273c56f:"9328","5e95c892":"9647",f87cbaa6:"9729","347ca734":"9773","36994c47":"9858",ca1b7bc1:"9873","813b1aa0":"9996"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,f)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var d=new Promise(((f,d)=>c=e[a]=[f,d]));f.push(c[2]=d);var b=r.p+r.u(a),t=new Error;r.l(b,(f=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var d=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+b+")",t.name="ChunkLoadError",t.type=d,t.request=b,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var c,d,b=f[0],t=f[1],o=f[2],n=0;if(b.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(f);n{"use strict";var e,a,f,c,d,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,c,d)=>{if(!f){var b=1/0;for(i=0;i=d)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,d0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[f,c,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var b={};a=a||[null,f({}),f([]),f(f)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(d,b),d},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({72:"325586e3",191:"096dedec",381:"485ec31e",406:"9c41ee96",594:"5e8c322a",845:"e2509f05",849:"0058b4c6",957:"c141421f",1101:"a2d8571d",1122:"ed5bf3ae",1235:"a7456010",1259:"ce9294c7",1339:"e401bd4d",1343:"695ba452",1485:"3ccf3569",1768:"0f6f7c87",1903:"acecf23e",1972:"73664a40",2138:"1a4e3797",2262:"e6fecdbd",2409:"02ba3073",2452:"d63a007d",2467:"0963d772",2560:"3b483d89",2583:"c89cbdb5",2711:"9e4087bc",2925:"857d4e3f",3212:"d4284aa7",3249:"ccc49370",3276:"e5aefb32",3403:"a74188c8",3520:"322a4173",3531:"f5a78775",3637:"f4f34a3a",3694:"8717b14a",3738:"c40bfeb3",3755:"8b12d01d",3800:"0058754d",3896:"7b6accd5",3919:"bbbca958",3925:"a4048931",3976:"bb00feff",4134:"393be207",4196:"af5821cc",4346:"f995d61e",4583:"1df93b7f",4584:"f82cd581",4813:"6875c492",5064:"fbaff884",5557:"d9f32620",5742:"aba21aa0",6061:"1f391b9e",6190:"6480425b",6352:"7bbf514f",6354:"3b4d2dbf",6507:"1bb47565",6594:"35105669",6708:"afb10fe8",6956:"322eff50",6991:"5e825ac7",7098:"a7bd4aaa",7184:"1e563bf9",7472:"814f3328",7556:"c401fedd",7643:"a6aa9e1f",7758:"bb551ae2",7865:"024de627",7930:"50bcd713",8025:"5e90a9b3",8121:"3a2db09e",8130:"f81c1134",8146:"c15d9823",8209:"01a85c17",8246:"9faee089",8266:"953f1d2e",8275:"694c912d",8401:"17896441",8462:"3217192f",8609:"925b3f96",8737:"7661071f",8830:"45d7547e",8910:"8a5469a7",9048:"a94703ab",9088:"6edf06a3",9325:"59362658",9328:"e273c56f",9647:"5e95c892",9729:"f87cbaa6",9773:"347ca734",9858:"36994c47",9873:"ca1b7bc1",9996:"813b1aa0"}[e]||e)+"."+{72:"2140e734",191:"30379ecf",381:"3b8764e1",406:"0bc9789f",416:"8fe0370d",594:"27078a25",845:"4ca4b571",849:"fa2156de",957:"534e51bb",1101:"569688b7",1122:"ce9fb296",1235:"01c51c11",1259:"f9970bc7",1339:"21be5ca2",1343:"49e6d7bb",1485:"7e6f0b85",1768:"c6cf02a5",1903:"408603ab",1972:"1dbb218a",2138:"3b9f1811",2237:"964ba571",2262:"73bb9dd1",2409:"5186eff1",2452:"705f2514",2467:"593cf592",2560:"528eda14",2583:"5aa3eaf2",2711:"594ee1b1",2925:"3bbe26c4",3212:"81d46ac2",3242:"eff6ba00",3249:"e48ced1d",3276:"074405ba",3403:"f942db12",3520:"52711a4b",3531:"dd9cc360",3637:"f878fecd",3694:"defcb0a0",3738:"d1baf258",3755:"3541dc88",3800:"0dc70dcf",3896:"6478b48e",3919:"13ea875d",3925:"3c625ea2",3976:"65d19b50",4134:"eb56c4bb",4196:"e4f3bb8b",4346:"79f390d6",4583:"b24c0f41",4584:"f58dc1df",4813:"6d49a07f",5064:"b7f7a2be",5557:"64356def",5742:"5b35ab57",6061:"d8686820",6190:"eed7dcce",6352:"73b26f58",6354:"f165ea6c",6507:"e54fee76",6594:"573430e0",6708:"7b643256",6956:"fe38aa95",6991:"9f8d5c5e",7098:"1ccb7c00",7184:"d24d8c92",7472:"7b603e5e",7556:"83af0b6b",7643:"848cc9ea",7758:"1ad75dcd",7865:"8360fc62",7930:"46c0faad",8025:"eeeb6ef1",8121:"70c9a4ae",8130:"6e2c5413",8146:"3e8fd083",8209:"e63d16a5",8246:"9857c5d5",8266:"94c28e4e",8275:"f68d2bc2",8401:"50ee32b7",8462:"9a878f15",8498:"28fb9d4d",8609:"7d402955",8737:"bdcf50cf",8830:"36b76f50",8910:"8d0addb0",8913:"a57d5824",9048:"672a973b",9088:"8fb9bf65",9325:"8c339f08",9328:"2490c944",9462:"12b53926",9647:"757d1c74",9729:"e10aa3f9",9773:"9270cf4a",9858:"e2f41c0d",9873:"c5ad8a65",9996:"a50518e8"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},d="adminforth:",r.l=(e,a,f,b)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var d=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",35105669:"6594",59362658:"9325","325586e3":"72","096dedec":"191","485ec31e":"381","9c41ee96":"406","5e8c322a":"594",e2509f05:"845","0058b4c6":"849",c141421f:"957",a2d8571d:"1101",ed5bf3ae:"1122",a7456010:"1235",ce9294c7:"1259",e401bd4d:"1339","695ba452":"1343","3ccf3569":"1485","0f6f7c87":"1768",acecf23e:"1903","73664a40":"1972","1a4e3797":"2138",e6fecdbd:"2262","02ba3073":"2409",d63a007d:"2452","0963d772":"2467","3b483d89":"2560",c89cbdb5:"2583","9e4087bc":"2711","857d4e3f":"2925",d4284aa7:"3212",ccc49370:"3249",e5aefb32:"3276",a74188c8:"3403","322a4173":"3520",f5a78775:"3531",f4f34a3a:"3637","8717b14a":"3694",c40bfeb3:"3738","8b12d01d":"3755","0058754d":"3800","7b6accd5":"3896",bbbca958:"3919",a4048931:"3925",bb00feff:"3976","393be207":"4134",af5821cc:"4196",f995d61e:"4346","1df93b7f":"4583",f82cd581:"4584","6875c492":"4813",fbaff884:"5064",d9f32620:"5557",aba21aa0:"5742","1f391b9e":"6061","6480425b":"6190","7bbf514f":"6352","3b4d2dbf":"6354","1bb47565":"6507",afb10fe8:"6708","322eff50":"6956","5e825ac7":"6991",a7bd4aaa:"7098","1e563bf9":"7184","814f3328":"7472",c401fedd:"7556",a6aa9e1f:"7643",bb551ae2:"7758","024de627":"7865","50bcd713":"7930","5e90a9b3":"8025","3a2db09e":"8121",f81c1134:"8130",c15d9823:"8146","01a85c17":"8209","9faee089":"8246","953f1d2e":"8266","694c912d":"8275","3217192f":"8462","925b3f96":"8609","7661071f":"8737","45d7547e":"8830","8a5469a7":"8910",a94703ab:"9048","6edf06a3":"9088",e273c56f:"9328","5e95c892":"9647",f87cbaa6:"9729","347ca734":"9773","36994c47":"9858",ca1b7bc1:"9873","813b1aa0":"9996"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,f)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var d=new Promise(((f,d)=>c=e[a]=[f,d]));f.push(c[2]=d);var b=r.p+r.u(a),t=new Error;r.l(b,(f=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var d=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+b+")",t.name="ChunkLoadError",t.type=d,t.request=b,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var c,d,b=f[0],t=f[1],o=f[2],n=0;if(b.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(f);n
-
+
diff --git a/blog/first-blog-post/index.html b/blog/first-blog-post/index.html
index 654a8967d..379cf3701 100644
--- a/blog/first-blog-post/index.html
+++ b/blog/first-blog-post/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/index.html b/blog/index.html
index 35a4c783f..14e05c386 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/long-blog-post/index.html b/blog/long-blog-post/index.html
index ded8e81ec..b4103ad0f 100644
--- a/blog/long-blog-post/index.html
+++ b/blog/long-blog-post/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/mdx-blog-post/index.html b/blog/mdx-blog-post/index.html
index 06e5544ec..32c9ad7ab 100644
--- a/blog/mdx-blog-post/index.html
+++ b/blog/mdx-blog-post/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/tags/docusaurus/index.html b/blog/tags/docusaurus/index.html
index c0b1a9edc..e48ed5748 100644
--- a/blog/tags/docusaurus/index.html
+++ b/blog/tags/docusaurus/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/tags/facebook/index.html b/blog/tags/facebook/index.html
index dd27a0c52..c67842c48 100644
--- a/blog/tags/facebook/index.html
+++ b/blog/tags/facebook/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/tags/hello/index.html b/blog/tags/hello/index.html
index 08ffa0b92..cbba98f8a 100644
--- a/blog/tags/hello/index.html
+++ b/blog/tags/hello/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/tags/hola/index.html b/blog/tags/hola/index.html
index 386936c5c..35082c242 100644
--- a/blog/tags/hola/index.html
+++ b/blog/tags/hola/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/tags/index.html b/blog/tags/index.html
index ac661cdcf..37b5a8164 100644
--- a/blog/tags/index.html
+++ b/blog/tags/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/welcome/index.html b/blog/welcome/index.html
index 2c38aa897..dd388f448 100644
--- a/blog/welcome/index.html
+++ b/blog/welcome/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/index.html b/docs/api/index.html
index 6ef3f8d75..7cefe9fad 100644
--- a/docs/api/index.html
+++ b/docs/api/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/plugins/AuditLogPlugin/types/index.html b/docs/api/plugins/AuditLogPlugin/types/index.html
index 1d3380cae..66866b522 100644
--- a/docs/api/plugins/AuditLogPlugin/types/index.html
+++ b/docs/api/plugins/AuditLogPlugin/types/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions/index.html b/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions/index.html
index 7a6fa6c05..b6cd4153a 100644
--- a/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions/index.html
+++ b/docs/api/plugins/AuditLogPlugin/types/type-aliases/PluginOptions/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/plugins/ForeignInlineListPlugin/types/index.html b/docs/api/plugins/ForeignInlineListPlugin/types/index.html
index a2ffbabc3..fc11749f7 100644
--- a/docs/api/plugins/ForeignInlineListPlugin/types/index.html
+++ b/docs/api/plugins/ForeignInlineListPlugin/types/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions/index.html b/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions/index.html
index 72f36fe4a..2d00a3dbc 100644
--- a/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions/index.html
+++ b/docs/api/plugins/ForeignInlineListPlugin/types/type-aliases/PluginOptions/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/ActionCheckSource/index.html b/docs/api/types/AdminForthConfig/enumerations/ActionCheckSource/index.html
index d4c01906d..ab0e2d86c 100644
--- a/docs/api/types/AdminForthConfig/enumerations/ActionCheckSource/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/ActionCheckSource/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AdminForthDataTypes/index.html b/docs/api/types/AdminForthConfig/enumerations/AdminForthDataTypes/index.html
index f50daacf4..b913d87b6 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AdminForthDataTypes/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AdminForthDataTypes/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AdminForthFilterOperators/index.html b/docs/api/types/AdminForthConfig/enumerations/AdminForthFilterOperators/index.html
index 26a86c22f..d100c2a27 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AdminForthFilterOperators/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AdminForthFilterOperators/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AdminForthMenuTypes/index.html b/docs/api/types/AdminForthConfig/enumerations/AdminForthMenuTypes/index.html
index 247b4fe71..0376c2c51 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AdminForthMenuTypes/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AdminForthMenuTypes/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AdminForthResourcePages/index.html b/docs/api/types/AdminForthConfig/enumerations/AdminForthResourcePages/index.html
index dca735907..310b56f98 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AdminForthResourcePages/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AdminForthResourcePages/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AdminForthSortDirections/index.html b/docs/api/types/AdminForthConfig/enumerations/AdminForthSortDirections/index.html
index 27c40136f..2972a9660 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AdminForthSortDirections/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AdminForthSortDirections/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/enumerations/AllowedActionsEnum/index.html b/docs/api/types/AdminForthConfig/enumerations/AllowedActionsEnum/index.html
index d3480223d..19e02f2a4 100644
--- a/docs/api/types/AdminForthConfig/enumerations/AllowedActionsEnum/index.html
+++ b/docs/api/types/AdminForthConfig/enumerations/AllowedActionsEnum/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/index.html b/docs/api/types/AdminForthConfig/index.html
index 7ba21e766..b0fb002f8 100644
--- a/docs/api/types/AdminForthConfig/index.html
+++ b/docs/api/types/AdminForthConfig/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/AdminForthClass/index.html b/docs/api/types/AdminForthConfig/interfaces/AdminForthClass/index.html
index 213c6bc4c..e9ef02433 100644
--- a/docs/api/types/AdminForthConfig/interfaces/AdminForthClass/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/AdminForthClass/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnector/index.html b/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnector/index.html
index 06e547444..49251c690 100644
--- a/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnector/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnector/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnectorConstructor/index.html b/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnectorConstructor/index.html
index 3fcd6d5dc..feb01333f 100644
--- a/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnectorConstructor/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/AdminForthDataSourceConnectorConstructor/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/AdminForthPluginType/index.html b/docs/api/types/AdminForthConfig/interfaces/AdminForthPluginType/index.html
index 7d5249e26..294a15c34 100644
--- a/docs/api/types/AdminForthConfig/interfaces/AdminForthPluginType/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/AdminForthPluginType/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/CodeInjectorType/index.html b/docs/api/types/AdminForthConfig/interfaces/CodeInjectorType/index.html
index a2e5e818d..15a5a0727 100644
--- a/docs/api/types/AdminForthConfig/interfaces/CodeInjectorType/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/CodeInjectorType/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/ExpressHttpServer/index.html b/docs/api/types/AdminForthConfig/interfaces/ExpressHttpServer/index.html
index e8acfceda..09c39bf7e 100644
--- a/docs/api/types/AdminForthConfig/interfaces/ExpressHttpServer/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/ExpressHttpServer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/interfaces/GenericHttpServer/index.html b/docs/api/types/AdminForthConfig/interfaces/GenericHttpServer/index.html
index 1b13bd341..a17bf6a0b 100644
--- a/docs/api/types/AdminForthConfig/interfaces/GenericHttpServer/index.html
+++ b/docs/api/types/AdminForthConfig/interfaces/GenericHttpServer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthColumnEnumItem/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthColumnEnumItem/index.html
index 834a86c03..15da90b52 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthColumnEnumItem/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthColumnEnumItem/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclaration/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclaration/index.html
index b2c4f17bc..e54c25f41 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclaration/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclaration/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclarationFull/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclarationFull/index.html
index 01acaa76f..5a225ba19 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclarationFull/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthComponentDeclarationFull/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig/index.html
index 3cf8a2039..adcf9a046 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfig/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfigMenuItem/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfigMenuItem/index.html
index ec27b1b28..0589ec8f5 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfigMenuItem/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthConfigMenuItem/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthDataSource/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthDataSource/index.html
index bcb59c66a..7430daf3e 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthDataSource/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthDataSource/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthFieldComponents/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthFieldComponents/index.html
index e198fbd8b..703af6fa1 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthFieldComponents/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthFieldComponents/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthForeignResource/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthForeignResource/index.html
index f89a4fdfa..04b0fe0e7 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthForeignResource/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthForeignResource/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthResource/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthResource/index.html
index cf02196bc..9ee323833 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthResource/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthResource/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminForthResourceColumn/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminForthResourceColumn/index.html
index 68a2e2d4e..f63c952b1 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminForthResourceColumn/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminForthResourceColumn/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AdminUser/index.html b/docs/api/types/AdminForthConfig/type-aliases/AdminUser/index.html
index b836d76fe..b70949c8a 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AdminUser/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AdminUser/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AfterDataSourceResponseFunction/index.html b/docs/api/types/AdminForthConfig/type-aliases/AfterDataSourceResponseFunction/index.html
index d448012d6..0ff297b17 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AfterDataSourceResponseFunction/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AfterDataSourceResponseFunction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AfterSaveFunction/index.html b/docs/api/types/AdminForthConfig/type-aliases/AfterSaveFunction/index.html
index 70d6fa7c6..d959418b8 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AfterSaveFunction/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AfterSaveFunction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AllowedActionValue/index.html b/docs/api/types/AdminForthConfig/type-aliases/AllowedActionValue/index.html
index 91951d32b..89f51eccb 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AllowedActionValue/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AllowedActionValue/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/AllowedActions/index.html b/docs/api/types/AdminForthConfig/type-aliases/AllowedActions/index.html
index cad7db959..cddee0ecf 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/AllowedActions/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/AllowedActions/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/BeforeDataSourceRequestFunction/index.html b/docs/api/types/AdminForthConfig/type-aliases/BeforeDataSourceRequestFunction/index.html
index d3df1b6ff..2a5fee835 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/BeforeDataSourceRequestFunction/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/BeforeDataSourceRequestFunction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/BeforeSaveFunction/index.html b/docs/api/types/AdminForthConfig/type-aliases/BeforeSaveFunction/index.html
index a13804263..cb3583141 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/BeforeSaveFunction/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/BeforeSaveFunction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/AdminForthConfig/type-aliases/ValidationObject/index.html b/docs/api/types/AdminForthConfig/type-aliases/ValidationObject/index.html
index 4bf0019cf..7526abf57 100644
--- a/docs/api/types/AdminForthConfig/type-aliases/ValidationObject/index.html
+++ b/docs/api/types/AdminForthConfig/type-aliases/ValidationObject/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/FrontendAPI/enumerations/AlertVariant/index.html b/docs/api/types/FrontendAPI/enumerations/AlertVariant/index.html
index a87948049..7c4051833 100644
--- a/docs/api/types/FrontendAPI/enumerations/AlertVariant/index.html
+++ b/docs/api/types/FrontendAPI/enumerations/AlertVariant/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/FrontendAPI/index.html b/docs/api/types/FrontendAPI/index.html
index 0f57c884c..df37e989b 100644
--- a/docs/api/types/FrontendAPI/index.html
+++ b/docs/api/types/FrontendAPI/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/FrontendAPI/interfaces/FrontendAPIInterface/index.html b/docs/api/types/FrontendAPI/interfaces/FrontendAPIInterface/index.html
index ede55d994..5b50b7c09 100644
--- a/docs/api/types/FrontendAPI/interfaces/FrontendAPIInterface/index.html
+++ b/docs/api/types/FrontendAPI/interfaces/FrontendAPIInterface/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/FrontendAPI/type-aliases/AlertParams/index.html b/docs/api/types/FrontendAPI/type-aliases/AlertParams/index.html
index 32c74b9d5..3c6d68b4d 100644
--- a/docs/api/types/FrontendAPI/type-aliases/AlertParams/index.html
+++ b/docs/api/types/FrontendAPI/type-aliases/AlertParams/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/api/types/FrontendAPI/type-aliases/ConfirmParams/index.html b/docs/api/types/FrontendAPI/type-aliases/ConfirmParams/index.html
index 47a202a0e..4f17c2d4c 100644
--- a/docs/api/types/FrontendAPI/type-aliases/ConfirmParams/index.html
+++ b/docs/api/types/FrontendAPI/type-aliases/ConfirmParams/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/alert/index.html b/docs/tutorial/Customization/alert/index.html
index cf4884bcd..742f64a4d 100644
--- a/docs/tutorial/Customization/alert/index.html
+++ b/docs/tutorial/Customization/alert/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/branding/index.html b/docs/tutorial/Customization/branding/index.html
index 6db764a37..bbbb7f138 100644
--- a/docs/tutorial/Customization/branding/index.html
+++ b/docs/tutorial/Customization/branding/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/bulkActions/index.html b/docs/tutorial/Customization/bulkActions/index.html
index 97aecd46a..f05a03cf3 100644
--- a/docs/tutorial/Customization/bulkActions/index.html
+++ b/docs/tutorial/Customization/bulkActions/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/customFieldRendering/index.html b/docs/tutorial/Customization/customFieldRendering/index.html
index b104c87f7..ff775cc02 100644
--- a/docs/tutorial/Customization/customFieldRendering/index.html
+++ b/docs/tutorial/Customization/customFieldRendering/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/customPages/index.html b/docs/tutorial/Customization/customPages/index.html
index fa006cd1c..7f9f8ae9c 100644
--- a/docs/tutorial/Customization/customPages/index.html
+++ b/docs/tutorial/Customization/customPages/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/hooks/index.html b/docs/tutorial/Customization/hooks/index.html
index ccf048a75..ceb71e984 100644
--- a/docs/tutorial/Customization/hooks/index.html
+++ b/docs/tutorial/Customization/hooks/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/limitingAccess/index.html b/docs/tutorial/Customization/limitingAccess/index.html
index 0cd68be7b..3facb668d 100644
--- a/docs/tutorial/Customization/limitingAccess/index.html
+++ b/docs/tutorial/Customization/limitingAccess/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/pageInjections/index.html b/docs/tutorial/Customization/pageInjections/index.html
index 38b274077..c50f72960 100644
--- a/docs/tutorial/Customization/pageInjections/index.html
+++ b/docs/tutorial/Customization/pageInjections/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Customization/virtualColumns/index.html b/docs/tutorial/Customization/virtualColumns/index.html
index 8fa88cc3b..300363fc6 100644
--- a/docs/tutorial/Customization/virtualColumns/index.html
+++ b/docs/tutorial/Customization/virtualColumns/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/tutorial/Plugins/AuditLog/index.html b/docs/tutorial/Plugins/AuditLog/index.html
index dbed20555..c003ee82e 100644
--- a/docs/tutorial/Plugins/AuditLog/index.html
+++ b/docs/tutorial/Plugins/AuditLog/index.html
@@ -13,7 +13,7 @@
-
+
@@ -27,16 +27,19 @@
InstallationGetting Started will be used as base for this example.
For the first, to track records changes, we need to set up the database and table with certain fields inside where tracked data will be stored.
-
In this example, you should create this table in your own database:
-
CREATETABLE audit_logs( id uuid NOTNULL,-- identifier of applied change record created_at timestamp without time zone,-- timestamp of applied change resource_id varchar(255),-- identifier of resource where change were applied user_id uuid,-- identifier of user who made the changes "action"varchar(255),-- type of change (create, edit, delete) diff text,-- delta betwen before/after versions record_id varchar,-- identifier of record that been changed PRIMARYKEY(id) );
+
First of all you should create this table in your own database. In our example we will continue using SQLite database we created
+in Getting Started. Just add the following code to the end of initDataBase function in index.ts file:
+
./index.ts
asyncfunctioninitDataBase(){ ... const auditTableExists = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='audit_logs';`).get(); if(!auditTableExists){ await db.prepare(` CREATE TABLE audit_logs ( id uuid NOT NULL, -- identifier of applied change record created_at timestamp without time zone, -- timestamp of applied change resource_id varchar(255), -- identifier of resource where change were applied user_id uuid, -- identifier of user who made the changes "action" varchar(255), -- type of change (create, edit, delete) diff text, -- delta betwen before/after versions record_id varchar, -- identifier of record that been changed PRIMARY KEY(id) );`).run(); } }
+
Also to make this code start
Setting up the resource and dataSource for plugin
Logger sets up for all the resources by default. But you can exclude unwanted resources with option "excludeResourceIds". In this example, we'll exclude resource "users" from logging.
Also, it excludes itself to avoid infinte logging loop.