cabloy 5.1.148 → 5.1.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cabloy-version +1 -1
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/repo-docs/.vitepress/config.mjs +4 -0
- package/repo-docs/backend/markdown-guide.md +1 -0
- package/repo-docs/backend/relations-guide.md +1 -0
- package/repo-docs/frontend/form-layout-guide.md +15 -1
- package/repo-docs/frontend/markdown-guide.md +1 -0
- package/repo-docs/fullstack/edition-collaboration-differences.md +1 -0
- package/repo-docs/fullstack/one-to-one-companion-resource-guide.md +447 -0
- package/repo-e2e/specs/cabloy-basic.spec.ts +176 -1
- package/vona/src/suite/a-training/modules/training-student/package.json +1 -0
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +177 -103
- package/vona/src/suite/a-training/modules/training-student/src/bean/meta.index.ts +1 -0
- package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +19 -1
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +3 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +3 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +21 -2
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +7 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +21 -2
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +21 -2
- package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +0 -3
- package/vona/src/suite/a-training/modules/training-student/src/entity/studentContent.tsx +36 -0
- package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +6 -0
- package/vona/src/suite/a-training/modules/training-student/src/model/studentContent.ts +22 -0
- package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +63 -6
- package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +117 -7
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +4 -0
- package/zova/src/suite/a-training/modules/training-student/package.json +3 -1
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +40 -40
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +358 -337
- package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +18 -7
- package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/formLayout.ts +13 -5
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Locator, Page } from '@playwright/test';
|
|
1
|
+
import type { Locator, Page, Route } from '@playwright/test';
|
|
2
2
|
|
|
3
3
|
import { expect, test } from '@playwright/test';
|
|
4
4
|
|
|
@@ -56,6 +56,39 @@ function waitForStudentSelect(page: Page) {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function installStudentCreateResponseCapture(page: Page) {
|
|
60
|
+
let studentId: string | number | undefined;
|
|
61
|
+
const handler = async (route: Route) => {
|
|
62
|
+
const request = route.request();
|
|
63
|
+
const url = new URL(request.url());
|
|
64
|
+
if (
|
|
65
|
+
request.method() !== 'POST' ||
|
|
66
|
+
url.pathname !== '/api/training/student' ||
|
|
67
|
+
request.headers()['x-vona-openapi-schema']
|
|
68
|
+
) {
|
|
69
|
+
await route.continue();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const response = await route.fetch();
|
|
73
|
+
const payload = await response.json();
|
|
74
|
+
if (response.ok() && ['string', 'number'].includes(typeof payload.data)) {
|
|
75
|
+
studentId = payload.data;
|
|
76
|
+
}
|
|
77
|
+
await route.fulfill({ response });
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
async install() {
|
|
81
|
+
await page.route('**/api/training/student', handler);
|
|
82
|
+
},
|
|
83
|
+
async uninstall() {
|
|
84
|
+
await page.unroute('**/api/training/student', handler);
|
|
85
|
+
},
|
|
86
|
+
get studentId() {
|
|
87
|
+
return studentId;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
59
92
|
async function getFieldGeometry(locator: Locator): Promise<IFieldGeometry> {
|
|
60
93
|
return locator.evaluate(element => {
|
|
61
94
|
const field = element.closest('label')?.parentElement;
|
|
@@ -348,3 +381,145 @@ test(
|
|
|
348
381
|
expect(pageErrors).toEqual([]);
|
|
349
382
|
},
|
|
350
383
|
);
|
|
384
|
+
|
|
385
|
+
test(
|
|
386
|
+
'ATP-BASIC-FORM-01: Training Student content remains in the Basic Information tab',
|
|
387
|
+
{ tag: ['@admin', '@flow'] },
|
|
388
|
+
async ({ page }) => {
|
|
389
|
+
const pageErrors = collectPageErrors(page);
|
|
390
|
+
await loginAsAdmin(page);
|
|
391
|
+
|
|
392
|
+
const response = await page.goto('/admin/rest/resource/training-student%3Astudent/create', {
|
|
393
|
+
waitUntil: 'load',
|
|
394
|
+
});
|
|
395
|
+
expect(response?.ok()).toBeTruthy();
|
|
396
|
+
await expect(page.locator('html')).toHaveAttribute('data-zova-hydrated', 'admin');
|
|
397
|
+
|
|
398
|
+
const basicInformationTab = page.getByRole('tab', { name: 'Basic Information', exact: true });
|
|
399
|
+
const studentContentGroup = page
|
|
400
|
+
.locator('fieldset')
|
|
401
|
+
.filter({ has: page.locator('legend').filter({ hasText: /^Student Content$/ }) });
|
|
402
|
+
await expect(studentContentGroup).toHaveCount(1);
|
|
403
|
+
await expect(
|
|
404
|
+
studentContentGroup.getByText('Description Markdown', { exact: true }),
|
|
405
|
+
).toBeVisible();
|
|
406
|
+
|
|
407
|
+
const studentContentPanel = studentContentGroup.locator('xpath=ancestor::*[@role="tabpanel"]');
|
|
408
|
+
await expect(studentContentPanel).toHaveCount(1);
|
|
409
|
+
const basicInformationTabId = await basicInformationTab.getAttribute('id');
|
|
410
|
+
expect(basicInformationTabId).not.toBeNull();
|
|
411
|
+
await expect(studentContentPanel).toHaveAttribute('aria-labelledby', basicInformationTabId!);
|
|
412
|
+
expect(pageErrors).toEqual([]);
|
|
413
|
+
},
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
test(
|
|
417
|
+
'ATP-BASIC-SUMMARY-01: Training Student summary renders Markdown HTML in a dialog',
|
|
418
|
+
{ tag: ['@admin', '@flow'] },
|
|
419
|
+
async ({ page }) => {
|
|
420
|
+
const pageErrors = collectPageErrors(page);
|
|
421
|
+
await loginAsAdmin(page);
|
|
422
|
+
|
|
423
|
+
const studentName = `Summary E2E ${Date.now()}`;
|
|
424
|
+
const createResponseCapture = installStudentCreateResponseCapture(page);
|
|
425
|
+
let studentId: string | number | undefined;
|
|
426
|
+
await createResponseCapture.install();
|
|
427
|
+
try {
|
|
428
|
+
const createPageResponse = await page.goto(
|
|
429
|
+
'/admin/rest/resource/training-student%3Astudent/create',
|
|
430
|
+
{ waitUntil: 'load' },
|
|
431
|
+
);
|
|
432
|
+
expect(createPageResponse?.ok()).toBeTruthy();
|
|
433
|
+
await expect(page.locator('html')).toHaveAttribute('data-zova-hydrated', 'admin');
|
|
434
|
+
await page
|
|
435
|
+
.getByRole('group', { name: 'Student Name *', exact: true })
|
|
436
|
+
.getByRole('textbox')
|
|
437
|
+
.fill(studentName);
|
|
438
|
+
await page
|
|
439
|
+
.getByRole('group', { name: 'Mobile *', exact: true })
|
|
440
|
+
.getByRole('textbox')
|
|
441
|
+
.fill('13812345678');
|
|
442
|
+
await page
|
|
443
|
+
.locator('.ProseMirror')
|
|
444
|
+
.last()
|
|
445
|
+
.fill(`## Summary heading\n\nSummary paragraph ${studentName}`);
|
|
446
|
+
await page.getByRole('tab', { name: 'Student Training Records', exact: true }).click();
|
|
447
|
+
await page.getByText('Foundation Track', { exact: true }).click();
|
|
448
|
+
|
|
449
|
+
const submitButton = page.getByRole('button', { name: 'Submit', exact: true });
|
|
450
|
+
await expect(submitButton).toBeEnabled();
|
|
451
|
+
await submitButton.click();
|
|
452
|
+
await expect(page).toHaveURL(/\/admin\/(?:\?|$)/);
|
|
453
|
+
studentId = createResponseCapture.studentId;
|
|
454
|
+
expect(['string', 'number']).toContain(typeof studentId);
|
|
455
|
+
|
|
456
|
+
const response = await page.goto('/admin/rest/resource/training-student%3Astudent', {
|
|
457
|
+
waitUntil: 'load',
|
|
458
|
+
});
|
|
459
|
+
expect(response?.ok()).toBeTruthy();
|
|
460
|
+
await expect(page.locator('html')).toHaveAttribute('data-zova-hydrated', 'admin');
|
|
461
|
+
|
|
462
|
+
const filterName = page.getByLabel('Student Name');
|
|
463
|
+
await expect(filterName).toBeVisible();
|
|
464
|
+
await filterName.fill(studentName);
|
|
465
|
+
const searchResponse = waitForStudentSelect(page);
|
|
466
|
+
await page.getByRole('button', { name: 'Search', exact: true }).click();
|
|
467
|
+
await searchResponse;
|
|
468
|
+
|
|
469
|
+
const row = page.locator('tr').filter({ hasText: studentName });
|
|
470
|
+
await expect(row).toHaveCount(1);
|
|
471
|
+
const summaryResponse = page.waitForResponse(response => {
|
|
472
|
+
const url = new URL(response.url());
|
|
473
|
+
return (
|
|
474
|
+
response.request().method() === 'GET' &&
|
|
475
|
+
response.ok() &&
|
|
476
|
+
url.pathname === `/api/training/student/summary/${studentId}` &&
|
|
477
|
+
!response.request().headers()['x-vona-openapi-schema']
|
|
478
|
+
);
|
|
479
|
+
});
|
|
480
|
+
await row.getByRole('button', { name: 'Summary', exact: true }).click();
|
|
481
|
+
await summaryResponse;
|
|
482
|
+
|
|
483
|
+
const description = page.locator('.student-summary-description');
|
|
484
|
+
await expect(description).toBeVisible();
|
|
485
|
+
await expect(description.locator('h2')).toHaveText('Summary heading');
|
|
486
|
+
await expect(description).toContainText(`Summary paragraph ${studentName}`);
|
|
487
|
+
expect(pageErrors).toEqual([]);
|
|
488
|
+
} finally {
|
|
489
|
+
try {
|
|
490
|
+
if (studentId !== undefined) {
|
|
491
|
+
const description = page.locator('.student-summary-description');
|
|
492
|
+
if (await description.count()) {
|
|
493
|
+
await description.locator('xpath=../..').getByRole('button').click();
|
|
494
|
+
}
|
|
495
|
+
const row = page.locator('tr').filter({ hasText: studentName });
|
|
496
|
+
if (!(await row.count())) {
|
|
497
|
+
const response = await page.goto('/admin/rest/resource/training-student%3Astudent', {
|
|
498
|
+
waitUntil: 'load',
|
|
499
|
+
});
|
|
500
|
+
expect(response?.ok()).toBeTruthy();
|
|
501
|
+
await expect(page.locator('html')).toHaveAttribute('data-zova-hydrated', 'admin');
|
|
502
|
+
await page.getByLabel('Student Name').fill(studentName);
|
|
503
|
+
const searchResponse = waitForStudentSelect(page);
|
|
504
|
+
await page.getByRole('button', { name: 'Search', exact: true }).click();
|
|
505
|
+
await searchResponse;
|
|
506
|
+
}
|
|
507
|
+
const deleteResponse = page.waitForResponse(response => {
|
|
508
|
+
const url = new URL(response.url());
|
|
509
|
+
return (
|
|
510
|
+
response.request().method() === 'DELETE' &&
|
|
511
|
+
response.ok() &&
|
|
512
|
+
url.pathname === `/api/training/student/deleteForce/${studentId}` &&
|
|
513
|
+
!response.request().headers()['x-vona-openapi-schema']
|
|
514
|
+
);
|
|
515
|
+
});
|
|
516
|
+
await row.getByRole('button', { name: 'Force Delete', exact: true }).click();
|
|
517
|
+
await page.getByRole('button', { name: 'Yes', exact: true }).click();
|
|
518
|
+
await deleteResponse;
|
|
519
|
+
}
|
|
520
|
+
} finally {
|
|
521
|
+
await createResponseCapture.uninstall();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
);
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
// eslint-disable
|
|
2
|
-
import type { TypeEntityMeta,TypeModelsClassLikeGeneral,TypeSymbolKeyFieldsMore,IModelRelationHasMany } from 'vona-module-a-orm';
|
|
2
|
+
import type { TypeEntityMeta,TypeModelsClassLikeGeneral,TypeSymbolKeyFieldsMore,IModelRelationHasOne,IModelRelationBelongsTo,IModelRelationHasMany } from 'vona-module-a-orm';
|
|
3
3
|
import type { TypeEntityOptionsFields,TypeControllerOptionsActions } from 'vona-module-a-openapi';
|
|
4
4
|
import type { TableIdentity } from 'table-identity';
|
|
5
5
|
/** entity: begin */
|
|
6
6
|
export * from '../entity/student.tsx';
|
|
7
|
+
export * from '../entity/studentContent.tsx';
|
|
7
8
|
import type { IEntityOptionsStudent } from '../entity/student.tsx';
|
|
9
|
+
import type { IEntityOptionsStudentContent } from '../entity/studentContent.tsx';
|
|
8
10
|
import 'vona-module-a-orm';
|
|
9
11
|
declare module 'vona-module-a-orm' {
|
|
10
12
|
|
|
11
13
|
export interface IEntityRecord {
|
|
12
14
|
'training-student:student': IEntityOptionsStudent;
|
|
15
|
+
'training-student:studentContent': IEntityOptionsStudentContent;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
|
|
@@ -20,16 +23,21 @@ declare module 'vona-module-training-student' {
|
|
|
20
23
|
/** entity: end */
|
|
21
24
|
/** entity: begin */
|
|
22
25
|
import type { EntityStudent } from '../entity/student.tsx';
|
|
26
|
+
import type { EntityStudentContent } from '../entity/studentContent.tsx';
|
|
23
27
|
export interface IModuleEntity {
|
|
24
28
|
'student': EntityStudentMeta;
|
|
29
|
+
'studentContent': EntityStudentContentMeta;
|
|
25
30
|
}
|
|
26
31
|
/** entity: end */
|
|
27
32
|
/** entity: begin */
|
|
28
33
|
export type EntityStudentTableName = 'trainingStudent';
|
|
34
|
+
export type EntityStudentContentTableName = 'trainingStudentContent';
|
|
29
35
|
export type EntityStudentMeta=TypeEntityMeta<EntityStudent,EntityStudentTableName>;
|
|
36
|
+
export type EntityStudentContentMeta=TypeEntityMeta<EntityStudentContent,EntityStudentContentTableName>;
|
|
30
37
|
declare module 'vona-module-a-orm' {
|
|
31
38
|
export interface ITableRecord {
|
|
32
39
|
'trainingStudent': EntityStudentMeta;
|
|
40
|
+
'trainingStudentContent': EntityStudentContentMeta;
|
|
33
41
|
}
|
|
34
42
|
}
|
|
35
43
|
declare module 'vona-module-training-student' {
|
|
@@ -37,16 +45,23 @@ declare module 'vona-module-training-student' {
|
|
|
37
45
|
export interface IEntityOptionsStudent {
|
|
38
46
|
fields?: TypeEntityOptionsFields<EntityStudent, IEntityOptionsStudent[TypeSymbolKeyFieldsMore]>;
|
|
39
47
|
}
|
|
48
|
+
|
|
49
|
+
export interface IEntityOptionsStudentContent {
|
|
50
|
+
fields?: TypeEntityOptionsFields<EntityStudentContent, IEntityOptionsStudentContent[TypeSymbolKeyFieldsMore]>;
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
/** entity: end */
|
|
42
54
|
/** model: begin */
|
|
43
55
|
export * from '../model/student.ts';
|
|
56
|
+
export * from '../model/studentContent.ts';
|
|
44
57
|
import type { IModelOptionsStudent } from '../model/student.ts';
|
|
58
|
+
import type { IModelOptionsStudentContent } from '../model/studentContent.ts';
|
|
45
59
|
import 'vona-module-a-orm';
|
|
46
60
|
declare module 'vona-module-a-orm' {
|
|
47
61
|
|
|
48
62
|
export interface IModelRecord {
|
|
49
63
|
'training-student:student': IModelOptionsStudent;
|
|
64
|
+
'training-student:studentContent': IModelOptionsStudentContent;
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
|
|
@@ -63,12 +78,25 @@ declare module 'vona-module-training-student' {
|
|
|
63
78
|
get $onionName(): 'training-student:student';
|
|
64
79
|
get $onionOptions(): IModelOptionsStudent;
|
|
65
80
|
}
|
|
81
|
+
|
|
82
|
+
export interface ModelStudentContent {
|
|
83
|
+
/** @internal */
|
|
84
|
+
get scope(): ScopeModuleTrainingStudent;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ModelStudentContent {
|
|
88
|
+
get $beanFullName(): 'training-student.model.studentContent';
|
|
89
|
+
get $onionName(): 'training-student:studentContent';
|
|
90
|
+
get $onionOptions(): IModelOptionsStudentContent;
|
|
91
|
+
}
|
|
66
92
|
}
|
|
67
93
|
/** model: end */
|
|
68
94
|
/** model: begin */
|
|
69
95
|
import type { ModelStudent } from '../model/student.ts';
|
|
96
|
+
import type { ModelStudentContent } from '../model/studentContent.ts';
|
|
70
97
|
export interface IModuleModel {
|
|
71
98
|
'student': ModelStudent;
|
|
99
|
+
'studentContent': ModelStudentContent;
|
|
72
100
|
}
|
|
73
101
|
/** model: end */
|
|
74
102
|
/** model: begin */
|
|
@@ -77,6 +105,7 @@ import 'vona';
|
|
|
77
105
|
declare module 'vona' {
|
|
78
106
|
export interface IBeanRecordGeneral {
|
|
79
107
|
'training-student.model.student': ModelStudent;
|
|
108
|
+
'training-student.model.studentContent': ModelStudentContent;
|
|
80
109
|
}
|
|
81
110
|
}
|
|
82
111
|
/** model: end */
|
|
@@ -87,6 +116,13 @@ declare module 'vona-module-training-student' {
|
|
|
87
116
|
export interface IModelOptionsStudent {
|
|
88
117
|
relations: {
|
|
89
118
|
trainingRecords: IModelRelationHasMany<'training-record:record', 'studentId', false, 'id'|'name'|'subjectCount'|'totalScore'|'averageScore'|'trainingTime'|'sceneImageIds'|'dossierFileIds'|'description', undefined, undefined, undefined>;
|
|
119
|
+
studentContent: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'studentId'|'descriptionMarkdown'|'descriptionHtml'>;
|
|
120
|
+
studentContentForm: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'studentId'|'descriptionMarkdown'>;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export interface IModelOptionsStudentContent {
|
|
124
|
+
relations: {
|
|
125
|
+
student: IModelRelationBelongsTo<'training-student:studentContent', 'training-student:student', false, '*'>;
|
|
90
126
|
};
|
|
91
127
|
}
|
|
92
128
|
export interface ModelStudent {
|
|
@@ -130,91 +166,51 @@ getByNameEqI<T extends IModelGetOptions<EntityStudent,ModelStudent>>(name?: stri
|
|
|
130
166
|
selectByName<T extends IModelSelectParams<EntityStudent,ModelStudent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(name?: string, params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T>[]>;
|
|
131
167
|
selectByNameEqI<T extends IModelSelectParams<EntityStudent,ModelStudent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(name?: string, params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T>[]>;
|
|
132
168
|
}
|
|
169
|
+
export interface ModelStudentContent {
|
|
170
|
+
[SymbolKeyEntity]: EntityStudentContent;
|
|
171
|
+
[SymbolKeyEntityMeta]: EntityStudentContentMeta;
|
|
172
|
+
[SymbolKeyModelOptions]: IModelOptionsStudentContent;
|
|
173
|
+
get<T extends IModelGetOptions<EntityStudentContent,ModelStudentContent>>(where: TypeModelWhere<EntityStudentContent>, options?: T): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T> | undefined>;
|
|
174
|
+
/**
|
|
175
|
+
* Retrieves one matching primary row with a pessimistic FOR UPDATE lock.
|
|
176
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
177
|
+
* Entity and query caches are bypassed.
|
|
178
|
+
*/
|
|
179
|
+
getForUpdate<T extends IModelGetOptions<EntityStudentContent,ModelStudentContent>>(where: TypeModelWhere<EntityStudentContent>, options?: T): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T> | undefined>;
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves a primary row by ID with the same pessimistic FOR UPDATE lock semantics.
|
|
182
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
183
|
+
* Entity and query caches are bypassed.
|
|
184
|
+
*/
|
|
185
|
+
getByIdForUpdate<T extends IModelGetOptions<EntityStudentContent,ModelStudentContent>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T> | undefined>;
|
|
186
|
+
mget<T extends IModelGetOptions<EntityStudentContent,ModelStudentContent>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T>[]>;
|
|
187
|
+
selectAndCount<T extends IModelSelectParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityStudentContent, ModelStudentContent, T>>;
|
|
188
|
+
select<T extends IModelSelectParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T>[]>;
|
|
189
|
+
insert<T extends IModelInsertOptions<EntityStudentContent,ModelStudentContent>>(data?: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>, options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T, true>>;
|
|
190
|
+
insertBulk<T extends IModelInsertOptions<EntityStudentContent,ModelStudentContent>>(items: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T, true>[]>;
|
|
191
|
+
update<T extends IModelUpdateOptions<EntityStudentContent,ModelStudentContent>>(data: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>, options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>>;
|
|
192
|
+
updateBulk<T extends IModelUpdateOptions<EntityStudentContent,ModelStudentContent>>(items: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>[]>;
|
|
193
|
+
delete<T extends IModelDeleteOptions<EntityStudentContent,ModelStudentContent>>(where?: TypeModelWhere<EntityStudentContent>, options?: T): Promise<void>;
|
|
194
|
+
deleteBulk<T extends IModelDeleteOptions<EntityStudentContent,ModelStudentContent>>(ids: TableIdentity[], options?: T): Promise<void>;
|
|
195
|
+
mutate<T extends IModelMutateOptions<EntityStudentContent,ModelStudentContent>>(data?: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>, options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>>;
|
|
196
|
+
mutateBulk<T extends IModelMutateOptions<EntityStudentContent,ModelStudentContent>>(items: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>[]>;
|
|
197
|
+
count<T extends IModelSelectCountParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<string | undefined>;
|
|
198
|
+
increment<T extends IModelIncrementParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
|
|
199
|
+
decrement<T extends IModelIncrementParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
|
|
200
|
+
aggregate<T extends IModelSelectAggrParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelAggrRelationResult<T>>;
|
|
201
|
+
group<T extends IModelSelectGroupParams<EntityStudentContent,ModelStudentContent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelGroupRelationResult<EntityStudentContent, T>[]>;
|
|
202
|
+
getById<T extends IModelGetOptions<EntityStudentContent,ModelStudentContent>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityStudentContent, ModelStudentContent, T> | undefined>;
|
|
203
|
+
updateById<T extends IModelUpdateOptions<EntityStudentContent,ModelStudentContent>>(id: TableIdentity, data: TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>, options?: T): Promise<TypeModelMutateRelationData<EntityStudentContent,ModelStudentContent, T>>;
|
|
204
|
+
deleteById<T extends IModelDeleteOptions<EntityStudentContent,ModelStudentContent>>(id: TableIdentity, options?: T): Promise<void>;
|
|
205
|
+
}
|
|
133
206
|
}
|
|
134
207
|
declare module 'vona-module-a-orm' {
|
|
135
208
|
export interface IModelClassRecord {
|
|
136
209
|
'training-student:student': ModelStudent;
|
|
210
|
+
'training-student:studentContent': ModelStudentContent;
|
|
137
211
|
}
|
|
138
212
|
}
|
|
139
213
|
/** model: end */
|
|
140
|
-
/** service: begin */
|
|
141
|
-
export * from '../service/student.ts';
|
|
142
|
-
|
|
143
|
-
import 'vona-module-a-bean';
|
|
144
|
-
declare module 'vona-module-a-bean' {
|
|
145
|
-
|
|
146
|
-
export interface IServiceRecord {
|
|
147
|
-
'training-student:student': never;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
declare module 'vona-module-training-student' {
|
|
153
|
-
|
|
154
|
-
export interface ServiceStudent {
|
|
155
|
-
/** @internal */
|
|
156
|
-
get scope(): ScopeModuleTrainingStudent;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export interface ServiceStudent {
|
|
160
|
-
get $beanFullName(): 'training-student.service.student';
|
|
161
|
-
get $onionName(): 'training-student:student';
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
/** service: end */
|
|
165
|
-
/** service: begin */
|
|
166
|
-
import type { ServiceStudent } from '../service/student.ts';
|
|
167
|
-
export interface IModuleService {
|
|
168
|
-
'student': ServiceStudent;
|
|
169
|
-
}
|
|
170
|
-
/** service: end */
|
|
171
|
-
/** service: begin */
|
|
172
|
-
|
|
173
|
-
import 'vona';
|
|
174
|
-
declare module 'vona' {
|
|
175
|
-
export interface IBeanRecordGeneral {
|
|
176
|
-
'training-student.service.student': ServiceStudent;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/** service: end */
|
|
180
|
-
/** meta: begin */
|
|
181
|
-
export * from '../bean/meta.index.ts';
|
|
182
|
-
export * from '../bean/meta.version.ts';
|
|
183
|
-
import type { IMetaOptionsIndex } from 'vona-module-a-index';
|
|
184
|
-
import 'vona-module-a-meta';
|
|
185
|
-
declare module 'vona-module-a-meta' {
|
|
186
|
-
|
|
187
|
-
export interface IMetaRecord {
|
|
188
|
-
'training-student:index': IMetaOptionsIndex;
|
|
189
|
-
'training-student:version': never;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
declare module 'vona-module-training-student' {
|
|
195
|
-
|
|
196
|
-
export interface MetaIndex {
|
|
197
|
-
/** @internal */
|
|
198
|
-
get scope(): ScopeModuleTrainingStudent;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export interface MetaIndex {
|
|
202
|
-
get $beanFullName(): 'training-student.meta.index';
|
|
203
|
-
get $onionName(): 'training-student:index';
|
|
204
|
-
get $onionOptions(): IMetaOptionsIndex;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export interface MetaVersion {
|
|
208
|
-
/** @internal */
|
|
209
|
-
get scope(): ScopeModuleTrainingStudent;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export interface MetaVersion {
|
|
213
|
-
get $beanFullName(): 'training-student.meta.version';
|
|
214
|
-
get $onionName(): 'training-student:version';
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
/** meta: end */
|
|
218
214
|
/** dto: begin */
|
|
219
215
|
export * from '../dto/detailRecordBase.tsx';
|
|
220
216
|
export * from '../dto/detailRecordMutate.tsx';
|
|
@@ -381,58 +377,136 @@ import 'vona-module-a-openapi';
|
|
|
381
377
|
}
|
|
382
378
|
|
|
383
379
|
/** controller: end */
|
|
384
|
-
/**
|
|
385
|
-
export * from '../bean/
|
|
386
|
-
import type { ISsrMenuOptionsStudent } from '../bean/ssrMenu.student.ts';
|
|
387
|
-
import 'vona-module-a-ssr';
|
|
388
|
-
declare module 'vona-module-a-ssr' {
|
|
380
|
+
/** imageScene: begin */
|
|
381
|
+
export * from '../bean/imageScene.studentImage.ts';
|
|
389
382
|
|
|
390
|
-
|
|
391
|
-
|
|
383
|
+
import { type IDecoratorImageSceneOptions } from 'vona-module-a-image';
|
|
384
|
+
declare module 'vona-module-a-image' {
|
|
385
|
+
|
|
386
|
+
export interface IImageSceneRecord {
|
|
387
|
+
'training-student:studentImage': IDecoratorImageSceneOptions;
|
|
392
388
|
}
|
|
393
389
|
|
|
394
390
|
|
|
395
391
|
}
|
|
396
392
|
declare module 'vona-module-training-student' {
|
|
397
393
|
|
|
398
|
-
export interface
|
|
394
|
+
export interface ImageSceneStudentImage {
|
|
399
395
|
/** @internal */
|
|
400
396
|
get scope(): ScopeModuleTrainingStudent;
|
|
401
397
|
}
|
|
402
398
|
|
|
403
|
-
export interface
|
|
404
|
-
get $beanFullName(): 'training-student.
|
|
399
|
+
export interface ImageSceneStudentImage {
|
|
400
|
+
get $beanFullName(): 'training-student.imageScene.studentImage';
|
|
401
|
+
get $onionName(): 'training-student:studentImage';
|
|
402
|
+
get $onionOptions(): IDecoratorImageSceneOptions;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/** imageScene: end */
|
|
406
|
+
/** service: begin */
|
|
407
|
+
export * from '../service/student.ts';
|
|
408
|
+
|
|
409
|
+
import 'vona-module-a-bean';
|
|
410
|
+
declare module 'vona-module-a-bean' {
|
|
411
|
+
|
|
412
|
+
export interface IServiceRecord {
|
|
413
|
+
'training-student:student': never;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
}
|
|
418
|
+
declare module 'vona-module-training-student' {
|
|
419
|
+
|
|
420
|
+
export interface ServiceStudent {
|
|
421
|
+
/** @internal */
|
|
422
|
+
get scope(): ScopeModuleTrainingStudent;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export interface ServiceStudent {
|
|
426
|
+
get $beanFullName(): 'training-student.service.student';
|
|
405
427
|
get $onionName(): 'training-student:student';
|
|
406
|
-
get $onionOptions(): ISsrMenuOptionsStudent;
|
|
407
428
|
}
|
|
408
429
|
}
|
|
409
|
-
/**
|
|
410
|
-
/**
|
|
411
|
-
|
|
430
|
+
/** service: end */
|
|
431
|
+
/** service: begin */
|
|
432
|
+
import type { ServiceStudent } from '../service/student.ts';
|
|
433
|
+
export interface IModuleService {
|
|
434
|
+
'student': ServiceStudent;
|
|
435
|
+
}
|
|
436
|
+
/** service: end */
|
|
437
|
+
/** service: begin */
|
|
412
438
|
|
|
413
|
-
import
|
|
414
|
-
declare module 'vona
|
|
439
|
+
import 'vona';
|
|
440
|
+
declare module 'vona' {
|
|
441
|
+
export interface IBeanRecordGeneral {
|
|
442
|
+
'training-student.service.student': ServiceStudent;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/** service: end */
|
|
446
|
+
/** meta: begin */
|
|
447
|
+
export * from '../bean/meta.index.ts';
|
|
448
|
+
export * from '../bean/meta.version.ts';
|
|
449
|
+
import type { IMetaOptionsIndex } from 'vona-module-a-index';
|
|
450
|
+
import 'vona-module-a-meta';
|
|
451
|
+
declare module 'vona-module-a-meta' {
|
|
415
452
|
|
|
416
|
-
export interface
|
|
417
|
-
'training-student:
|
|
453
|
+
export interface IMetaRecord {
|
|
454
|
+
'training-student:index': IMetaOptionsIndex;
|
|
455
|
+
'training-student:version': never;
|
|
418
456
|
}
|
|
419
457
|
|
|
420
458
|
|
|
421
459
|
}
|
|
422
460
|
declare module 'vona-module-training-student' {
|
|
423
461
|
|
|
424
|
-
export interface
|
|
462
|
+
export interface MetaIndex {
|
|
425
463
|
/** @internal */
|
|
426
464
|
get scope(): ScopeModuleTrainingStudent;
|
|
427
465
|
}
|
|
428
466
|
|
|
429
|
-
export interface
|
|
430
|
-
get $beanFullName(): 'training-student.
|
|
431
|
-
get $onionName(): 'training-student:
|
|
432
|
-
get $onionOptions():
|
|
467
|
+
export interface MetaIndex {
|
|
468
|
+
get $beanFullName(): 'training-student.meta.index';
|
|
469
|
+
get $onionName(): 'training-student:index';
|
|
470
|
+
get $onionOptions(): IMetaOptionsIndex;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export interface MetaVersion {
|
|
474
|
+
/** @internal */
|
|
475
|
+
get scope(): ScopeModuleTrainingStudent;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export interface MetaVersion {
|
|
479
|
+
get $beanFullName(): 'training-student.meta.version';
|
|
480
|
+
get $onionName(): 'training-student:version';
|
|
433
481
|
}
|
|
434
482
|
}
|
|
435
|
-
/**
|
|
483
|
+
/** meta: end */
|
|
484
|
+
/** ssrMenu: begin */
|
|
485
|
+
export * from '../bean/ssrMenu.student.ts';
|
|
486
|
+
import type { ISsrMenuOptionsStudent } from '../bean/ssrMenu.student.ts';
|
|
487
|
+
import 'vona-module-a-ssr';
|
|
488
|
+
declare module 'vona-module-a-ssr' {
|
|
489
|
+
|
|
490
|
+
export interface ISsrMenuRecord {
|
|
491
|
+
'training-student:student': ISsrMenuOptionsStudent;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
}
|
|
496
|
+
declare module 'vona-module-training-student' {
|
|
497
|
+
|
|
498
|
+
export interface SsrMenuStudent {
|
|
499
|
+
/** @internal */
|
|
500
|
+
get scope(): ScopeModuleTrainingStudent;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export interface SsrMenuStudent {
|
|
504
|
+
get $beanFullName(): 'training-student.ssrMenu.student';
|
|
505
|
+
get $onionName(): 'training-student:student';
|
|
506
|
+
get $onionOptions(): ISsrMenuOptionsStudent;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/** ssrMenu: end */
|
|
436
510
|
/** locale: begin */
|
|
437
511
|
import { locales } from './locales.ts';
|
|
438
512
|
/** locale: end */
|
|
@@ -12,11 +12,29 @@ export class MetaVersion extends BeanBase implements IMetaVersionUpdate {
|
|
|
12
12
|
table.comment(entityStudent.$comment.$table);
|
|
13
13
|
table.basicFields();
|
|
14
14
|
table.string(entityStudent.name, 50).comment(entityStudent.$comment.name);
|
|
15
|
-
table.string(entityStudent.description, 255).comment(entityStudent.$comment.description);
|
|
16
15
|
table.string(entityStudent.mobile, 50).comment(entityStudent.$comment.mobile);
|
|
17
16
|
table.tableIdentity(entityStudent.imageId).comment(entityStudent.$comment.imageId);
|
|
18
17
|
table.integer(entityStudent.level).comment(entityStudent.$comment.level);
|
|
19
18
|
});
|
|
19
|
+
|
|
20
|
+
const entityStudentContent = this.scope.entity.studentContent;
|
|
21
|
+
await this.bean.model.createTable(entityStudentContent.$table, table => {
|
|
22
|
+
table.comment(entityStudentContent.$comment.$table);
|
|
23
|
+
table.basicFields();
|
|
24
|
+
table
|
|
25
|
+
.text(entityStudentContent.descriptionMarkdown)
|
|
26
|
+
.comment(entityStudentContent.$comment.descriptionMarkdown);
|
|
27
|
+
table
|
|
28
|
+
.text(entityStudentContent.descriptionHtml)
|
|
29
|
+
.comment(entityStudentContent.$comment.descriptionHtml);
|
|
30
|
+
table
|
|
31
|
+
.tableIdentity(entityStudentContent.studentId)
|
|
32
|
+
.comment(entityStudentContent.$comment.studentId);
|
|
33
|
+
table.index(
|
|
34
|
+
[entityStudentContent.studentId],
|
|
35
|
+
`idx_${entityStudentContent.$table}_studentId`,
|
|
36
|
+
);
|
|
37
|
+
});
|
|
20
38
|
}
|
|
21
39
|
}
|
|
22
40
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
Description: 'Description',
|
|
3
|
+
DescriptionMarkdown: 'Description Markdown',
|
|
4
|
+
DescriptionHtml: 'Description HTML',
|
|
5
|
+
StudentContent: 'Student Content',
|
|
3
6
|
Level: 'Training Stage',
|
|
4
7
|
BasicInformation: 'Basic Information',
|
|
5
8
|
StudentProfile: 'Student Profile',
|