Skip to content

Commit 055cbd7

Browse files
authored
Merge pull request #315 from devforth/next
Next
2 parents 7b88fdb + fc32967 commit 055cbd7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2619
-483
lines changed

adminforth/commands/createApp/templates/index.ts.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import AdminForth from 'adminforth';
33
import usersResource from "./resources/adminuser.js";
44
import { fileURLToPath } from 'url';
55
import path from 'path';
6+
import { Filters } from 'adminforth';
67

78
const ADMIN_BASE_URL = '';
89

@@ -15,6 +16,12 @@ export const admin = new AdminForth({
1516
rememberMeDays: 30,
1617
loginBackgroundImage: 'https://images.unsplash.com/photo-1534239697798-120952b76f2b?q=80&w=3389&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
1718
loginBackgroundPosition: '1/2',
19+
loginPromptHTML: async () => {
20+
const adminforthUserExists = await admin.resource("adminuser").count(Filters.EQ('email', 'adminforth')) > 0;
21+
if (adminforthUserExists) {
22+
return "Please use <b>adminforth</b> as username and <b>adminforth</b> as password"
23+
}
24+
},
1825
},
1926
customization: {
2027
brandName: "{{appName}}",

adminforth/commands/createCustomComponent/configLoader.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import fs from 'fs/promises';
22
import path from 'path';
33
import chalk from 'chalk';
44
import jiti from 'jiti';
5+
import dotenv from "dotenv";
56

7+
dotenv.config({ path: '.env.local', override: true });
8+
dotenv.config({ path: '.env', override: true });
69

710
export async function loadAdminForthConfig() {
811
const configFileName = 'index.ts';

adminforth/dataConnectors/baseConnector.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,23 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
114114
const fieldObj = resource.dataSourceColumns.find((col) => col.name == (filters as IAdminForthSingleFilter).field);
115115
if (!fieldObj) {
116116
const similar = suggestIfTypo(resource.dataSourceColumns.map((col) => col.name), (filters as IAdminForthSingleFilter).field);
117-
throw new Error(`Field '${(filters as IAdminForthSingleFilter).field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
117+
118+
let isPolymorphicTarget = false;
119+
if (global.adminforth?.config?.resources) {
120+
isPolymorphicTarget = global.adminforth.config.resources.some(res =>
121+
res.dataSourceColumns.some(col =>
122+
col.foreignResource?.polymorphicResources?.some(pr =>
123+
pr.resourceId === resource.resourceId
124+
)
125+
)
126+
);
127+
}
128+
if (isPolymorphicTarget) {
129+
process.env.HEAVY_DEBUG && console.log(`⚠️ Field '${(filters as IAdminForthSingleFilter).field}' not found in polymorphic target resource '${resource.resourceId}', allowing query to proceed.`);
130+
return { ok: true, error: '' };
131+
} else {
132+
throw new Error(`Field '${(filters as IAdminForthSingleFilter).field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
133+
}
118134
}
119135
// value normalization
120136
if (filters.operator == AdminForthFilterOperators.IN || filters.operator == AdminForthFilterOperators.NIN) {

adminforth/dataConnectors/mongo.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
6969
return Number.isInteger(value) ? 'integer' : 'float';
7070
}
7171
if (value instanceof Date) return 'datetime';
72+
if (value && typeof value === 'object' && ('$numberDecimal' in value || value._bsontype === 'Decimal128')) return 'decimal';
7273
if (typeof value === 'object') return 'json';
7374
return 'string';
7475
}
@@ -89,13 +90,18 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
8990
sampleValues.set(fullKey, value);
9091
}
9192

92-
if (
93-
value instanceof Buffer ||
94-
(value && typeof value === 'object' && (value as any)._bsontype === 'Decimal128')
95-
) {
93+
if (value instanceof Buffer) {
9694
addType(fullKey, 'json');
9795
return;
9896
}
97+
if (
98+
value &&
99+
typeof value === 'object' &&
100+
('$numberDecimal' in value || (value as any)._bsontype === 'Decimal128')
101+
) {
102+
addType(fullKey, 'decimal');
103+
return;
104+
}
99105

100106
if (
101107
value &&
@@ -104,9 +110,10 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
104110
!(value instanceof Date)
105111
) {
106112
addType(fullKey, 'json');
107-
} else {
108-
addType(fullKey, detectType(value));
113+
return
109114
}
115+
116+
addType(fullKey, detectType(value));
110117
});
111118
}
112119

