In Thymeleaf with multiple actions and multiple forms are possible? - forms

Hi i am new in thymeleaf + spring and i start learn it.
and wanted to integrate these 2 form in one page .
that means now 2 forms are in 2 different pages and the th:action are different ..
here i want these 2 forms work in one page
i tried that with a page with 2 forms and 2 actions but that caught error..
Create Standard Code
<form action="#" th:action="#{/saveStandard.html}" th:object="${standard}">
<table>
<h1>Create Standard</h1>
<tr>
<td>Standard Name:</td>
<td><input type="text" placeholder="Enter Standard Name" required="required"
th:field="*{standardName}"/></td>
</tr>
<tr>
<td><input type="submit" value="Create" name="save" /></td>
</tr>
</table>
</form>
Create Division Code
<form action="#" th:action="#{/saveDivision.html}"
th:object="${division}">
<table>
<td>Division Name:</td>
<tr>
<td><input type="text" placeholder="Enter Division Name" required="required"
th:field="*{divisionName}" />
</td>
</tr>
<td><input type="submit" class="btn btn-primary" value="Create"
name="save" /></td>
</table>
</form>
these are controllers..
#RequestMapping(value = Array("/saveStandard.html"), params = Array({ "save" }))
def saveStandard(standard: Standard): String = {
standard.setCreatedDate(new java.sql.Date(new java.util.Date().getTime))
standardService.addStandard(standard)
"redirect:/school/CreateStandard.html"
}
#RequestMapping(value = Array("/saveDivision.html"), params = Array({ "save" }))
def saveDivision(division: Division): String = {
division.setCreatedDate(new java.sql.Date(new java.util.Date().getTime))
divisionService.addDivision(division)
"redirect:/school/CreateDivision.html"
}
if you knew about this question please share your answer here..
and Thanks...

