ApiLogicServer 15.0.20__py3-none-any.whl → 15.0.23__py3-none-any.whl
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.
- api_logic_server_cli/api_logic_server.py +2 -2
- api_logic_server_cli/api_logic_server_info.yaml +2 -2
- api_logic_server_cli/genai/genai_admin_app.py +41 -13
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-Resource-Learning-Prompt.md +119 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-js-Learning-Prompt.md +71 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-config-prompt.md +18 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-json-api-model-prompt.md +89 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/{Admin-App-Learning-Prompt.md → z-unused-Admin-App-Learning-Prompt.md} +33 -24
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/package.json +3 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/Config.js +527 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/app_loader.js +24 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/.eslintrc +5 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/.yarnrc.yml +4 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/default-settings.js +25 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/default-settings.ts +25 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/errors.js +116 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/errors.ts +116 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/index.test.tsx +7 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/index.tsx +11 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/ra-jsonapi-client.js +577 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/ra-jsonapi-client.ts +577 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/resourceLookup.js +124 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/resourceLookup.ts +124 -0
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/styles.module.css +9 -0
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/METADATA +1 -1
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/RECORD +30 -12
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/dataProvider.js +0 -110
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/WHEEL +0 -0
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/entry_points.txt +0 -0
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/licenses/LICENSE +0 -0
- {apilogicserver-15.0.20.dist-info → apilogicserver-15.0.23.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,10 @@ ApiLogicServer CLI: given a database url, create [and run] customizable ApiLogic
|
|
|
12
12
|
Called from api_logic_server_cli.py, by instantiating the ProjectRun object.
|
|
13
13
|
'''
|
|
14
14
|
|
|
15
|
-
__version__ = "15.00.
|
|
15
|
+
__version__ = "15.00.23" # last public release: 15.00.22 (15.00.12)
|
|
16
16
|
recent_changes = \
|
|
17
17
|
f'\n\nRecent Changes:\n' +\
|
|
18
|
-
"\t06/
|
|
18
|
+
"\t06/23/2024 - 15.00.23: Tech Preview: als genai-app w/ sra provider+model, import fix, bug [96] \n"\
|
|
19
19
|
"\t06/10/2024 - 15.00.12: MCP Security, win fixes for readme, graphics quotes \n"\
|
|
20
20
|
"\t06/08/2024 - 15.00.10: MCP, optional shortening of stacktrace lines, bugfix[92] \n"\
|
|
21
21
|
"\t05/16/2024 - 14.05.00: safrs 3.1.7, running mcp preview \n"\
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
last_created_date: June
|
|
1
|
+
last_created_date: June 23, 2025 06:19:07
|
|
2
2
|
last_created_project_name: ../../../servers/basic_demo
|
|
3
|
-
last_created_version: 15.00.
|
|
3
|
+
last_created_version: 15.00.22
|
|
@@ -43,28 +43,41 @@ class GenAIAdminApp:
|
|
|
43
43
|
|
|
44
44
|
self.api_version = genai_version
|
|
45
45
|
self.project_root = project.project_directory_path
|
|
46
|
+
self.app_templates_path = genai_svcs.get_manager_path(use_env=True).joinpath('system/genai/app_templates')
|
|
47
|
+
|
|
46
48
|
self.dbml_path = self.project_root / "docs/db.dbml"
|
|
47
|
-
self.admin_yaml_path = self.project_root / f"ui/admin/{schema}"
|
|
48
49
|
self.discovery_path = self.project_root / "docs/mcp_learning/mcp_discovery.json"
|
|
49
50
|
|
|
51
|
+
self.admin_yaml_path = self.project_root / f"ui/admin/{schema}"
|
|
52
|
+
self.admin_config_prompt_path = self.app_templates_path / f"app_learning/Admin-config-prompt.md"
|
|
53
|
+
self.admin_json_api_model_prompt_path = self.app_templates_path / f"app_learning/Admin-json-api-model-prompt.md"
|
|
54
|
+
assert self.admin_config_prompt_path.exists(), "sys err - self.admin_config_prompt_path"
|
|
55
|
+
assert self.admin_json_api_model_prompt_path.exists(), "sys err - self.admin_json_api_model_prompt_path"
|
|
56
|
+
|
|
50
57
|
self.ui_project_path = self.project_root / f"ui/{app_name}"
|
|
51
58
|
self.ui_src_path = self.ui_project_path / "src"
|
|
52
59
|
|
|
53
60
|
self.app_templates_path = genai_svcs.get_manager_path(use_env=True).joinpath('system/genai/app_templates')
|
|
54
61
|
self.react_admin_template_path = self.app_templates_path / 'react-admin-template'
|
|
55
62
|
self.prompts_path = self.app_templates_path / "app_learning"
|
|
56
|
-
self.admin_app_learning = utils.read_file(self.prompts_path / "Admin-App-Learning-Prompt.md")
|
|
63
|
+
# self.admin_app_learning = utils.read_file(self.prompts_path / "Admin-App-Learning-Prompt.md")
|
|
64
|
+
self.admin_app_resource_learning = utils.read_file(self.prompts_path / "Admin-App-Resource-Learning-Prompt.md")
|
|
65
|
+
self.admin_app_js_learning = utils.read_file(self.prompts_path / "Admin-App-js-Learning-Prompt.md")
|
|
57
66
|
self.image_url = self.prompts_path / 'Order-Page.png' # did not seem to help, made it 2x slower
|
|
58
67
|
|
|
59
68
|
# self.schema = utils.read_file(self.dbml_path)
|
|
60
69
|
self.schema_yaml = utils.read_file(self.admin_yaml_path)
|
|
61
|
-
self.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
self.resources
|
|
65
|
-
|
|
66
|
-
self.
|
|
67
|
-
|
|
70
|
+
self.schema_dict = yaml.safe_load(self.schema_yaml)
|
|
71
|
+
self.admin_config_prompt = utils.read_file(self.admin_config_prompt_path)
|
|
72
|
+
self.admin_json_api_model_prompt = utils.read_file(self.admin_json_api_model_prompt_path)
|
|
73
|
+
config_prompt_parts = self.admin_config_prompt.split('<resources></resources>')
|
|
74
|
+
self.resources = self.schema_dict['resources']
|
|
75
|
+
# convert self.resources dict to text lines
|
|
76
|
+
self.resource_lines = json.dumps(self.resources, indent=4)
|
|
77
|
+
resources_dict = "\n".join([f"- {name}: {details}" for name, details in self.resources.items()])
|
|
78
|
+
config_prompt = config_prompt_parts[0] + "\n<resources>\n" + self.resource_lines + config_prompt_parts[1]
|
|
79
|
+
self.schema = config_prompt + self.admin_json_api_model_prompt
|
|
80
|
+
self.schema_lines = self.schema.split('\n') # for debug
|
|
68
81
|
|
|
69
82
|
shutil.copytree(self.react_admin_template_path, self.ui_project_path, dirs_exist_ok=True)
|
|
70
83
|
|
|
@@ -109,7 +122,7 @@ class GenAIAdminApp:
|
|
|
109
122
|
return "\n".join(result_lines)
|
|
110
123
|
|
|
111
124
|
|
|
112
|
-
for each_resource_name, each_resource in self.
|
|
125
|
+
for each_resource_name, each_resource in self.resources.items():
|
|
113
126
|
# image moves app gen time from 70 -> 130 secs
|
|
114
127
|
example_image_content_unused = [
|
|
115
128
|
{
|
|
@@ -126,7 +139,7 @@ class GenAIAdminApp:
|
|
|
126
139
|
]
|
|
127
140
|
messages = [
|
|
128
141
|
{"role": "user", "content": "You are a helpful expert in react and JavaScript"},
|
|
129
|
-
{"role": "user", "content": self.
|
|
142
|
+
{"role": "user", "content": self.admin_app_resource_learning},
|
|
130
143
|
# {"role": "user", "content": example_image_content},
|
|
131
144
|
{"role": "user", "content": f'Schema:\n{self.schema_yaml}'},
|
|
132
145
|
{"role": "user", "content": f'Generate the full javascript source code for the `{each_resource_name}.js` React Admin file, formatted as a JSResponseFormat'}]
|
|
@@ -143,10 +156,23 @@ class GenAIAdminApp:
|
|
|
143
156
|
|
|
144
157
|
|
|
145
158
|
def b_generate_app_js(self):
|
|
159
|
+
|
|
160
|
+
def fix_app(raw_source: str) -> str:
|
|
161
|
+
''' Remove code occasional begin/end code markers <br>
|
|
162
|
+
'''
|
|
163
|
+
source_lines = raw_source.splitlines()
|
|
164
|
+
result_lines = []
|
|
165
|
+
data_provider_import = False
|
|
166
|
+
do_fixup = False
|
|
167
|
+
for each_line in source_lines:
|
|
168
|
+
# fixes here
|
|
169
|
+
result_lines.append(each_line)
|
|
170
|
+
return "\n".join(result_lines) # return source_lines as a string
|
|
171
|
+
|
|
146
172
|
messages = []
|
|
147
173
|
messages = [
|
|
148
174
|
{"role": "user", "content": "You are a helpful expert in react and JavaScript"},
|
|
149
|
-
{"role": "user", "content": self.
|
|
175
|
+
{"role": "user", "content": self.admin_app_js_learning},
|
|
150
176
|
{"role": "user", "content": f'Schema:\n{self.schema_yaml}'},
|
|
151
177
|
{"role": "user", "content": f'Generate the complete App.js that wires together the above resources. for the `app.js` React Admin file, formatted as a JSResponseFormat.'}]
|
|
152
178
|
save_response = self.project_root / f"docs/admin_app/app.js"
|
|
@@ -156,7 +182,9 @@ class GenAIAdminApp:
|
|
|
156
182
|
response_as=JSResponseFormat)
|
|
157
183
|
response_dict = json.loads(output)
|
|
158
184
|
target_file = self.ui_src_path / "App.js"
|
|
159
|
-
|
|
185
|
+
source_code = response_dict['code']
|
|
186
|
+
source_code = fix_app(source_code)
|
|
187
|
+
utils.write_file(target_file, source_code)
|
|
160
188
|
|
|
161
189
|
log.info(f"✅ Wrote: {target_file}\n")
|
|
162
190
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
## Context
|
|
2
|
+
|
|
3
|
+
Generate a per-resource file for a React Admin application using the following instructions.
|
|
4
|
+
The result must be a runnable React app (`npm start`) that connects to the supplied JSON:API, with fully implemented components (no placeholders or empty files).
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
### Per-Resource Files (Required)
|
|
10
|
+
|
|
11
|
+
For each resource (`Customer`, `Order` etc):
|
|
12
|
+
|
|
13
|
+
* Create a source file under `src/`, e.g., `Customer.js`
|
|
14
|
+
* Each file must **fully** implement:
|
|
15
|
+
* `CustomerList`
|
|
16
|
+
* `CustomerShow`
|
|
17
|
+
* `CustomerCreate`
|
|
18
|
+
* `CustomerEdit`
|
|
19
|
+
|
|
20
|
+
Use:
|
|
21
|
+
|
|
22
|
+
- `<ReferenceField>` for foreign key displays
|
|
23
|
+
- `<ReferenceInput>` for foreign key input
|
|
24
|
+
- `<ReferenceManyField>` for tabbed child lists
|
|
25
|
+
- For show pages
|
|
26
|
+
|
|
27
|
+
* Always start with `<SimpleShowLayout>`, followed by a `<TabbedShowLayout>` for related data
|
|
28
|
+
* DO NOT start with `<TabbedShowLayout>`
|
|
29
|
+
|
|
30
|
+
ALWAYS include these 2 imports at the top of the file, with this EXACT formatting, whether or not they are used:
|
|
31
|
+
|
|
32
|
+
```jsx
|
|
33
|
+
import React from 'react';
|
|
34
|
+
import { List, FunctionField, Datagrid, TextField, DateField, NumberField, ReferenceField, ReferenceManyField, Show, TabbedShowLayout, Tab, SimpleShowLayout, TextInput, NumberInput, DateTimeInput, ReferenceInput, SelectInput, Create, SimpleForm, Edit, Filter, Pagination, BooleanField, BooleanInput } from 'react-admin'; // mandatory import
|
|
35
|
+
```
|
|
36
|
+
You may add other imports, but be sure all those are included.
|
|
37
|
+
|
|
38
|
+
DO NOT use `<EmailInput>` - use `<TextInput>`.
|
|
39
|
+
|
|
40
|
+
DO NOT put `<ReferenceField>` in `<Datagrid>`.
|
|
41
|
+
|
|
42
|
+
Do **not leave any file empty**.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## App Features
|
|
47
|
+
|
|
48
|
+
### Multi-Page
|
|
49
|
+
|
|
50
|
+
For each resource:
|
|
51
|
+
|
|
52
|
+
- Create a **List page** showing 7 user-friendly columns
|
|
53
|
+
- Add **pagination**, **sorting**, and **filtering**
|
|
54
|
+
- Link each row to a **Display (Show) page**
|
|
55
|
+
|
|
56
|
+
### Multi-Resource
|
|
57
|
+
|
|
58
|
+
Each **Display Page** should:
|
|
59
|
+
|
|
60
|
+
- Show all fields in a **multi-column layout**
|
|
61
|
+
- Include a **tab sheet** (`<TabbedShowLayout>`) for each related resource using `<ReferenceManyField>`
|
|
62
|
+
- Link child rows to their own display page
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
|
|
66
|
+
- Customer Display has tab for OrderList
|
|
67
|
+
|
|
68
|
+
- The tab (with OrderList) is shown *below* all the Customer fields.
|
|
69
|
+
- Each Order in the tab links to Order Display
|
|
70
|
+
|
|
71
|
+
### Automatic Joins
|
|
72
|
+
|
|
73
|
+
For foreign keys:
|
|
74
|
+
|
|
75
|
+
- Display joined value (e.g., `product.name` instead of `product_id`)
|
|
76
|
+
- Use first string field from parent table containing `name`, `title`, or `description`
|
|
77
|
+
|
|
78
|
+
Numeric Primary key fields:
|
|
79
|
+
|
|
80
|
+
- Display at the end of forms/lists
|
|
81
|
+
|
|
82
|
+
### Lookups (Foreign Keys)
|
|
83
|
+
|
|
84
|
+
For foreign key fields:
|
|
85
|
+
|
|
86
|
+
- Provide auto-complete dropdown (`<ReferenceInput>`)
|
|
87
|
+
- For numeric foreign keys, use the joined string field as lookup text
|
|
88
|
+
|
|
89
|
+
### Cascade Add
|
|
90
|
+
|
|
91
|
+
When adding a child row as a detail in a Master / Detail,
|
|
92
|
+
default the Foreign Key to the Parent (Master) Primary Key.
|
|
93
|
+
|
|
94
|
+
## Implementation
|
|
95
|
+
|
|
96
|
+
### Architecture
|
|
97
|
+
|
|
98
|
+
- **Framework**: React 18 + react-admin 4.x
|
|
99
|
+
- **Data Provider**: Custom pre-built in src/rav4-jsonapi-client
|
|
100
|
+
- **CORS**: Ensure API allows `http://localhost:3000`
|
|
101
|
+
|
|
102
|
+
```py
|
|
103
|
+
from flask_cors import CORS
|
|
104
|
+
CORS(app, origins='*') # or restrict to localhost:3000
|
|
105
|
+
```
|
|
106
|
+
- **Project Setup**:
|
|
107
|
+
|
|
108
|
+
- Use `create-react-app`
|
|
109
|
+
- Include: `react-admin`, `@mui/material`, `@emotion/react`, `@emotion/styled`, `react-router-dom`
|
|
110
|
+
- Do not use any deprecated or unmaintained libraries
|
|
111
|
+
- Include complete and correct `App.js`, `index.js`, `dataProvider.js`, and `index.html`
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Response Format
|
|
115
|
+
|
|
116
|
+
Format the response as a JSResponseFormat:
|
|
117
|
+
|
|
118
|
+
class JSResponseFormat(BaseModel): # must match system/genai/prompt_inserts/response_format.prompt
|
|
119
|
+
code : str # generated javascript code (only)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
### App Wiring
|
|
4
|
+
|
|
5
|
+
Sample code for react `App.js` (follow these guidelines EXACTLY):
|
|
6
|
+
|
|
7
|
+
```jsx
|
|
8
|
+
// begin constant imports (always included) -- generate this code EXACTLY
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { Admin, Resource, Loading } from 'react-admin'; // val? loading
|
|
11
|
+
import { jsonapiClient } from "./rav4-jsonapi-client/ra-jsonapi-client";
|
|
12
|
+
import { createTheme } from '@mui/material/styles';
|
|
13
|
+
import { useConf, loadHomeConf } from "./Config"; // val ??
|
|
14
|
+
// end constant imports
|
|
15
|
+
|
|
16
|
+
// import each resource, e.g.
|
|
17
|
+
import { CustomerList, CustomerShow, CustomerCreate, CustomerEdit } from './Customer';
|
|
18
|
+
...
|
|
19
|
+
|
|
20
|
+
const theme = createTheme({
|
|
21
|
+
palette: {
|
|
22
|
+
primary: { main: '#1976d2' }, // Material-UI default blue
|
|
23
|
+
secondary: { main: '#1565c0' }, // A darker blue, or choose another color
|
|
24
|
+
},
|
|
25
|
+
typography: { fontSize: 14 },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const App = () => {
|
|
29
|
+
const [conf, setConf] = React.useState({});
|
|
30
|
+
|
|
31
|
+
React.useEffect(() => {
|
|
32
|
+
const fetchData = async () => {
|
|
33
|
+
try {
|
|
34
|
+
console.log('loading HomeConf-1')
|
|
35
|
+
const conf = await loadHomeConf()
|
|
36
|
+
setConf(conf)
|
|
37
|
+
setLoading(false);
|
|
38
|
+
console.log('AppConf0: ', conf);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('Error fetching data:', error);
|
|
41
|
+
sessionStorage.removeItem("raSpa");
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
fetchData();
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
if (loading) {
|
|
48
|
+
return <Loading loadingPrimary="Loading..." loadingSecondary="Please wait" />;
|
|
49
|
+
}
|
|
50
|
+
const dataProvider = jsonapiClient(conf.api_root, { conf: {} }, null);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
// register each resource (do NOT generate {dataProvider(conf.api_root)}...
|
|
54
|
+
<Admin dataProvider={dataProvider} theme={theme}>
|
|
55
|
+
<Resource name="Customer" list={CustomerList} show={CustomerShow} edit={CustomerEdit} create={CustomerCreate} />
|
|
56
|
+
...
|
|
57
|
+
</Admin>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default App;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Response Format
|
|
67
|
+
|
|
68
|
+
Format the response as a JSResponseFormat:
|
|
69
|
+
|
|
70
|
+
class JSResponseFormat(BaseModel): # must match system/genai/prompt_inserts/response_format.prompt
|
|
71
|
+
code : str # generated javascript code (only)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Backend JSONAPI endpoint metadata is described in the following <resources> section , each key is a resource collection endpoint name.
|
|
2
|
+
The tab_groups attribute describes the resource relationships, with fks being the foreign keys of the related resource.
|
|
3
|
+
user_key tells which attribute should be shown when referencing the resource. for example, if the user_key is "name", the resource should be be shown by its "name" in the UI, while its reference should be by its "id".
|
|
4
|
+
|
|
5
|
+
<resources></resources>
|
|
6
|
+
|
|
7
|
+
Most of the time, the resource name key will be the same as the type,
|
|
8
|
+
so you can use an instance type to get the resource configuration.
|
|
9
|
+
|
|
10
|
+
ignore SPAPage and SPASection resources.
|
|
11
|
+
|
|
12
|
+
This resource configuration can be used when importing the Config getConf() function in the react code, for example:
|
|
13
|
+
|
|
14
|
+
<javascriptCode>
|
|
15
|
+
import { getConf } from '../../Config';
|
|
16
|
+
const conf = getConf();
|
|
17
|
+
const resources = conf.resources;
|
|
18
|
+
</javascriptCode>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
This JSONAPI is fetched using the react-admin dataProvider (useDataprovider hook).
|
|
2
|
+
All resources have a "type" and "id" attributes (according to the JSONAPI specification).
|
|
3
|
+
|
|
4
|
+
Besides the regular parameters, the dataProvider is extended to interpret the "include" meta parameter to retrieve included relationships.
|
|
5
|
+
|
|
6
|
+
<javascriptCode>
|
|
7
|
+
dataProvider.getList(resourceName, {
|
|
8
|
+
pagination: { page: 1, perPage: 10 },
|
|
9
|
+
meta: { include: ["relationship_name"]}
|
|
10
|
+
})
|
|
11
|
+
</javascriptCode>
|
|
12
|
+
|
|
13
|
+
attributes are inlined in the instance:
|
|
14
|
+
for example, if the resource is "some_resource" and the attribute is "name", then 'some_resource.name' will be the attribute value.
|
|
15
|
+
|
|
16
|
+
included relationships are inlined in the instance:
|
|
17
|
+
for example, if the resource is "some_resource" and the relationship is "relationship_name", the included data will be in the instance "relationship_name" key (some_resource.relationship_name).
|
|
18
|
+
So:
|
|
19
|
+
some_resource.relationship_name.id will be the id of the included (toone) relationship.
|
|
20
|
+
some_resource.relationship_name will be an array of included (tomany) relationships.
|
|
21
|
+
|
|
22
|
+
instances have a "relationships" key, which contains a dictionary of the relationships, for example,
|
|
23
|
+
following is the response for a resource with a tomany relationship named "tomany_relationships_name"
|
|
24
|
+
<json>
|
|
25
|
+
{
|
|
26
|
+
"tomany_relationships_name": {
|
|
27
|
+
"data": [
|
|
28
|
+
{
|
|
29
|
+
"id": "1",
|
|
30
|
+
"type": "Transaction"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"meta": {
|
|
34
|
+
"count": 1,
|
|
35
|
+
"limit": 5,
|
|
36
|
+
"total": 1
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"toone_relationsip_name": {
|
|
40
|
+
"data": {
|
|
41
|
+
"id": "1",
|
|
42
|
+
"type": "Customer"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
</json>
|
|
47
|
+
|
|
48
|
+
The actual relationship data is in the "data" key of the relationship.
|
|
49
|
+
for example, the 'instance.tomany_relationships_name' will be an array of the instances data of the related resource:
|
|
50
|
+
<json>
|
|
51
|
+
[
|
|
52
|
+
{
|
|
53
|
+
"id": "1",
|
|
54
|
+
"ja_type": "Transaction",
|
|
55
|
+
"attributes": {
|
|
56
|
+
"Type": "withdrawal",
|
|
57
|
+
"account_id": 1,
|
|
58
|
+
"amount": 500,
|
|
59
|
+
"description": "Grocery Shopping",
|
|
60
|
+
"transaction_date": "2022-03-01"
|
|
61
|
+
},
|
|
62
|
+
"Type": "withdrawal",
|
|
63
|
+
"account_id": 1,
|
|
64
|
+
"amount": 500,
|
|
65
|
+
"description": "Grocery Shopping",
|
|
66
|
+
"transaction_date": "2022-03-01",
|
|
67
|
+
"relationships": {
|
|
68
|
+
"account": {
|
|
69
|
+
"data": null
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"account": null
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
</json>
|
|
76
|
+
|
|
77
|
+
similarly, the 'instance.toone_relationship_name' will be the instance data of the related resource:
|
|
78
|
+
<json>
|
|
79
|
+
{
|
|
80
|
+
"id": "1",
|
|
81
|
+
"credit_limit": 10000,
|
|
82
|
+
"first_name": "Alice",
|
|
83
|
+
"last_name": "Brown",
|
|
84
|
+
}
|
|
85
|
+
</json>
|
|
86
|
+
if a toone relationship is empty, it's value will be null.
|
|
87
|
+
|
|
88
|
+
if you want to fetch all related resources, you can use the 'meta: { include: ["+all"]}' parameter in the dataProvider.getList call.
|
|
89
|
+
|
|
@@ -56,12 +56,7 @@ default the Foreign Key to the Parent (Master) Primary Key.
|
|
|
56
56
|
### Architecture
|
|
57
57
|
|
|
58
58
|
- **Framework**: React 18 + react-admin 4.x
|
|
59
|
-
- **Data Provider**: Custom
|
|
60
|
-
|
|
61
|
-
- Must support: `getList`, `getOne`, `getMany`, `getManyReference`, `create`, `update`, `delete`
|
|
62
|
-
- Must support: filters, joins, sorting, pagination
|
|
63
|
-
|
|
64
|
-
- **Backend**: JSON:API per `mcp_discovery.json`
|
|
59
|
+
- **Data Provider**: Custom pre-built in src/rav4-jsonapi-client
|
|
65
60
|
- **CORS**: Ensure API allows `http://localhost:3000`
|
|
66
61
|
|
|
67
62
|
```py
|
|
@@ -116,19 +111,19 @@ Do **not leave any file empty**.
|
|
|
116
111
|
|
|
117
112
|
### App Wiring
|
|
118
113
|
|
|
119
|
-
Sample code for `App.js
|
|
120
|
-
|
|
114
|
+
Sample code for `App.js` (follow these guidelines EXACTLY):
|
|
121
115
|
|
|
122
116
|
```jsx
|
|
117
|
+
// begin constant imports (always included) -- generate this code EXACTLY
|
|
123
118
|
import React from 'react';
|
|
124
|
-
import { Admin, Resource } from 'react-admin';
|
|
119
|
+
import { Admin, Resource, Loading } from 'react-admin'; // val? loading
|
|
125
120
|
import { createTheme } from '@mui/material/styles';
|
|
121
|
+
import { useConf, loadHomeConf } from "./Config"; // val ??
|
|
122
|
+
// end constant imports
|
|
126
123
|
|
|
127
|
-
// import each resource
|
|
124
|
+
// import each resource, e.g.
|
|
128
125
|
import { CustomerList, CustomerShow, CustomerCreate, CustomerEdit } from './Customer';
|
|
129
126
|
...
|
|
130
|
-
// import the data provider
|
|
131
|
-
import { dataProvider } from './dataProvider';
|
|
132
127
|
|
|
133
128
|
const theme = createTheme({
|
|
134
129
|
palette: {
|
|
@@ -139,8 +134,32 @@ const theme = createTheme({
|
|
|
139
134
|
});
|
|
140
135
|
|
|
141
136
|
const App = () => {
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
const [conf, setConf] = React.useState({});
|
|
138
|
+
|
|
139
|
+
React.useEffect(() => {
|
|
140
|
+
const fetchData = async () => {
|
|
141
|
+
try {
|
|
142
|
+
console.log('loading HomeConf-1')
|
|
143
|
+
const conf = await loadHomeConf()
|
|
144
|
+
setConf(conf)
|
|
145
|
+
setLoading(false);
|
|
146
|
+
console.log('AppConf0: ', conf);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error('Error fetching data:', error);
|
|
149
|
+
sessionStorage.removeItem("raSpa");
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
fetchData();
|
|
153
|
+
}, []);
|
|
154
|
+
|
|
155
|
+
if (loading) {
|
|
156
|
+
return <Loading loadingPrimary="Loading..." loadingSecondary="Please wait" />;
|
|
157
|
+
}
|
|
158
|
+
const dataProvider = jsonapiClient(conf.api_root, { conf: {} }, null);
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
// register each resource (do NOT generate {dataProvider(conf.api_root)}...
|
|
162
|
+
<Admin dataProvider={dataProvider} theme={theme}>
|
|
144
163
|
<Resource name="Customer" list={CustomerList} show={CustomerShow} edit={CustomerEdit} create={CustomerCreate} />
|
|
145
164
|
...
|
|
146
165
|
</Admin>
|
|
@@ -150,16 +169,6 @@ const App = () => {
|
|
|
150
169
|
export default App;
|
|
151
170
|
```
|
|
152
171
|
|
|
153
|
-
For dataProvider:
|
|
154
|
-
|
|
155
|
-
1. be sure it includes the braces: `import { dataProvider }`
|
|
156
|
-
2. Do Not generate either:
|
|
157
|
-
|
|
158
|
-
```jsx
|
|
159
|
-
import jsonServerProvider from 'ra-data-json-server'
|
|
160
|
-
const dataProvider = jsonServerProvider('http://api.example.com');
|
|
161
|
-
```
|
|
162
|
-
|
|
163
172
|
---
|
|
164
173
|
|
|
165
174
|
## Response Format
|
api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/package.json
CHANGED
|
@@ -10,11 +10,14 @@
|
|
|
10
10
|
"@testing-library/jest-dom": "^6.6.3",
|
|
11
11
|
"@testing-library/react": "^16.3.0",
|
|
12
12
|
"@testing-library/user-event": "^13.5.0",
|
|
13
|
+
"compare-versions": "^6.1.1",
|
|
14
|
+
"keycloak-js": "^26.2.0",
|
|
13
15
|
"react": "^19.1.0",
|
|
14
16
|
"react-admin": "^5.8.3",
|
|
15
17
|
"react-dom": "^19.1.0",
|
|
16
18
|
"react-router-dom": "^7.6.2",
|
|
17
19
|
"react-scripts": "5.0.1",
|
|
20
|
+
"url-join": "^5.0.0",
|
|
18
21
|
"web-vitals": "^2.1.4"
|
|
19
22
|
},
|
|
20
23
|
"scripts": {
|