@@ -117,7 +124,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
117124
return Array.from(fieldTypes.entries()).map(([name, types]) => {
118125
const primaryKey = name === '_id';
119126

120-
const priority = ['datetime', 'date', 'integer', 'float', 'boolean', 'json', 'string'];
127+
const priority = ['datetime', 'date', 'integer', 'float', 'boolean', 'json', 'decimal', 'string'];
121128

122129
const matched = priority.find(t => types.has(t)) || 'string';
123130

@@ -129,8 +136,8 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
129136
datetime: 'DATETIME',
130137
date: 'DATE',
131138
json: 'JSON',
139+
decimal: 'DECIMAL',
132140
};
133-
134141
return {
135142
name,
136143
type: typeMap[matched] ?? 'STRING',

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ model ContentImage {
199199
Create a migration:
200200

201201
```bash
202-
npm run makemigration -- --name add-posts && npm run migrate:local
202+
npm run makemigration -- --name add-posts ; npm run migrate:local
203203
```
204204

205205

adminforth/documentation/docs/tutorial/001-gettingStarted.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ This will create a migration file in `migrations` and apply it to the database.
8989
In future, when you need to add new resources, you need to modify `schema.prisma` (add models, change fields, etc.). After doing any modification you need to create a new migration using next command:
9090

9191
```bash
92-
npm run makemigration -- --name init && npm run migrate:local
92+
npm run makemigration -- --name init ; npm run migrate:local
9393
```
9494

9595
Other developers need to pull migration and run `npm run migrateLocal` to apply any unapplied migrations.
@@ -173,7 +173,7 @@ model apartments {
173173
Run the following command to create a new migration:
174174

175175
```bash
176-
npm run makemigration -- --name add-apartments && npm run migrate:local
176+
npm run makemigration -- --name add-apartments ; npm run migrate:local
177177
```
178178

179179
### Step3. Create the `apartments` resource
@@ -292,6 +292,7 @@ export default {
292292
name: 'realtor_id',
293293
foreignResource: {
294294
resourceId: 'adminuser',
295+
searchableFields: ["id", "email"], // fields available for search in filter
295296
}
296297
}
297298
],

adminforth/documentation/docs/tutorial/01-helloWorld.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ model Post {
122122
Create database using `prisma migrate`:
123123

124124
```bash
125-
npm run makemigration --name init && npm run migrate:local
125+
npm run makemigration --name init ; npm run migrate:local
126126
```
127127

128128
## Setting up AdminForth

adminforth/documentation/docs/tutorial/03-Customization/01-branding.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,26 @@ const admin = new AdminForth({
9494
Here is how it looks:
9595
![AdminForth Themes](image-10.png)
9696

97+
## Single theme
98+
99+
If you want to enforce a consistent theme and disable the theme switcher, you can configure AdminForth to use only one theme variant.
100+
101+
```ts title='./index.ts'
102+
103+
const admin = new AdminForth({
104+
...
105+
customization: {
106+
//diff-add
107+
singleTheme: "light",
108+
styles: {
109+
...
110+
}
111+
}
112+
},
113+
...
114+
});
115+
```
116+
97117

98118
## Square vs rounded buttons?
99119

@@ -149,4 +169,52 @@ auth: {
149169
`loginBackgroundPosition` accepts values:
150170

151171
- `over` - image will be over the whole login page with cover mode
152-
- `1/2`(default), `3/4`, `2/5`, `3/5` etc. - image will be in the left side of the login page with cover mode
172+
- `1/2`(default), `3/4`, `2/5`, `3/5` etc. - image will be in the left side of the login page with cover mode
173+
174+
### Disabling background blend mode
175+
176+
When using `loginBackgroundPosition: 'over'`, AdminForth applies a background blend mode by default to ensure text readability over the background image. If you want to disable this blend mode and display the background image without any overlay effects, you can add:
177+
178+
```ts title='./index.ts'
179+
auth: {
180+
...
181+
loginBackgroundImage: '@@/photo-1516501312919-d0cb0b7b60b8.jpeg',
182+
loginBackgroundPosition: 'over',
183+
//diff-add
184+
removeBackgroundBlendMode: true,
185+
}
186+
187+
```
188+
189+
## Custom items in html head
190+
191+
If you want to add custom elements to the HTML head, you can define them in the configuration:
192+
193+
```ts title='./index.ts'
194+
customization: {
195+
customHeadItems: [
196+
{
197+
tagName: 'link',
198+
attributes: {
199+
rel: 'stylesheet',
200+
href: 'https://example.com/custom.css'
201+
}
202+
},
203+
{
204+
tagName: 'script',
205+
attributes: {
206+
src: 'https://example.com/custom.js',
207+
defer: true
208+
}
209+
},
210+
{
211+
tagName: 'meta',
212+
attributes: {
213+
name: 'theme-color',
214+
content: ' #000000'
215+
}
216+
}
217+
]
218+
}
219+
220+
```

adminforth/documentation/docs/tutorial/03-Customization/02-customFieldRendering.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ const props = defineProps<{
194194
meta: any;
195195
resource: AdminForthResourceCommon;
196196
adminUser: AdminUser;
197+
readonly: boolean;
197198
}>();
198199
199200
const emit = defineEmits(["update:value"]);

adminforth/documentation/docs/tutorial/03-Customization/03-virtualColumns.md

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,4 @@ Hook still has access to the virtual field `updates.password`, and we use built-
235235
After hook is executed, `updates.password` will be removed from the record since it is virtual, so password itself will not be saved to the database.
236236
237237
238-
### Backend-only fields
239-
240-
Another important point is that `hashed_password` field should never be passed to frontend due to security reasons.
241-
242-
To do it we have 2 options:
243-
244-
1) Do not list `password_hash` in the `columns` array of the resource. If AdminForth knows nothing about field
245-
it will never pass this field to frontend.
246-
2) Define `password_hash` in columns way but set `backendOnly`. The scond option is more explicit and should be preferrred
247-
248-
```ts
249-
{
250-
name: 'password_hash',
251-
type: AdminForthDataTypes.STRING,
252-
showIn: { all: false },
253-
backendOnly: true, // will never go to frontend
254-
}
255-
```
238+

0 commit comments

Comments
 (0)