Hi It is posible here a example
HTML Example
<section id="registration" class="section">
<div class="container tagline">
<em>Register User</em><br />
<form method="post" th:action="#{/user/register}" th:object="${newUser}">
<div>
<label for="givenName">Id</label>
<input id="id" placeholder="Enter Id" type="text" th:field="*{id}" />
<p th:if="${#fields.hasErrors('id')}" th:text="${#strings.listJoin(#fields.errors('id'), ', ')}">
</p>
</div>
<div>
<label for="givenName">Name</label>
<input id="name" placeholder="Enter Name" type="text" th:field="*{name}" />
<p th:if="${#fields.hasErrors('name')}"
th:text="${#strings.listJoin(#fields.errors('name'), ', ')}"></p>
</div>
<div>
<label for="email">Email</label>
<input id="email" placeholder="Enter the Email" type="text" th:field="*{email}" />
<p th:if="${#fields.hasErrors('email')}"
th:text="${#strings.listJoin(#fields.errors('email'), ', ')}"></p>
</div>
<button type="submit">Create user</button>
</form>
</div>
</section>
<div>
<form method="get" th:action="#{/user/searchById}" th:object="${searchUser}">
<input id="id" placeholder="Search by id" type="text" th:field="*{id}" size="10" >
<button type="submit" >search</button>
</form>
<form method="get" th:action="#{/user/searchByName}" th:object="${searchUser}">
<input id="id" placeholder="Search by Name" type="text" th:field="*{name}" size="10" >
<button type="submit" >search</button>
</form>
<form method="get" th:action="#{/user/searchByEmail}" th:object="${searchUser}">
<input id="id" placeholder="Search by Email" type="text" th:field="*{email}" size="10" >
<button type="submit" >search</button>
</form>
</div>
Spring
#Controller
#RequestMapping("/user")
public class User {
BookingFacadeUserImp userService = new BookingFacadeUserImp();
#GetMapping()
public ModelAndView init() {
return getModelView().addObject("users", getUsersByName("", 100, 0));
}
#PostMapping("/register")
public ModelAndView saveUser(#Valid #ModelAttribute("newUser") UserDTO user, BindingResult result)
throws NumberFormatException, ParseException {
System.out.println("Register: " + user);
userService.createUser(user);
return getModelView().addObject("users", getUsersByName("", 100, 0));
}
#GetMapping("/delete/{id}")
public ModelAndView delete(#PathVariable long id) {
userService.deleteUser(id);
return init();
}
#PostMapping("/update")
public ModelAndView updateUser(#ModelAttribute("updateUser") UserDTO user) {
userService.updateUser(user);
return init();
}
#GetMapping("/searchById")
public ModelAndView searchById(#ModelAttribute("searchUser") UserDTO user) {
if (user.getId() > 0)
return getModelView().addObject("users", getUsersById(user.getId()));
else
return init();
}
#GetMapping("/searchByName")
public ModelAndView searchByName(#ModelAttribute("searchUser") UserDTO user) {
if (!user.getName().equals(""))
return getModelView().addObject("users", getUsersByName(user.getName(),100,0));
else
return init();
}
public ModelAndView getModelView() {
ModelAndView model = new ModelAndView("user");
model.addObject("newUser", new UserDTO());
model.addObject("searchUser", new UserDTO());
return model;
}
public List<UserDTO> getUsersById(long id) {
List<UserDTO> list = new ArrayList<UserDTO>();
list.add((UserDTO) userService.getUserById(id));
return list;
}
public List<com.example.demo.task1.model.User> getUsersByName(String name, int pageSiza, int pageNum) {
return userService.getUsersByName(name, pageSiza, pageNum);
}
public List<com.example.demo.task1.model.User> getUsersByEmail(String email) {
return (List<com.example.demo.task1.model.User>) userService.getUserByEmail(email);
}
}

Related

Set value Entity Framework Core during OnGet

I thought this would be simple...
If I want to force a value to a column/filed before the page loads, how do I do that?
Here's the lines from the Model:
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
[Display(Name = "Contract Value")]
public decimal? ContractValue { get; set; } = 0m;
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
[Display(Name = "Contract Expended")]
public decimal? ContractValueExpended { get; set; } = 0m;
And, here's what I tried using Fluent API.
modelBuilder.Entity<Contract>()
.Property(e => e.ContractValue)
.HasDefaultValue(0);
modelBuilder.Entity<Contract>()
.Property(e => e.ContractValueExpended)
.HasDefaultValue(0);
My bad. Here is create.cshtml.cs
public class CreateModel : GlobalPageModel
{
private readonly TawdryIndustries.Data.CompanyContext _context;
public CreateModel(TawdryIndustries.Data.CompanyContext context)
{
_context = context;
}
public IActionResult OnGet()
{
PopulateEmployeeNamesSelectList(_context);
PopulateCustomerNamesSelectList(_context);
return Page();
}
[BindProperty]
public Contract Contract { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var emptyContract = new Contract();
if (await TryUpdateModelAsync<Contract>(
emptyContract,
"Contract",
c => c.ContractID,
c => c.ContractNumber,
c => c.ContractName,
c => c.CustomerID,
c => c.ContractAwardDate,
c => c.ContractBegDate,
c => c.ContractEndDate,
c => c.ContractValue,
c => c.ContractValueExpended,
c => c.ContractManagerID))
{
_context.Contracts.Add(emptyContract);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
PopulateEmployeeNamesSelectList(_context, emptyContract.ContractManagerID);
PopulateCustomerNamesSelectList(_context, emptyContract.CustomerID);
return Page();
}
And, here is the razor page (create.cshtml):
#page
#model TawdryIndustries.Pages.Contracts.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Contract</h4>
<hr />
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<table class="table">
<tr>
<td>
<label asp-for="Contract.CustomerID" class="control-label"></label>
<select asp-for="Contract.CustomerID" class="form-control"
asp-items="#Model.CustomerNameSL">
<option value="">-- Select Customer --</option>
</select>
<span asp-validation-for="Contract.CustomerID" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractNumber" class="control-label"></label>
<input asp-for="Contract.ContractNumber" class="form-control" />
<span asp-validation-for="Contract.ContractNumber" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractName" class="control-label"></label>
<input asp-for="Contract.ContractName" class="form-control" />
<span asp-validation-for="Contract.ContractName" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
<label asp-for="Contract.ContractAwardDate" class="control-label"></label>
<input asp-for="Contract.ContractAwardDate" class="form-control" />
<span asp-validation-for="Contract.ContractAwardDate" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractBegDate" class="control-label"></label>
<input asp-for="Contract.ContractBegDate" class="form-control" />
<span asp-validation-for="Contract.ContractBegDate" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractEndDate" class="control-label"></label>
<input asp-for="Contract.ContractEndDate" class="form-control" />
<span asp-validation-for="Contract.ContractEndDate" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
<label asp-for="Contract.ContractValue" class="control-label"></label>
<input asp-for="Contract.ContractValue" class="form-control" />
<span asp-validation-for="Contract.ContractValue" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractValueExpended" class="control-label"></label>
<input asp-for="Contract.ContractValueExpended" class="form-control" />
<span asp-validation-for="Contract.ContractValueExpended" class="text-danger"></span>
</td>
<td>
<label asp-for="Contract.ContractManagerID" class="control-label"></label>
<select asp-for="Contract.ContractManagerID" class="form-control"
asp-items="#Model.EmployeeNameSL">
<option value="">-- Select Manager --</option>
</select>
<span asp-validation-for="Contract.ContractManagerID" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Create" class="btn btn-primary" />
</td>
</tr>
</table>
</form>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
However, when the page is displayed (in create specifically), both of those fields are still blank. I want to force both fields to 0 when a new contract is created before the page loads.
For that matter, is there any way to set a value for a variable before a page loads?
In ASP.NET I would
<html>
<head></head>
<body>
<asp:textbox id="mytext" runat="server"></asp:textbox>
</body>
and:
protected void Page_Load(object sender, EventArgs e)
{
string somevar = "This is a test";
mytext.Text = somevar;
}
And the text box would contain "This is a test" when the page was displayed.
What is the equivalent in EF Core?
Thanks,
John

Thymeleaf form not submitting to Spring boot controller

I am trying to submit a form to Spring boot controller
This is the thymeleaf part:
<form th:action="#{/change_password}" method="post">
<div class="row">
<div class="col-md-9 register-right">
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<h3 class="register-heading">Change password</h3>
<div class="row register-form">
<div class="col-md-6">
<div class="form-group">
<input type="email" th:name="email" id="email" class="form-control" placeholder="Email *" >
<span th:if="${notPresent}" class="alert alert-info" style="color:red; width: 100% !important; border: none; background-color: transparent !important;">This email does not exist!</span>
</div>
<div class="form-group">
<input type="password" th:name="password" id="password" class="form-control" placeholder="Password *" >
</div>
<div class="form-group">
<input type="password" th:name="confirmPassword" id="confirmPassword" class="form-control" placeholder="Confirm *" >
</div>
</div>
<div class="col-md-6">
<input type="submit" class="btnRegister" style="background-color: #ffa600 !important;" value="Change"/>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
This is the Spring boot controller method:
#PostMapping("/change_password")
public String changeUserPassword(HttpServletRequest request, Model model) {
String path = "";
User u = userService.findByEmail(request.getParameter("email"));
if(u == null || u.getActive() == 0) {
model.addAttribute("notPresent", true);
path = "redirect:/forgot_password";
} else {
u.setPassword(bCryptPasswordEncoder.encode(request.getParameter("password")));
userService.updateUser(u);
sendEmail(u.getEmail(), u.getFirstname());
path = "redirect:/login";
}
return path;
}
I don't get any errors so I am not sure what's wrong.
To submit a form you can use an object userPassword define in a Class like this:
package ....
imports ....
#Data #AllArgsConstructor #NoArgsConstructor #ToString
public class UserPassword {
private Integer id;
private String password;
... other fields you need
}
You add this object to the controller displaying the page with :
model.addAttribute("UserPassword", userPassword);
Then you add this object to your form:
<form th:action="#{/change_password}" th:object="${userPassword}" method="post">
You need to bind data to this object in your html page (here I bind password from userPassword to the input tag):
<input type="password" th:field="*{password}" class="form-control" placeholder="Password *" >
And Finnaly I retrieve the object in the controller:
#PostMapping("/change_password")
public String changeUserPassword(Model model, #ModelAttribute UserPassword userPassword) {
.....
}
You can find a complete tutorial on part 7 from https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html

How do you create multiple rows at the same time in Entity Framework Core?

I am trying to add multiple rows to a MySql database using ASP.net Core with Entity Framework Core. I want to add multiple rows to a one-to-many relationship. The code I have so far is:
#model Products.Models.SideEffect
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>SideEffect</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group" id="side-effect-list">
Add
<br />
<label asp-for="SideEffects" class="control-label"></label>
<input asp-for="SideEffects" class="form-control side-effect" name="SideEffects[0].SideEffect" />
<span asp-validation-for="SideEffects" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ProductName" class="control-label"></label>
<select asp-for="ProductName" class ="form-control" asp-items="ViewBag.ProductName"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(function () {
$("#add").click(function (e) {
e.preventDefault();
var i = ($(".side-effect").length) / 2;
var n = '<br />' + '<input asp-for="SideEffects" class="form-control side-effect" name="SideEffects[0].SideEffect" />';
$("#side-effect-list").append(n);
});
});
</script>
}
And for the controller:
// GET: SideEffect/Create
public IActionResult Create()
{
ViewData["ProductName"] = new SelectList(_context.Products, "ProductId", "ProductName");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,SideEffects,ProductId, ProductName")] SideEffect sideEffect)
{
if (ModelState.IsValid)
{
_context.AddRange(sideEffect);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["ProductName"] = new SelectList(_context.Products, "ProductId", "ProductName", sideEffect.ProductName);
return View(sideEffect);
}
When I submit the form it adds value for Side Effect. Suggestions would be helpful.

CRUD Angular App

its a crud app i am inputting user info into a form and then saving it in an array and then rendering it into a table .I can add more rows with different user data . And i can delete a certain row from the table . I also have a edit button but i don't have no idea how to do that.
Register.html file
<div class="container">
<h2 class="page-header">Register</h2>
<form (ngSubmit)="onRegisterSubmit()" [formGroup] = "form">
<div class="form-group">
<label>Full Name</label>
<input type="text" [(ngModel)]="fullname" formControlName="fullname" class="form-control" >
</div>
<div class="form-group">
<label>Username</label>
<input type="text" [(ngModel)]="username" formControlName="username" class="form-control" >
</div>
<div class="form-group">
<label>Email</label>
<input type="text" [(ngModel)]="email" formControlName="email" class="form-control" >
</div>
<div class="form-group">
<label>Password</label>
<input type="password" [(ngModel)]="password" formControlName="password" class="form-control">
</div>
<input type="submit" class="btn btn-primary" value="Submit" [disabled]="!form.valid">
</form>
<br>
<br>
<table border="2" class="table table-striped">
<tr>
<th>Full Name</th>
<th>Username</th>
<th>Email</th>
<th>Password</th>
<th>Delete</th>
<th>Edit</th>
</tr>
<div > </div>
<tr *ngFor="let user of userDetails">
<td>{{user.username}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.password}}</td>
<td><button (click)="userDelete()">X</button></td>
<td><button (click)="userEdit()">Edit</button></td>
</tr>
</table>
</div>
Register.ts file
export class RegisterComponent implements OnInit {
fullname : string;
username : string;
email : string;
password : string;
userDetails:Array<object>;
constructor(
private validateService: ValidateService,
private flashMessage:FlashMessagesService)
{ }
form;
ngOnInit() {
this.userDetails=[];
this.form = new FormGroup({
fullname : new FormControl("", Validators.required),
username : new FormControl("", Validators.required),
email : new FormControl("", Validators.required),
password : new FormControl("", Validators.required)
});
}
onRegisterSubmit(){
let user = {
fullname : this.fullname ,
username : this.username,
email : this.email ,
password : this.password
}
this.userDetails.push(user);
if(!this.validateService.validateRegister(user)){
this.flashMessage.show('Please fill in all fields', {cssClass: 'alert-danger', timeout: 3000});
return false;
}
// Validate Email
if(!this.validateService.validateEmail(user.email)){
this.flashMessage.show('Please use a valid email', {cssClass: 'alert-danger', timeout: 3000});
return false;
}
}
userDelete(){
this.userDetails.pop();
}
userEdit(){
//No logic
}
}
Validation service file
export class ValidateService {
constructor() { }
validateRegister(user){
if(user.fullname == undefined || user.email == undefined || user.username == undefined || user.password == undefined){
return false;
} else {
return true;
}
}
validateEmail(email){
const re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}
To hardcode new values is simple:
<tr *ngFor="let user of userDetails; index as i">
<td>{{user.username}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.password}}</td>
<td><button (click)="userDelete()">X</button></td>
<td><button (click)="userEdit(i)">Edit</button></td>
</tr>
userEdit(i) {
let editUser = this.userDetails[i];
editUser = { fullname: 'Tadas Blynda', etc. }
}
But what you need is probably this:
<div>
<form (ngSubmit)="onRegisterSubmit()" [formGroup] = "form" [hidden]="clicked">
<div class="form-group">
<label>Full Name</label>
<input type="text" [(ngModel)]="fullname" formControlName="fullname" class="form-control" >
</div>
<div class="form-group">
<label>Username</label>
<input type="text" [(ngModel)]="username" formControlName="username" class="form-control" >
</div>
<div class="form-group">
<label>Email</label>
<input type="text" [(ngModel)]="email" formControlName="email" class="form-control" >
</div>
<div class="form-group">
<label>Password</label>
<input type="password" [(ngModel)]="password" formControlName="password" class="form-control">
</div>
<input type="submit" class="btn btn-primary" value="Submit" [disabled]="!form.valid">
</form>
</div>
<div>
<form (ngSubmit)="onEditSubmit()" [formGroup] = "form" [hidden]="!clicked">
<div class="form-group">
<label>Full Name</label>
<input type="text" [(ngModel)]="fullname" formControlName="fullname" class="form-control"
placeholder="userDetails[editIndex]?.fullname" >
</div>
<div class="form-group">
<label>Username</label>
<input type="text" [(ngModel)]="username" formControlName="username" class="form-control" >
</div>
<div class="form-group">
<label>Email</label>
<input type="text" [(ngModel)]="email" formControlName="email" class="form-control" >
</div>
<div class="form-group">
<label>Password</label>
<input type="password" [(ngModel)]="password" formControlName="password" class="form-control">
</div>
<input type="submit" class="btn btn-primary" value="Submit" [disabled]="!form.valid">
</form>
</div>
<br>
<br>
<table border="2" class="table table-striped">
<tr>
<th>Full Name</th>
<th>Username</th>
<th>Email</th>
<th>Password</th>
<th>Delete</th>
<th>Edit</th>
</tr>
<div > </div>
<tr *ngFor="let user of userDetails; index as i">
<td>{{user.fullname}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.password}}</td>
<td><button (click)="userDelete()">X</button></td>
<td><button (click)="clickEdit(i)">Edit</button></td>
</tr>
</table>
And
export class AppComponent {
fullname : string;
username : string;
email : string;
password : string;
clicked = false;
userDetails:Array<object>;
form;
ngOnInit() {
this.userDetails=[];
this.form = new FormGroup({
fullname : new FormControl("", Validators.required),
username : new FormControl("", Validators.required),
email : new FormControl("", Validators.required),
password : new FormControl("", Validators.required)
});
}
onRegisterSubmit(){
let user = {
fullname : this.fullname ,
username : this.username,
email : this.email ,
password : this.password
}
this.userDetails.push(user);
}
editIndex = null;
clickEdit(i){
this.clicked = !this.clicked;
this.editIndex = i;
}
onEditSubmit() {
let editUser = {
fullname : this.fullname ,
username : this.username,
email : this.email ,
password : this.password
}
this.userDetails[this.editIndex] = editUser;
this.clicked = !this.clicked;
}
}
Let me know please, if any issues.

getParameter in Servlet from form in JSP

I have a jsp with a form
<form action="Login" method="post">
<h1>Login</h1>
<div>
<input type="text" placeholder="Email" required="" id="email" />
</div>
<div>
<input type="password" placeholder="Password" required="" id="password" />
</div>
<div>
<input type="submit" value="Login" />
</div>
</form><!-- form -->
In the login Servlet I do the next:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
String pass = request.getParameter("password");
String email = request.getParameter("email");
The problem is the pass and email is always null, I don't know why.
Because you get parameters by name. Try to put this:
<input type="text" placeholder="Email" required="" id="email" name="email" />
And you'll get the parameter.
<form action="Login" method="post">
<h1>Login</h1>
<div>
<input type="text" placeholder="Email" required="" name="email" />
</div>
<div>
<input type="password" placeholder="Password" required="" name="password" />
</div>
<div>
<input type="submit" value="Login" />
</div>
</form>
String pass = request.getParameter("password");
String email = request.getParameter("email");
jsp code
<html>
<body>
<form name="loginForm" method="post" >
<input type="text" name="username" required>
<input type="password" name="password" required="">
<input type="submit" name="login" value="Login" required>
</form>
</body>
servlet code
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
//System.out.print(username);
String password = request.getParameter("password");
//System.out.print(password);
if (//handle ur logic) {//call validate function in UserValidate.java
//System.out.println("validate true");
HttpSession session = request.getSession();
session.setAttribute("username",username);
RequestDispatcher rd = request.getRequestDispatcher("welcome.jsp");
rd.forward(request, response);
} else {
//System.out.println("validate false");
out.print("<p style=\"color:blue\">Invalid Username Password</p>");
RequestDispatcher rd = request.getRequestDispatcher("index.jsp");
rd.include(request, response);
}
out.close();
}
in here you have to create a session and setAttribute("username",username).
i think u get some idea.