Skip to content

Commit 988dfc0

Browse files
committed
Merge branch 'next' of github.com:devforth/adminforth into inline-create
2 parents de887f4 + ca48854 commit 988dfc0

File tree

29 files changed

+552
-258
lines changed

29 files changed

+552
-258
lines changed

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import AdminForth, { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
1+
import AdminForth, { AdminForthDataTypes, AdminForthResourceInput, AdminForthResource, AdminUser } from 'adminforth';
2+
23
import type { AdminUser } from 'adminforth';
34

45
async function canModifyUsers({ adminUser }: { adminUser: AdminUser }): Promise<boolean> {
@@ -86,18 +87,19 @@ export default {
8687
],
8788
hooks: {
8889
create: {
89-
beforeSave: async ({ record, adminUser, resource }) => {
90-
record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);
90+
beforeSave: async ({ record, adminUser, resource }: { record: any, adminUser: AdminUser, resource: AdminForthResource }) => {
91+
record.passwordHash = await AdminForth.Utils.generatePasswordHash(record.password);
9192
return { ok: true };
9293
}
9394
},
9495
edit: {
95-
beforeSave: async ({ record, adminUser, resource }) => {
96-
if (record.password) {
97-
record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);
96+
beforeSave: async ({ updates, adminUser, resource }: { updates: any, adminUser: AdminUser, resource: AdminForthResource }) => {
97+
console.log('Updating user', updates);
98+
if (updates.password) {
99+
updates.passwordHash = await AdminForth.Utils.generatePasswordHash(updates.password);
98100
}
99101
return { ok: true }
100102
},
101103
},
102-
}
104+
},
103105
} as AdminForthResourceInput;

adminforth/dataConnectors/baseConnector.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
7272
throw new Error('Method not implemented.');
7373
}
7474

75-
createRecordOriginalValues({ resource, record }: { resource: AdminForthResource; record: any; }): Promise<void> {
75+
createRecordOriginalValues({ resource, record }: { resource: AdminForthResource; record: any; }): Promise<string> {
7676
throw new Error('Method not implemented.');
7777
}
7878

@@ -94,6 +94,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
9494
resource: AdminForthResource; record: any; adminUser: any;
9595
}): Promise<{ error?: string; ok: boolean; createdRecord?: any; }> {
9696
// transform value using setFieldValue and call createRecordOriginalValues
97+
9798
const filledRecord = {...record};
9899
const recordWithOriginalValues = {...record};
99100

@@ -106,9 +107,12 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
106107
});
107108
}
108109
}
109-
recordWithOriginalValues[col.name] = this.setFieldValue(col, filledRecord[col.name]);
110+
if (filledRecord[col.name] !== undefined) {
111+
// no sense to set value if it is not defined
112+
recordWithOriginalValues[col.name] = this.setFieldValue(col, filledRecord[col.name]);
113+
}
110114
}
111-
115+
112116
let error: string | null = null;
113117
await Promise.all(
114118
resource.dataSourceColumns.map(async (col) => {
@@ -125,12 +129,17 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
125129
return { error, ok: false };
126130
}
127131

128-
process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record', recordWithOriginalValues);
129-
await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues });
132+
process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record',JSON.stringify(recordWithOriginalValues));
133+
const pkValue = await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues });
134+
135+
let createdRecord = recordWithOriginalValues;
136+
if (pkValue) {
137+
createdRecord = await this.getRecordByPrimaryKey(resource, pkValue);
138+
}
130139

131140
return {
132141
ok: true,
133-
createdRecord: recordWithOriginalValues,
142+
createdRecord,
134143
}
135144
}
136145

adminforth/dataConnectors/clickhouse.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
294294
}))
295295
return result;
296296
}
297-
async createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }) {
297+
async createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }): Promise<string> {
298298
const tableName = resource.table;
299299
const columns = Object.keys(record);
300300
await this.client.insert({
@@ -303,6 +303,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
303303
columns: columns,
304304
values: [Object.values(record)],
305305
});
306+
return ''; // todo
306307
}
307308

308309
async updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource, recordId: any, newValues: any }) {

adminforth/dataConnectors/mongo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
174174
return result;
175175
}
176176

177-
async createRecordOriginalValues({ resource, record }) {
177+
async createRecordOriginalValues({ resource, record }): Promise<string> {
178178
const tableName = resource.table;
179179
const collection = this.client.db().collection(tableName);
180180
const columns = Object.keys(record);
@@ -183,6 +183,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
183183
newRecord[colName] = record[colName];
184184
}
185185
await collection.insertOne(newRecord);
186+
return ''; // todo
186187
}
187188

188189
async updateRecordOriginalValues({ resource, recordId, newValues }) {

adminforth/dataConnectors/mysql.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
257257
return result;
258258
}
259259

260-
async createRecordOriginalValues({ resource, record }) {
260+
async createRecordOriginalValues({ resource, record }): Promise<string> {
261261
const tableName = resource.table;
262262
const columns = Object.keys(record);
263263
const placeholders = columns.map(() => '?').join(', ');
@@ -267,6 +267,8 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
267267
console.log('🪲📜 MySQL Q:', q, 'values:', values);
268268
}
269269
await this.client.execute(q, values);
270+
271+
return ''; // todo
270272
}
271273

272274
async updateRecordOriginalValues({ resource, recordId, newValues }) {

adminforth/dataConnectors/postgres.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,19 +302,21 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
302302
return result;
303303
}
304304

