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.
Files changed (51) hide show
  1. api_logic_server_cli/api_logic_server.py +4 -4
  2. api_logic_server_cli/api_logic_server_info.yaml +2 -2
  3. api_logic_server_cli/genai/genai_admin_app.py +33 -9
  4. api_logic_server_cli/prototypes/.DS_Store +0 -0
  5. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-Resource-Learning-Prompt.md +119 -0
  6. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-js-Learning-Prompt.md +71 -0
  7. 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
  8. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/package.json +3 -0
  9. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/Config.js +527 -0
  10. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/app_loader.js +24 -0
  11. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/.eslintrc +5 -0
  12. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/.yarnrc.yml +4 -0
  13. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/default-settings.js +25 -0
  14. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/default-settings.ts +25 -0
  15. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/errors.js +116 -0
  16. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/errors.ts +116 -0
  17. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/index.test.tsx +7 -0
  18. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/index.tsx +11 -0
  19. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/ra-jsonapi-client.js +577 -0
  20. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/ra-jsonapi-client.ts +577 -0
  21. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/resourceLookup.js +124 -0
  22. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/resourceLookup.ts +124 -0
  23. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/rav4-jsonapi-client/styles.module.css +9 -0
  24. api_logic_server_cli/prototypes/nw/.DS_Store +0 -0
  25. api_logic_server_cli/prototypes/nw/ui/.DS_Store +0 -0
  26. api_logic_server_cli/prototypes/nw/ui/react_admin/.DS_Store +0 -0
  27. api_logic_server_cli/prototypes/nw/ui/react_admin/src/App.js +30 -31
  28. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Category.js +62 -62
  29. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Customer.js +143 -48
  30. api_logic_server_cli/prototypes/nw/ui/react_admin/src/CustomerDemographic.js +20 -37
  31. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Department.js +38 -39
  32. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Employee.js +85 -134
  33. api_logic_server_cli/prototypes/nw/ui/react_admin/src/EmployeeAudit.js +89 -77
  34. api_logic_server_cli/prototypes/nw/ui/react_admin/src/EmployeeTerritory.js +59 -59
  35. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Location.js +45 -49
  36. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Order.js +42 -60
  37. api_logic_server_cli/prototypes/nw/ui/react_admin/src/OrderDetail.js +97 -106
  38. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Product.js +60 -62
  39. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Region.js +36 -41
  40. api_logic_server_cli/prototypes/nw/ui/react_admin/src/SampleDBVersion.js +73 -0
  41. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Shipper.js +57 -54
  42. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Supplier.js +71 -87
  43. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Territory.js +47 -41
  44. api_logic_server_cli/prototypes/nw/ui/react_admin/src/Union.js +18 -34
  45. {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/METADATA +1 -1
  46. {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/RECORD +50 -31
  47. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/src/dataProvider.js +0 -110
  48. {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/WHEEL +0 -0
  49. {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/entry_points.txt +0 -0
  50. {apilogicserver-15.0.19.dist-info → apilogicserver-15.0.22.dist-info}/licenses/LICENSE +0 -0
  51. {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
+ }
@@ -0,0 +1,9 @@
1
+ /* add css module styles here (optional) */
2
+
3
+ .test {
4
+ margin: 2em;
5
+ padding: 0.5em;
6
+ border: 2px solid #000;
7
+ font-size: 2em;
8
+ text-align: center;
9
+ }
@@ -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' }, // Material-UI default blue
30
- secondary: { main: '#1565c0' }, // A darker blue, or choose another color
28
+ primary: { main: '#1976d2' },
29
+ secondary: { main: '#1565c0' },
31
30
  },
32
31
  typography: { fontSize: 14 },
33
32
  });
34
33
 
35
34
  const App = () => {
36
- return (
37
- <Admin dataProvider={dataProvider} theme={theme}>
38
- {/* Register each resource with their components */}
39
- <Resource name="Customer" list={CustomerList} show={CustomerShow} edit={CustomerEdit} create={CustomerCreate} />
40
- <Resource name="Category" list={CategoryList} show={CategoryShow} edit={CategoryEdit} create={CategoryCreate} />
41
- <Resource name="Order" list={OrderList} show={OrderShow} edit={OrderEdit} create={OrderCreate} />
42
- <Resource name="Product" list={ProductList} show={ProductShow} edit={ProductEdit} create={ProductCreate} />
43
- <Resource name="Employee" list={EmployeeList} show={EmployeeShow} edit={EmployeeEdit} create={EmployeeCreate} />
44
- <Resource name="Supplier" list={SupplierList} show={SupplierShow} edit={SupplierEdit} create={SupplierCreate} />
45
- <Resource name="Shipper" list={ShipperList} show={ShipperShow} edit={ShipperEdit} create={ShipperCreate} />
46
- <Resource name="Region" list={RegionList} show={RegionShow} edit={RegionEdit} create={RegionCreate} />
47
- <Resource name="Territory" list={TerritoryList} show={TerritoryShow} edit={TerritoryEdit} create={TerritoryCreate} />
48
- <Resource name="CustomerDemographic" list={CustomerDemographicList} show={CustomerDemographicShow} edit={CustomerDemographicEdit} create={CustomerDemographicCreate} />
49
- <Resource name="EmployeeAudit" list={EmployeeAuditList} show={EmployeeAuditShow} edit={EmployeeAuditEdit} create={EmployeeAuditCreate} />
50
- <Resource name="EmployeeTerritory" list={EmployeeTerritoryList} show={EmployeeTerritoryShow} edit={EmployeeTerritoryEdit} create={EmployeeTerritoryCreate} />
51
- <Resource name="Department" list={DepartmentList} show={DepartmentShow} edit={DepartmentEdit} create={DepartmentCreate} />
52
- <Resource name="Union" list={UnionList} show={UnionShow} edit={UnionEdit} create={UnionCreate} />
53
- <Resource name="Location" list={LocationList} show={LocationShow} edit={LocationEdit} create={LocationCreate} />
54
- <Resource name="OrderDetail" list={OrderDetailList} show={OrderDetailShow} edit={OrderDetailEdit} create={OrderDetailCreate} />
55
- </Admin>
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
- List, Datagrid, TextField, ReferenceField,
5
- Show, TabbedShowLayout, Tab, SimpleShowLayout,
6
- TextInput, ReferenceManyField, Pagination,
7
- Filter, Create, Edit, SimpleForm, SelectInput, ReferenceInput
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
- // Define the filters for the Category List
23
+ // Filters for Category List
24
+ //theme color;
11
25
  const CategoryFilter = (props) => (
12
- <Filter {...props}>
13
- <TextInput label="Search" source="q" alwaysOn />
14
- <TextInput label="Category Name" source="CategoryName" />
15
- <TextInput label="Description" source="Description" />
16
- </Filter>
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
- // Pagination configuration
20
- const CategoryPagination = props => <Pagination rowsPerPageOptions={[7]} {...props} />;
21
-
22
- // List view for Categories
33
+ // Category List
23
34
  export const CategoryList = (props) => (
24
- <List {...props} filters={<CategoryFilter />} pagination={<CategoryPagination />}>
25
- <Datagrid rowClick="show">
26
- <TextField source="CategoryName" label="Category Name" />
27
- <TextField source="Description" label="Description" />
28
- <TextField source="Client_id" label="Client" />
29
- </Datagrid>
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 view for a single Category
43
+ // Category Show
34
44
  export const CategoryShow = (props) => (
35
- <Show {...props}>
36
- <SimpleShowLayout>
37
- <TextField source="CategoryName" label="Category Name" />
38
- <TextField source="Description" label="Description" />
39
- <TextField source="Client_id" label="Client" />
40
- </SimpleShowLayout>
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
- <Tab label="Related Resources">
43
- <ReferenceManyField
44
- label="Products"
45
- reference="Product"
46
- target="CategoryId"
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
- </Show>
59
+ </ReferenceManyField>
60
+ </SimpleShowLayout>
61
+ </Show>
55
62
  );
56
63
 
57
- // Create view for a Category
64
+ // Category Create
58
65
  export const CategoryCreate = (props) => (
59
- <Create {...props}>
60
- <SimpleForm>
61
- <TextInput source="CategoryName" label="Category Name" />
62
- <TextInput source="Description" label="Description" />
63
- <ReferenceInput label="Client" source="Client_id" reference="Client">
64
- <SelectInput optionText="name" />
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 view for a Category
74
+ // Category Edit
71
75
  export const CategoryEdit = (props) => (
72
- <Edit {...props}>
73
- <SimpleForm>
74
- <TextInput source="CategoryName" label="Category Name" />
75
- <TextInput source="Description" label="Description" />
76
- <ReferenceInput label="Client" source="Client_id" reference="Client">
77
- <SelectInput optionText="name" />
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
- List,
4
- Datagrid,
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 Customer list
6
+ // Filters for the list view
25
7
  const CustomerFilter = (props) => (
26
8
  <Filter {...props}>
27
- <TextInput label="Search by Company" source="CompanyName" alwaysOn />
28
- <TextInput label="Search by Contact" source="ContactName" />
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
- // Customer List
33
- export const CustomerList = (props) => (
34
- <List filters={<CustomerFilter />} pagination={<Pagination />} {...props}>
35
- <Datagrid rowClick="show">
36
- <TextField source="CompanyName" label="Company Name" />
37
- <TextField source="ContactName" label="Contact Name" />
38
- <NumberField source="Balance" label="Balance" />
39
- <NumberField source="CreditLimit" label="Credit Limit" />
40
- <NumberField source="OrderCount" label="Order Count" />
41
- <NumberField source="UnpaidOrderCount" label="Unpaid Orders" />
42
- <TextField source="Phone" label="Phone" />
43
- <NumberField source="Id" label="ID" />
44
- </Datagrid>
45
- </List>
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
- // Customer Show
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="Placed Order List">
152
+ <Tab label="Orders">
65
153
  <ReferenceManyField
154
+ label="Orders"
66
155
  reference="Order"
67
156
  target="CustomerId"
68
- label="Placed Orders"
157
+ perPage={7}
69
158
  >
70
159
  <Datagrid rowClick="show">
71
- <TextField source="Id" label="Order ID" />
72
- <TextField source="OrderDate" label="Order Date" />
73
- <TextField source="AmountTotal" label="Total Amount" />
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
  );