ApiLogicServer 15.0.19__py3-none-any.whl → 15.0.22__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 +4 -4
- api_logic_server_cli/api_logic_server_info.yaml +2 -2
- api_logic_server_cli/genai/genai_admin_app.py +33 -9
- api_logic_server_cli/prototypes/.DS_Store +0 -0
- 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-App-Learning-Prompt.md → z-unused-Admin-App-Learning-Prompt.md} +60 -35
- 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
- api_logic_server_cli/prototypes/nw/.DS_Store +0 -0
- api_logic_server_cli/prototypes/nw/ui/.DS_Store +0 -0
- api_logic_server_cli/prototypes/nw/ui/react_admin/.DS_Store +0 -0
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/App.js +30 -31
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Category.js +62 -62
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Customer.js +143 -48
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/CustomerDemographic.js +20 -37
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Department.js +38 -39
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Employee.js +85 -134
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/EmployeeAudit.js +89 -77
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/EmployeeTerritory.js +59 -59
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Location.js +45 -49
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Order.js +42 -60
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/OrderDetail.js +97 -106
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Product.js +60 -62
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Region.js +36 -41
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/SampleDBVersion.js +73 -0
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Shipper.js +57 -54
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Supplier.js +71 -87
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Territory.js +47 -41
- api_logic_server_cli/prototypes/nw/ui/react_admin/src/Union.js +18 -34
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/METADATA +1 -1
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/RECORD +50 -31
- api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/dataProvider.js +0 -110
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/WHEEL +0 -0
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/entry_points.txt +0 -0
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/licenses/LICENSE +0 -0
- {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
interface Relationship {
|
|
2
|
+
data: null | { id: string; type: string } | Array<{ id: string; type: string }>;
|
|
3
|
+
relationships?: { [key: string]: Relationship };
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A map-like class that maps resource linkage objects {id: 1, type: "user"} to concrete resources with attributes and
|
|
8
|
+
* relationships
|
|
9
|
+
*/
|
|
10
|
+
export default class ResourceLookup {
|
|
11
|
+
lookup: Map<any, any>;
|
|
12
|
+
includes: string[];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Constructs a new lookup map
|
|
16
|
+
* @param {Object} response A JSON API response, in JSON format
|
|
17
|
+
*/
|
|
18
|
+
constructor(response: any) {
|
|
19
|
+
this.lookup = new Map();
|
|
20
|
+
this.includes = [];
|
|
21
|
+
|
|
22
|
+
// If the response wasn't a JSON dictionary, we can't and don't need to build a lookup
|
|
23
|
+
if (typeof response !== 'object') return;
|
|
24
|
+
|
|
25
|
+
let resources;
|
|
26
|
+
// if (response.hasOwnProperty('included')) {
|
|
27
|
+
if (Object.prototype.hasOwnProperty.call(response, 'included')) {
|
|
28
|
+
resources = [...response.data, ...response.included];
|
|
29
|
+
} else {
|
|
30
|
+
resources = response.data;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Iterate over each resource returned and put each in the lookup
|
|
34
|
+
for (const entry of resources) {
|
|
35
|
+
const key = this.getKey(entry);
|
|
36
|
+
this.lookup.set(key, entry);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Calculates a hashable key for JSON API resources
|
|
42
|
+
* @param resource A resource linkage object
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
getKey(resource: any) {
|
|
46
|
+
return `${resource.type}:${resource.id}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Looks up a resource
|
|
51
|
+
* @param resource A resource linkage object
|
|
52
|
+
* @returns {Object}
|
|
53
|
+
*/
|
|
54
|
+
get(resource: any) {
|
|
55
|
+
// If we don't have included data for this resource, just return the Resource Linkage object, since that's still
|
|
56
|
+
// useful
|
|
57
|
+
if (this.has(resource)) {
|
|
58
|
+
return this.lookup.get(this.getKey(resource));
|
|
59
|
+
} else {
|
|
60
|
+
return structuredClone(resource);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns true if the resource is in the lookup
|
|
66
|
+
* @param resource
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
has(resource: any) {
|
|
70
|
+
return this.lookup.has(this.getKey(resource));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Converts a JSON API data object (with id, type, and attributes fields) into a flattened object
|
|
75
|
+
* @param {Object} response A JSON API data object
|
|
76
|
+
*/
|
|
77
|
+
unwrapData(response: any) {
|
|
78
|
+
// The base resource object, merge the attributes and the id/type fields
|
|
79
|
+
const result = Object.assign(
|
|
80
|
+
{
|
|
81
|
+
id: response?.id,
|
|
82
|
+
ja_type: response?.type,
|
|
83
|
+
type: response?.Type || response?.type,
|
|
84
|
+
attributes: response.attributes || {},
|
|
85
|
+
},
|
|
86
|
+
response.attributes
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Deal with relationships
|
|
90
|
+
if (Object.prototype.hasOwnProperty.call(response, 'relationships')) {
|
|
91
|
+
result.relationships = response.relationships;
|
|
92
|
+
for (const [relationshipName, relationship] of Object.entries(response.relationships)) {
|
|
93
|
+
if ((relationship as Relationship).data === null) {
|
|
94
|
+
result[relationshipName] = null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!(relationship as Relationship).data) {
|
|
98
|
+
continue;
|
|
99
|
+
} else if (Array.isArray((relationship as Relationship).data && (relationship as Relationship).data)) {
|
|
100
|
+
result[relationshipName] = (relationship as Relationship).data?.map((linkage: any) => {
|
|
101
|
+
const resource = this.get(linkage);
|
|
102
|
+
const lresult = structuredClone(this.unwrapData(resource));
|
|
103
|
+
Object.entries(lresult.attributes || {}).map(([key, value]) => {
|
|
104
|
+
lresult[key] = value;
|
|
105
|
+
});
|
|
106
|
+
result.relationships[relationshipName].data = result[relationshipName];
|
|
107
|
+
return lresult;
|
|
108
|
+
});
|
|
109
|
+
} else if ((relationship as Relationship).data?.id) {
|
|
110
|
+
const resource = this.get((relationship as Relationship).data);
|
|
111
|
+
result[relationshipName] = this.unwrapData(resource);
|
|
112
|
+
result.relationships[relationshipName].data = result[relationshipName];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
JSON.stringify(structuredClone(result));
|
|
119
|
+
} catch (e) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return structuredClone(result);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,59 +1,58 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Admin, Resource } from 'react-admin';
|
|
3
3
|
import { createTheme } from '@mui/material/styles';
|
|
4
|
-
|
|
5
|
-
// Import DataProvider
|
|
4
|
+
// import data provider
|
|
6
5
|
import { dataProvider } from './dataProvider';
|
|
7
6
|
|
|
8
|
-
// Import resource components
|
|
7
|
+
// Import all resource components
|
|
9
8
|
import { CustomerList, CustomerShow, CustomerCreate, CustomerEdit } from './Customer';
|
|
10
|
-
import { CategoryList, CategoryShow, CategoryCreate, CategoryEdit } from './Category';
|
|
11
9
|
import { OrderList, OrderShow, OrderCreate, OrderEdit } from './Order';
|
|
12
10
|
import { ProductList, ProductShow, ProductCreate, ProductEdit } from './Product';
|
|
11
|
+
import { CategoryList, CategoryShow, CategoryCreate, CategoryEdit } from './Category';
|
|
13
12
|
import { EmployeeList, EmployeeShow, EmployeeCreate, EmployeeEdit } from './Employee';
|
|
13
|
+
import { DepartmentList, DepartmentShow, DepartmentCreate, DepartmentEdit } from './Department';
|
|
14
14
|
import { SupplierList, SupplierShow, SupplierCreate, SupplierEdit } from './Supplier';
|
|
15
15
|
import { ShipperList, ShipperShow, ShipperCreate, ShipperEdit } from './Shipper';
|
|
16
|
-
import { RegionList, RegionShow, RegionCreate, RegionEdit } from './Region';
|
|
17
16
|
import { TerritoryList, TerritoryShow, TerritoryCreate, TerritoryEdit } from './Territory';
|
|
18
17
|
import { CustomerDemographicList, CustomerDemographicShow, CustomerDemographicCreate, CustomerDemographicEdit } from './CustomerDemographic';
|
|
19
18
|
import { EmployeeAuditList, EmployeeAuditShow, EmployeeAuditCreate, EmployeeAuditEdit } from './EmployeeAudit';
|
|
20
19
|
import { EmployeeTerritoryList, EmployeeTerritoryShow, EmployeeTerritoryCreate, EmployeeTerritoryEdit } from './EmployeeTerritory';
|
|
21
|
-
import { DepartmentList, DepartmentShow, DepartmentCreate, DepartmentEdit } from './Department';
|
|
22
|
-
import { UnionList, UnionShow, UnionCreate, UnionEdit } from './Union';
|
|
23
20
|
import { LocationList, LocationShow, LocationCreate, LocationEdit } from './Location';
|
|
24
21
|
import { OrderDetailList, OrderDetailShow, OrderDetailCreate, OrderDetailEdit } from './OrderDetail';
|
|
22
|
+
import { RegionList, RegionShow, RegionCreate, RegionEdit } from './Region';
|
|
23
|
+
import { SampleDBVersionList, SampleDBVersionShow, SampleDBVersionCreate, SampleDBVersionEdit } from './SampleDBVersion';
|
|
24
|
+
import { UnionList, UnionShow, UnionCreate, UnionEdit } from './Union';
|
|
25
25
|
|
|
26
|
-
// Define Material-UI Theme
|
|
27
26
|
const theme = createTheme({
|
|
28
27
|
palette: {
|
|
29
|
-
primary: { main: '#1976d2' },
|
|
30
|
-
secondary: { main: '#1565c0' },
|
|
28
|
+
primary: { main: '#1976d2' },
|
|
29
|
+
secondary: { main: '#1565c0' },
|
|
31
30
|
},
|
|
32
31
|
typography: { fontSize: 14 },
|
|
33
32
|
});
|
|
34
33
|
|
|
35
34
|
const App = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
return (
|
|
36
|
+
<Admin dataProvider={dataProvider} theme={theme}>
|
|
37
|
+
<Resource name="Customer" list={CustomerList} show={CustomerShow} edit={CustomerEdit} create={CustomerCreate} />
|
|
38
|
+
<Resource name="Order" list={OrderList} show={OrderShow} edit={OrderEdit} create={OrderCreate} />
|
|
39
|
+
<Resource name="Product" list={ProductList} show={ProductShow} edit={ProductEdit} create={ProductCreate} />
|
|
40
|
+
<Resource name="Category" list={CategoryList} show={CategoryShow} edit={CategoryEdit} create={CategoryCreate} />
|
|
41
|
+
<Resource name="Employee" list={EmployeeList} show={EmployeeShow} edit={EmployeeEdit} create={EmployeeCreate} />
|
|
42
|
+
<Resource name="Department" list={DepartmentList} show={DepartmentShow} edit={DepartmentEdit} create={DepartmentCreate} />
|
|
43
|
+
<Resource name="Supplier" list={SupplierList} show={SupplierShow} edit={SupplierEdit} create={SupplierCreate} />
|
|
44
|
+
<Resource name="Shipper" list={ShipperList} show={ShipperShow} edit={ShipperEdit} create={ShipperCreate} />
|
|
45
|
+
<Resource name="Territory" list={TerritoryList} show={TerritoryShow} edit={TerritoryEdit} create={TerritoryCreate} />
|
|
46
|
+
<Resource name="CustomerDemographic" list={CustomerDemographicList} show={CustomerDemographicShow} edit={CustomerDemographicEdit} create={CustomerDemographicCreate} />
|
|
47
|
+
<Resource name="EmployeeAudit" list={EmployeeAuditList} show={EmployeeAuditShow} edit={EmployeeAuditEdit} create={EmployeeAuditCreate} />
|
|
48
|
+
<Resource name="EmployeeTerritory" list={EmployeeTerritoryList} show={EmployeeTerritoryShow} edit={EmployeeTerritoryEdit} create={EmployeeTerritoryCreate} />
|
|
49
|
+
<Resource name="Location" list={LocationList} show={LocationShow} edit={LocationEdit} create={LocationCreate} />
|
|
50
|
+
<Resource name="OrderDetail" list={OrderDetailList} show={OrderDetailShow} edit={OrderDetailEdit} create={OrderDetailCreate} />
|
|
51
|
+
<Resource name="Region" list={RegionList} show={RegionShow} edit={RegionEdit} create={RegionCreate} />
|
|
52
|
+
<Resource name="SampleDBVersion" list={SampleDBVersionList} show={SampleDBVersionShow} edit={SampleDBVersionEdit} create={SampleDBVersionCreate} />
|
|
53
|
+
<Resource name="Union" list={UnionList} show={UnionShow} edit={UnionEdit} create={UnionCreate} />
|
|
54
|
+
</Admin>
|
|
55
|
+
);
|
|
57
56
|
};
|
|
58
57
|
|
|
59
58
|
export default App;
|
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
```jsx
|
|
2
1
|
import React from 'react';
|
|
3
2
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
List,
|
|
4
|
+
Datagrid,
|
|
5
|
+
TextField,
|
|
6
|
+
NumberField,
|
|
7
|
+
ReferenceField,
|
|
8
|
+
Show,
|
|
9
|
+
SimpleShowLayout,
|
|
10
|
+
TabbedShowLayout,
|
|
11
|
+
Tab,
|
|
12
|
+
TextInput,
|
|
13
|
+
NumberInput,
|
|
14
|
+
ReferenceManyField,
|
|
15
|
+
ReferenceInput,
|
|
16
|
+
SelectInput,
|
|
17
|
+
Create,
|
|
18
|
+
SimpleForm,
|
|
19
|
+
Edit,
|
|
20
|
+
Filter,
|
|
8
21
|
} from 'react-admin';
|
|
9
22
|
|
|
10
|
-
//
|
|
23
|
+
// Filters for Category List
|
|
24
|
+
//theme color;
|
|
11
25
|
const CategoryFilter = (props) => (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
<Filter {...props}>
|
|
27
|
+
<TextInput label="Search" source="q" alwaysOn />
|
|
28
|
+
<TextInput label="Category Name" source="CategoryName_ColumnName" />
|
|
29
|
+
<TextInput label="Description" source="Description" />
|
|
30
|
+
</Filter>
|
|
17
31
|
);
|
|
18
32
|
|
|
19
|
-
//
|
|
20
|
-
const CategoryPagination = props => <Pagination rowsPerPageOptions={[7]} {...props} />;
|
|
21
|
-
|
|
22
|
-
// List view for Categories
|
|
33
|
+
// Category List
|
|
23
34
|
export const CategoryList = (props) => (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</List>
|
|
35
|
+
<List filters={<CategoryFilter />} {...props} perPage={7}>
|
|
36
|
+
<Datagrid rowClick="show">
|
|
37
|
+
<TextField source="CategoryName_ColumnName" label="Category Name" />
|
|
38
|
+
<TextField source="Description" />
|
|
39
|
+
</Datagrid>
|
|
40
|
+
</List>
|
|
31
41
|
);
|
|
32
42
|
|
|
33
|
-
// Show
|
|
43
|
+
// Category Show
|
|
34
44
|
export const CategoryShow = (props) => (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
<Show {...props}>
|
|
46
|
+
<SimpleShowLayout>
|
|
47
|
+
<TextField source="CategoryName_ColumnName" label="Category Name" />
|
|
48
|
+
<TextField source="Description" />
|
|
49
|
+
<NumberField source="Id" label="ID" />
|
|
50
|
+
<ReferenceManyField reference="Product" target="CategoryId" label="Products">
|
|
41
51
|
<TabbedShowLayout>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<Datagrid rowClick="show">
|
|
49
|
-
<TextField source="ProductName" label="Product Name" />
|
|
50
|
-
</Datagrid>
|
|
51
|
-
</ReferenceManyField>
|
|
52
|
-
</Tab>
|
|
52
|
+
<Tab label="Products">
|
|
53
|
+
<Datagrid rowClick="show">
|
|
54
|
+
<TextField source="ProductName" label="Product Name" />
|
|
55
|
+
<NumberField source="UnitPrice" label="Unit Price" />
|
|
56
|
+
</Datagrid>
|
|
57
|
+
</Tab>
|
|
53
58
|
</TabbedShowLayout>
|
|
54
|
-
|
|
59
|
+
</ReferenceManyField>
|
|
60
|
+
</SimpleShowLayout>
|
|
61
|
+
</Show>
|
|
55
62
|
);
|
|
56
63
|
|
|
57
|
-
// Create
|
|
64
|
+
// Category Create
|
|
58
65
|
export const CategoryCreate = (props) => (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
</ReferenceInput>
|
|
66
|
-
</SimpleForm>
|
|
67
|
-
</Create>
|
|
66
|
+
<Create {...props}>
|
|
67
|
+
<SimpleForm>
|
|
68
|
+
<TextInput source="CategoryName_ColumnName" label="Category Name" />
|
|
69
|
+
<TextInput multiline source="Description" />
|
|
70
|
+
</SimpleForm>
|
|
71
|
+
</Create>
|
|
68
72
|
);
|
|
69
73
|
|
|
70
|
-
// Edit
|
|
74
|
+
// Category Edit
|
|
71
75
|
export const CategoryEdit = (props) => (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
</ReferenceInput>
|
|
79
|
-
</SimpleForm>
|
|
80
|
-
</Edit>
|
|
76
|
+
<Edit {...props}>
|
|
77
|
+
<SimpleForm>
|
|
78
|
+
<TextInput source="CategoryName_ColumnName" label="Category Name" />
|
|
79
|
+
<TextInput multiline source="Description" />
|
|
80
|
+
</SimpleForm>
|
|
81
|
+
</Edit>
|
|
81
82
|
);
|
|
82
|
-
```
|
|
@@ -1,51 +1,134 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
TextField,
|
|
6
|
-
NumberField,
|
|
7
|
-
Show,
|
|
8
|
-
SimpleShowLayout,
|
|
9
|
-
TabbedShowLayout,
|
|
10
|
-
Tab,
|
|
11
|
-
ReferenceManyField,
|
|
12
|
-
TextInput,
|
|
13
|
-
Edit,
|
|
14
|
-
SimpleForm,
|
|
15
|
-
Create,
|
|
16
|
-
NumberInput,
|
|
17
|
-
Pagination,
|
|
18
|
-
Filter,
|
|
19
|
-
ReferenceField,
|
|
20
|
-
FunctionField
|
|
21
|
-
} from 'react-admin';
|
|
22
|
-
import { Grid, Box } from '@mui/material';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
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, TopToolbar, Button, useListContext } from 'react-admin'; // mandatory import
|
|
3
|
+
import { ToggleButton, ToggleButtonGroup, Box, Card, CardContent, CardActions, Typography } from '@mui/material';
|
|
4
|
+
import { ViewList, ViewModule } from '@mui/icons-material';
|
|
23
5
|
|
|
24
|
-
// Filters for the
|
|
6
|
+
// Filters for the list view
|
|
25
7
|
const CustomerFilter = (props) => (
|
|
26
8
|
<Filter {...props}>
|
|
27
|
-
<TextInput label="Search
|
|
28
|
-
<TextInput label="
|
|
9
|
+
<TextInput label="Search" source="q" alwaysOn />
|
|
10
|
+
<TextInput label="Company Name" source="CompanyName" />
|
|
11
|
+
<TextInput label="Contact Name" source="ContactName" />
|
|
12
|
+
<TextInput label="City" source="City" />
|
|
13
|
+
<TextInput label="Country" source="Country" />
|
|
29
14
|
</Filter>
|
|
30
15
|
);
|
|
31
16
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
17
|
+
// Card view component for customers
|
|
18
|
+
const CustomerCard = ({ record, ...props }) => (
|
|
19
|
+
<Card sx={{ margin: 1, minWidth: 300, maxWidth: 350 }}>
|
|
20
|
+
<CardContent>
|
|
21
|
+
<Typography variant="h6" component="div" gutterBottom>
|
|
22
|
+
{record.CompanyName}
|
|
23
|
+
</Typography>
|
|
24
|
+
<Typography variant="body2" color="text.secondary">
|
|
25
|
+
Contact: {record.ContactName}
|
|
26
|
+
</Typography>
|
|
27
|
+
<Typography variant="body2" color="text.secondary">
|
|
28
|
+
{record.Address && `${record.Address}, `}{record.City}
|
|
29
|
+
{record.Region && `, ${record.Region}`}
|
|
30
|
+
</Typography>
|
|
31
|
+
<Typography variant="body2" color="text.secondary">
|
|
32
|
+
{record.Country}
|
|
33
|
+
</Typography>
|
|
34
|
+
{record.Phone && (
|
|
35
|
+
<Typography variant="body2" color="text.secondary">
|
|
36
|
+
Phone: {record.Phone}
|
|
37
|
+
</Typography>
|
|
38
|
+
)}
|
|
39
|
+
{record.Balance && (
|
|
40
|
+
<Typography variant="body2" color="text.primary" sx={{ mt: 1, fontWeight: 'bold' }}>
|
|
41
|
+
Balance: ${record.Balance.toLocaleString()}
|
|
42
|
+
</Typography>
|
|
43
|
+
)}
|
|
44
|
+
</CardContent>
|
|
45
|
+
<CardActions>
|
|
46
|
+
<Button
|
|
47
|
+
size="small"
|
|
48
|
+
onClick={() => window.location.href = `#/Customer/${record.Id}/show`}
|
|
49
|
+
>
|
|
50
|
+
View Details
|
|
51
|
+
</Button>
|
|
52
|
+
<Button
|
|
53
|
+
size="small"
|
|
54
|
+
onClick={() => window.location.href = `#/Customer/${record.Id}`}
|
|
55
|
+
>
|
|
56
|
+
Edit
|
|
57
|
+
</Button>
|
|
58
|
+
</CardActions>
|
|
59
|
+
</Card>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Custom list actions with view toggle
|
|
63
|
+
const CustomerListActions = ({ viewMode, setViewMode }) => (
|
|
64
|
+
<TopToolbar>
|
|
65
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
66
|
+
<ToggleButtonGroup
|
|
67
|
+
value={viewMode}
|
|
68
|
+
exclusive
|
|
69
|
+
onChange={(event, newView) => {
|
|
70
|
+
if (newView !== null) {
|
|
71
|
+
setViewMode(newView);
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
aria-label="view mode"
|
|
75
|
+
size="small"
|
|
76
|
+
>
|
|
77
|
+
<ToggleButton value="list" aria-label="list view">
|
|
78
|
+
<ViewList />
|
|
79
|
+
</ToggleButton>
|
|
80
|
+
<ToggleButton value="cards" aria-label="card view">
|
|
81
|
+
<ViewModule />
|
|
82
|
+
</ToggleButton>
|
|
83
|
+
</ToggleButtonGroup>
|
|
84
|
+
</Box>
|
|
85
|
+
</TopToolbar>
|
|
46
86
|
);
|
|
47
87
|
|
|
48
|
-
//
|
|
88
|
+
// Custom card grid component that uses react-admin's data context
|
|
89
|
+
const CustomerCardGrid = () => {
|
|
90
|
+
const { data, isLoading } = useListContext();
|
|
91
|
+
|
|
92
|
+
if (isLoading) return <div>Loading...</div>;
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, padding: 2 }}>
|
|
96
|
+
{data && data.map((record) => (
|
|
97
|
+
<CustomerCard key={record.Id} record={record} />
|
|
98
|
+
))}
|
|
99
|
+
</Box>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const CustomerList = (props) => {
|
|
104
|
+
const [viewMode, setViewMode] = useState('list');
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<List
|
|
108
|
+
filters={<CustomerFilter />}
|
|
109
|
+
{...props}
|
|
110
|
+
perPage={viewMode === 'cards' ? 12 : 7}
|
|
111
|
+
pagination={<Pagination />}
|
|
112
|
+
actions={<CustomerListActions viewMode={viewMode} setViewMode={setViewMode} />}
|
|
113
|
+
>
|
|
114
|
+
{viewMode === 'list' ? (
|
|
115
|
+
<Datagrid rowClick="show">
|
|
116
|
+
<TextField source="CompanyName" label="Company Name" />
|
|
117
|
+
<TextField source="ContactName" label="Contact Name" />
|
|
118
|
+
<TextField source="Address" label="Address" />
|
|
119
|
+
<TextField source="City" label="City" />
|
|
120
|
+
<TextField source="Country" label="Country" />
|
|
121
|
+
<TextField source="Phone" label="Phone" />
|
|
122
|
+
<TextField source="Fax" label="Fax" />
|
|
123
|
+
<NumberField source="Id" label="Customer ID"/>
|
|
124
|
+
</Datagrid>
|
|
125
|
+
) : (
|
|
126
|
+
<CustomerCardGrid />
|
|
127
|
+
)}
|
|
128
|
+
</List>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
49
132
|
export const CustomerShow = (props) => (
|
|
50
133
|
<Show {...props}>
|
|
51
134
|
<SimpleShowLayout>
|
|
@@ -59,18 +142,27 @@ export const CustomerShow = (props) => (
|
|
|
59
142
|
<TextField source="Country" label="Country" />
|
|
60
143
|
<TextField source="Phone" label="Phone" />
|
|
61
144
|
<TextField source="Fax" label="Fax" />
|
|
62
|
-
|
|
145
|
+
<NumberField source="Balance" options={{ style: 'currency', currency: 'USD' }} label="Balance" />
|
|
146
|
+
<NumberField source="CreditLimit" options={{ style: 'currency', currency: 'USD' }} label="Credit Limit" />
|
|
147
|
+
<NumberField source="OrderCount" label="Order Count" />
|
|
148
|
+
<NumberField source="UnpaidOrderCount" label="Unpaid Orders" />
|
|
149
|
+
<NumberField source="Id" label="Customer ID" />
|
|
150
|
+
|
|
63
151
|
<TabbedShowLayout>
|
|
64
|
-
<Tab label="
|
|
152
|
+
<Tab label="Orders">
|
|
65
153
|
<ReferenceManyField
|
|
154
|
+
label="Orders"
|
|
66
155
|
reference="Order"
|
|
67
156
|
target="CustomerId"
|
|
68
|
-
|
|
157
|
+
perPage={7}
|
|
69
158
|
>
|
|
70
159
|
<Datagrid rowClick="show">
|
|
71
|
-
<TextField source="
|
|
72
|
-
<
|
|
73
|
-
<
|
|
160
|
+
<TextField source="ShipName" label="Ship Name" />
|
|
161
|
+
<DateField source="OrderDate" label="Order Date" />
|
|
162
|
+
<DateField source="ShippedDate" label="Shipped Date" />
|
|
163
|
+
<NumberField source="AmountTotal" label="Total Amount" options={{ style: 'currency', currency: 'USD' }}/>
|
|
164
|
+
<BooleanField source="Ready" label="Ready" />
|
|
165
|
+
<NumberField source="Id" label="Order ID" />
|
|
74
166
|
</Datagrid>
|
|
75
167
|
</ReferenceManyField>
|
|
76
168
|
</Tab>
|
|
@@ -79,7 +171,6 @@ export const CustomerShow = (props) => (
|
|
|
79
171
|
</Show>
|
|
80
172
|
);
|
|
81
173
|
|
|
82
|
-
// Customer Create
|
|
83
174
|
export const CustomerCreate = (props) => (
|
|
84
175
|
<Create {...props}>
|
|
85
176
|
<SimpleForm>
|
|
@@ -93,11 +184,12 @@ export const CustomerCreate = (props) => (
|
|
|
93
184
|
<TextInput source="Country" label="Country" />
|
|
94
185
|
<TextInput source="Phone" label="Phone" />
|
|
95
186
|
<TextInput source="Fax" label="Fax" />
|
|
187
|
+
<NumberInput source="Balance" label="Balance" />
|
|
188
|
+
<NumberInput source="CreditLimit" label="Credit Limit" />
|
|
96
189
|
</SimpleForm>
|
|
97
190
|
</Create>
|
|
98
191
|
);
|
|
99
192
|
|
|
100
|
-
// Customer Edit
|
|
101
193
|
export const CustomerEdit = (props) => (
|
|
102
194
|
<Edit {...props}>
|
|
103
195
|
<SimpleForm>
|
|
@@ -111,6 +203,9 @@ export const CustomerEdit = (props) => (
|
|
|
111
203
|
<TextInput source="Country" label="Country" />
|
|
112
204
|
<TextInput source="Phone" label="Phone" />
|
|
113
205
|
<TextInput source="Fax" label="Fax" />
|
|
206
|
+
<NumberInput source="Balance" label="Balance" />
|
|
207
|
+
<NumberInput source="CreditLimit" label="Credit Limit" />
|
|
208
|
+
<NumberField source="Id" label="Customer ID" />
|
|
114
209
|
</SimpleForm>
|
|
115
210
|
</Edit>
|
|
116
211
|
);
|