305-
async createRecordOriginalValues({ resource, record }) {
305+
async createRecordOriginalValues({ resource, record }): Promise<string> {
306306
const tableName = resource.table;
307307
const columns = Object.keys(record);
308308
const placeholders = columns.map((_, i) => `$${i + 1}`).join(', ');
309309
const values = columns.map((colName) => record[colName]);
310310
for (let i = 0; i < columns.length; i++) {
311311
columns[i] = `"${columns[i]}"`;
312312
}
313-
const q = `INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders})`;
313+
const primaryKey = this.getPrimaryKey(resource);
314+
const q = `INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders}) RETURNING "${primaryKey}"`;
314315
if (process.env.HEAVY_DEBUG_QUERY) {
315316
console.log('🪲📜 PG Q:', q, 'values:', values);
316317
}
317-
await this.client.query(q, values);
318+
const ret = await this.client.query(q, values);
319+
return ret.rows[0][primaryKey];
318320
}
319321

320322
async updateRecordOriginalValues({ resource, recordId, newValues }) {

adminforth/dataConnectors/sqlite.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,14 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
235235
return result;
236236
}
237237

238-
async createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }) {
238+
async createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }): Promise<string> {
239239
const tableName = resource.table;
240240
const columns = Object.keys(record);
241241
const placeholders = columns.map(() => '?').join(', ');
242242
const values = columns.map((colName) => record[colName]);
243243
const q = this.client.prepare(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`);
244244
await q.run(values);
245+
return ''; // todo q.lastInsertRowid;
245246
}
246247

247248
async updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource, recordId: any, newValues: any }) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ myadmin/
7777

7878
### Initial Migration & Future Migrations
7979

80-
> ☝️ CLI creates Prisma schema file for managing migrations in relational databases, however you are not forced to use it. Instead you are free to use your favourite or existing migration tool. In this case just ignore generated prisma file, and don't run migration command which will be suggested by CLI. However you have to ensure that your migration tool will generate required table `adminuser` with same fields and types for Users resource.
80+
> ☝️ CLI creates Prisma schema file for managing migrations in relational databases, however you are not forced to use it. Instead you are free to use your favourite or existing migration tool. In this case just ignore generated prisma file, and don't run migration command which will be suggested by CLI. However you have to ensure that your migration tool will generate required table `adminuser` with same fields and types for Admin Users resource to implmenet BackOffice authentication.
8181
8282
CLI will suggest you a command to initialize the database with Prisma:
8383

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ cd ./custom
343343
npm init -y
344344
```
345345

346+
We will use this directory for all custom components. If you want to call your dir with other name then `custom`, just set [customComponentsDir option](/docs/api/Back/interfaces/AdminForthConfigCustomization/#customcomponentsdir)
347+
348+
346349
Also, for better development experience we recommend to create file `custom/tsconfig.json` with the following content:
347350

348351
```json

adminforth/documentation/docs/tutorial/02-glossary.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ It used to:
99
* Make queries to get the list and show records
1010
* Make queries to modify data
1111

12-
There might be several datasources in the system for various databases e.g. One 2 Mongo DBs and 1 Postgres DB.
12+
There might be several datasources in the system for various databases e.g. One datasource to Mongo DBs and one to Postgres DB.
1313

1414
## resource
1515

16-
A [Resource](/docs/api/Back/interfaces/AdminForthResource.md) is a representation of a table or collection in AdminForth. One resource is one table in the database.
17-
It has a `name` which should match name in database, a datasource id, and a list of columns.
18-
Also it has various customization options.
16+
A [Resource](/docs/api/Back/interfaces/AdminForthResource.md) is a AdminForth representation of a table or collection in database. One resource is one table in the database. Resource has `table` property which should be equal to the name of the table in the database.
17+
It has a datasource id to point to database, a definition of list of columns and various customization options.
1918

2019
## column
2120

@@ -47,6 +46,7 @@ There are next [actions](/docs/api/Common/enumerations/AllowedActionsEnum.md):
4746

4847
Hook is a optional async function which allows to inject in backend logic before executing the datasource query or after it.
4948
Hooks exist for all database queries including data read queries like list, show, and data write queries like create, edit, delete.
49+
All AdminForth hooks are executed on the backend side only.
5050

5151
## allowedAction
5252

@@ -56,8 +56,16 @@ returned false you can be sure that user attempt to perform the action or get th
5656

5757
## component
5858

59-
Component is a Vue component which is used to add or modify UI elements in AdminForth. It can be used as a full custom page with a link in menu or as a part of the existing AdminForth page
59+
Component is a Vue frontend component which is used to add or modify UI elements in AdminForth. It can be used as a full custom page with a link in menu or as a part of the existing AdminForth page
6060

6161
## field
6262

63-
The column in the record.
63+
Same to column, but considered in context of record.
64+
65+
## Plugin
66+
67+
Plugin is a class defined to extend AdminForth functionality. Plugin philosophy is to simply modify AdminForth config after it is defined by user. In other words, everything that could be done in config, can be done in plugin and vice versa.
68+
69+
In same way, like config does it, plugins set own Frontend components and backend hooks to modify AdminForth behavior.
70+
71+
The main difference is that plugin allows to simplify routine repeating tasks and reduce the amount of code in the config file and code of cusomtom components.

0 commit comments

Comments
 (0)