Skip to content

Commit 7eec522

Browse files
author
gustavnavar
committed
Update documentation
1 parent 863ce62 commit 7eec522

22 files changed

Lines changed: 944 additions & 7 deletions

.idea/artifacts/gridjavacore_jar.xml

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ https://github.com/gustavnavar/Grid.Java.Core/releases
1414

1515
## Folder description
1616
* [gridjavacore](./gridjavacore): Library to build back-ends based on Java JPA / Hibernate
17-
* [demo](./demo): Spring Boot demo project supporting the gridjavacore library. It can be tested with this [Blazor WASM project](https://github.com/gustavnavar/Grid.Blazor/tree/master/GridBlazorSpring)
17+
* [demo](./demo): Spring Boot demo project supporting the gridjavacore library. It can be tested with this [Blazor WASM project](https://github.com/gustavnavar/Grid.Blazor/tree/master/GridBlazorJava)
1818
* [docs](./docs): Documentation
1919

20-
The SQL Server database for all demos can be downloaded from [here](https://github.com/gustavnavar/Grid.Core/tree/master/sample_database)
20+
The SQL Server database for all demos can be downloaded from [here](https://github.com/gustavnavar/Grid.Java.Core/tree/master/sample_database)
2121

2222
Alternatively, if you prefer to install a fresh version of the database you can perform the following steps:
2323
- run this script from Microsoft web to create a new database: https://github.com/microsoft/sql-server-samples/blob/master/samples/databases/northwind-pubs/instnwnd.sql
@@ -28,10 +28,6 @@ Alternatively, if you prefer to install a fresh version of the database you can
2828
GO
2929
```
3030
- change manually some values of the new IsVip column to True
31-
- review the datetime columns. Any mismatch between EF Core model and database definitions will produce an exception and filtering will not work as expected. If database columns are defined as ```datetime``` you must modify the ```NorthwindDbContext``` class including:
32-
```c#
33-
modelBuilder.Entity<Order>().Property(r => r.OrderDate).HasColumnType("datetime");
34-
```
35-
for each datetime column. Or you can change all database columns' type to ```datetime2(7)```.
31+
- review the datetime columns. Any mismatch between JPA model and database definitions will produce an exception and filtering will not work as expected.
3632

3733

docs/images/Crud.png

378 KB
Loading

docs/images/Crud_edit.png

246 KB
Loading

docs/images/GridBlazor.png

299 KB
Loading

docs/images/Searching.png

322 KB
Loading

docs/images/Totals.png

311 KB
Loading

docs/java_backend/API.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Front-end back-end API
2+
3+
[Index](Documentation.md)
4+
5+
Normal usage of **GridJavaCore** and **GridBlazor** packages doesn't require any knowledge of this interface. This documentation is included only for those who want to implement their own front end instead of using **GridBlazor**.
6+
7+
## Request
8+
9+
The **GridBlazor** package sends a query string with the following parameters:
10+
11+
Parameter | Description | Example
12+
--------- | ----------- | -------
13+
grid-page | integer to define the requested page number | grid-page=2
14+
grid-column | the name of the column that is used for sorting | grid-column=OrderID
15+
grid-dir | the direction used for sorting: 0 means ascending and 1 means descending | grid-dir=0
16+
grid-sorting | multiple strings used for extended sorting and grouping | grid-sorting=Customer.CompanyName__0__1
17+
grid-filter | multiple strings used for filtering | grid-filter=OrderCustomDate__6__2019-06-11
18+
grid-clearinitfilter | the name of columns that have an initial filter but it is not used anymore | grid-clearinitfilter=Customer.CompanyName
19+
grid-search | word to be searched on all columns | grid-search=aro
20+
grid-pagesize | integer to dynamically change the initial grid page size | grid-pagesize=20
21+
grid-start-index | integer to define the first requested record when grid virtualization is enabled (from v 4.0.0 on) | grid-start-index=0
22+
grid-virt-count | integer to define the number of records requested when grid virtualization is enabled (from v 4.0.0 on) | grid-virt-count=17
23+
grid-no-totals | boolean to control if back-end calls must return data about grid totals when virtualization is used
24+
25+
The parameters **grid-page**, **grid-column**, **grid-dir**, **grid-search**, **grid-pagesize**, **grid-start-index** and **grid-virt-count** should appear once in a query string. Their use is straightforward.
26+
27+
Parameters for pagination (grid-page and grid-pagesize) must not be used alltogether with parameters for virtualization (grid-start-index and grid-virt-count).
28+
29+
But the parameters **grid-sorting**, **grid-filter** and **grid-clearinitfilter** may appear multiple times in a query string. Let's see more detail about them.
30+
31+
* **grid-sorting** is a string with 3 parts separated by "__":
32+
* the first part is the column name that is sorted or grouped
33+
* the second part is a number defining the type of sorting:
34+
* **0**: Ascending
35+
* **1**: Descending
36+
* the third part is a number defining the column order in which sorting is applied. It starts with 1 and cannot be repeated
37+
38+
* **grid-filter** is a string with 3 parts separated by "__":
39+
* the first part is the column name that is filtered
40+
* the second part is a number defining the type of filter:
41+
* **1**: Equals
42+
* **2**: Contains
43+
* **3**: StartsWith
44+
* **4**: EndsWidth
45+
* **5**: GreaterThan
46+
* **6**: LessThan
47+
* **7**: GreaterThanOrEquals
48+
* **8**: LessThanOrEquals
49+
* **9**: Special type to define the type of condition for multiple filtering
50+
* **10**: NotEquals
51+
* **11**: IsNull
52+
* **12**: IsNotNull
53+
* **13**: IsDuplicated
54+
* **14**: IsNotDuplicated
55+
* the third part is the **filterValue**, a string for the value of the filter.
56+
57+
In the special case of multiple filtering the possible values of a **grid-filter** represents the condition used to combine filter for the specified column:
58+
* **1**: And
59+
* **2**: Or
60+
61+
* **grid-clearinitfilter** is used only for columns that have defined an initial filter as:
62+
63+
```c#
64+
columns.add("customers.companyName").setInitialFilter(GridFilterType.STARTS_WITH, "a");
65+
```
66+
While the grid is using the initial filter this parameters must not be used. But from the moment that the initial filter is removed, either by clearing it or by defining other filter for that column, this parameter must be included in the query string with the name of the column.
67+
A query string can contain multiple times this parameter, once per each column that had an initial filter not used anymore.
68+
69+
The following query string is an example:
70+
71+
```url
72+
/Home/GetOrdersGridRows?
73+
grid-page=2&
74+
grid-pagesize=20&
75+
grid-sorting=Customer.CompanyName__0__1&
76+
grid-column=OrderID&
77+
grid-dir=0&
78+
grid-filter=Freight__5__50&
79+
grid-filter=Freight__9__1&
80+
grid-filter=Freight__6__100&
81+
grid-filter=Customer.CompanyName__1__Around+the+Horn&
82+
grid-clearinitfilter=Customer.CompanyName&
83+
grid-search=horn
84+
```
85+
In this example the front-end is requesting:
86+
* the page **2**
87+
* of pages with size **20**
88+
* for the grid sorted/grouped by column **Customer.CompanyName**
89+
* **ascending** ordered
90+
* in first position
91+
* then ordered by column **OrderID**
92+
* **ascending** ordered
93+
* filtered by column **Freight** with a value **greater** than **50**
94+
* using the **and** condition for the column **Freight**
95+
* filtered by column **Freight** with a value **less** than **100**
96+
* filtered by column **Customer.CompanyName** with a value **equals** to **Around the Horn**
97+
* without using the **intial filter** for the column **Customer.CompanyName**
98+
* and including the word **horn** in any column of a register
99+
100+
## Response
101+
102+
The **GridJavaCore** package sends back a **json** reponse string with the following format:
103+
104+
```
105+
{
106+
"items":[ array of registers ],
107+
"totals":
108+
{
109+
"sum":{ values of column's addition },
110+
"average":{ values of column's average },
111+
"max":{ values of column's max },
112+
"min":{ values of column's min }
113+
},
114+
"pager":
115+
{
116+
"pagingType": 0|1|2,
117+
"pageSize": number,
118+
"currentPage": number,
119+
"itemsCount": number,
120+
"startIndex": number,
121+
"virtualizedCount": number
122+
}
123+
}
124+
```
125+
126+
[<- Data annotations](Data_annotations.md) | [CRUD ->](Crud.md)

docs/java_backend/Crud.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# CRUD
2+
3+
[Index](Documentation.md)
4+
5+
GridJavaCore supports CRUD forms to add, edit, view and delete items for Blazor client-side projects.
6+
7+
These are the supported features:
8+
- Full screen forms
9+
- Auto-generated forms with field type detection based on column definition
10+
- Lists for drop-drown fields
11+
- Custom forms
12+
- Support of grid models including 1:N relationships
13+
- Support of entities with multiple foreign keys
14+
- Direct URLs
15+
16+
## Auto-generated forms
17+
18+
You will need a controller supporting 4 web services to perform the CRUD operation on the back-end. This is an example of this type of controller:
19+
20+
```java
21+
@RestController
22+
@RequiredArgsConstructor
23+
@RequestMapping(value = "/api")
24+
public class OrderController {
25+
26+
private final OrderRepository orderRepository;
27+
private final CustomerRepository customerRepository;
28+
private final EmployeeRepository employeeRepository;
29+
private final ShipperRepository shipperRepository;
30+
31+
@GetMapping(value = {"/order", "/Order"})
32+
public ResponseEntity<List<Order>> getAll() {
33+
return ResponseEntity.ok(orderRepository.findAll());
34+
}
35+
36+
@PostMapping(value = {"/order", "/Order"})
37+
public ResponseEntity<Object> create(@RequestBody Order order) {
38+
39+
try {
40+
if(order.getCustomerID() != null && ! order.getCustomerID().isBlank()) {
41+
var customer = customerRepository.findById(order.getCustomerID());
42+
customer.ifPresent(order::setCustomer);
43+
}
44+
if(order.getEmployeeID() != null) {
45+
var employee = employeeRepository.findById(order.getEmployeeID());
46+
employee.ifPresent(order::setEmployee);
47+
}
48+
if(order.getShipVia() != null) {
49+
var shipper = shipperRepository.findById(order.getShipVia());
50+
shipper.ifPresent(order::setShipper);
51+
}
52+
Order savedOrder = orderRepository.saveAndFlush(order);
53+
return ResponseEntity.ok(savedOrder.getOrderID());
54+
}
55+
catch (Exception e) {
56+
return ResponseEntity.badRequest()
57+
.body(e.getMessage().replace('{', '(').replace('}', ')'));
58+
}
59+
}
60+
61+
@GetMapping(value = {"/order/{id}", "/Order/{id}"})
62+
public ResponseEntity<Order> get(@PathVariable int id) {
63+
64+
Optional<Order> order = orderRepository.findById(id);
65+
return order.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
66+
}
67+
68+
@PutMapping(value = {"/order/{id}", "/Order/{id}"})
69+
public ResponseEntity<Object> update(@RequestBody Order order, @PathVariable int id) {
70+
71+
Optional<Order> attachedOrder = orderRepository.findById(id);
72+
if (attachedOrder.isEmpty())
73+
return ResponseEntity.notFound().build();
74+
75+
try {
76+
order.setOrderID(id);
77+
if(order.getCustomerID() != null && ! order.getCustomerID().isBlank()
78+
&& !order.getCustomerID().equals(attachedOrder.get().getCustomerID())) {
79+
var customer = customerRepository.findById(order.getCustomerID());
80+
customer.ifPresent(order::setCustomer);
81+
}
82+
if(order.getEmployeeID() != null && !order.getEmployeeID().equals(attachedOrder.get().getEmployeeID())) {
83+
var employee = employeeRepository.findById(order.getEmployeeID());
84+
employee.ifPresent(order::setEmployee);
85+
}
86+
if(order.getShipVia() != null && !order.getShipVia().equals(attachedOrder.get().getShipVia())) {
87+
var shipper = shipperRepository.findById(order.getShipVia());
88+
shipper.ifPresent(order::setShipper);
89+
}
90+
orderRepository.saveAndFlush(order);
91+
return ResponseEntity.noContent().build();
92+
}
93+
catch (Exception e) {
94+
return ResponseEntity.badRequest()
95+
.body(e.getMessage().replace('{', '(').replace('}', ')'));
96+
}
97+
}
98+
99+
@DeleteMapping(value = {"/order/{id}", "/Order/{id}"})
100+
public ResponseEntity<Object> delete(@PathVariable int id) {
101+
102+
Optional<Order> order = orderRepository.findById(id);
103+
if (order.isEmpty())
104+
return ResponseEntity.notFound().build();
105+
106+
try {
107+
orderRepository.delete(order.get());
108+
orderRepository.flush();
109+
return ResponseEntity.noContent().build();
110+
}
111+
catch (Exception e) {
112+
return ResponseEntity.badRequest()
113+
.body(e.getMessage().replace('{', '(').replace('}', ')'));
114+
}
115+
}
116+
}
117+
```
118+
119+
## Column definition
120+
121+
The column definition must include the primary keys:
122+
- using the **setPrimaryKey(true)** method for columns with auto-generated keys, or
123+
- using the **setPrimaryKey(true, false)** method for columns with manually generated keys
124+
125+
This is an example of column definition:
126+
127+
```java
128+
Consumer<IGridColumnCollection<Order>> columns = c -> {
129+
c.add("orderID", Integer.class).setPrimaryKey(true);
130+
c.add("customerID", String.class);
131+
c.add("employeeID", Integer.class);
132+
c.add("shipVia", Integer.class, true);
133+
c.add("orderDate", LocalDateTime.class, "orderCustomDate");
134+
c.add("customer.companyName", String.class);
135+
c.add("customer.contactName", String.class);
136+
c.add("freight", BigDecimal.class);
137+
c.add("customer.isVip",Boolean.class);
138+
c.add("requiredDate", LocalDateTime.class, true);
139+
c.add("shippedDate", LocalDateTime.class, true);
140+
c.add("shipName", String.class, true);
141+
c.add("shipAddress", String.class, true);
142+
c.add("shipCity", String.class, true);
143+
c.add("shipPostalCode", String.class, true);
144+
c.add("shipRegion", String.class, true);
145+
c.add("shipCountry", String.class, true);
146+
};
147+
```
148+
149+
This is an example of a grid using CRUD:
150+
151+
![](../images/Crud.png)
152+
153+
And this is an auto-genereated edit form:
154+
155+
![](../images/Crud_edit.png)
156+
157+
[<- Front-end back-end API](API.md)

0 commit comments

Comments
 (0)