Compare commits

...

9 Commits
master ... rest

Author SHA1 Message Date
265bf8b275 add rest controller 2024-10-22 17:39:38 +04:00
e8db1102e6 add ajax controller and requests 2022-10-05 01:41:08 +04:00
c8db7fb9bc add resources example 2022-09-21 17:44:07 +04:00
0d54eca2bf fix button 2022-09-14 16:02:25 +04:00
2ec0ca5716 add bootstrap 2022-09-14 15:58:54 +04:00
fecef79d76 fix build.gradle 2022-09-14 14:31:22 +04:00
b6fbbfcbe8 Merge branch 'master' into crud
# Conflicts:
#	build.gradle
2022-09-14 14:24:30 +04:00
Katerina881
46f904d893 fix dependencies 2021-10-28 17:33:49 +04:00
Anton Romanov
b126afac5e crud implementation 2021-10-28 17:07:25 +04:00
28 changed files with 3634 additions and 30 deletions

View File

@ -13,23 +13,24 @@ apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-serving-web-content'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 17
targetCompatibility = 17
sourceCompatibility = 11
targetCompatibility = 11
dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
implementation group: 'org.springframework.boot', name: 'spring-boot-devtools'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
implementation group: 'com.h2database', name: 'h2'
implementation group: 'javax.xml.bind', name: 'jaxb-api'
implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
implementation group: 'javassist', name: 'javassist', version: '3.12.1.GA'
implementation group: 'junit', name: 'junit'
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
}

2900
data/emails.trace.db Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
package email;
import email.model.Email;
import email.service.EmailService;
import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@Hidden
@RequestMapping("/ajax")
public class AjaxController {
private final EmailService emailService;
public AjaxController(EmailService emailService) {
this.emailService = emailService;
}
@ResponseBody
@GetMapping("/getEmail/{id}")
public Email getEmail(@PathVariable("id") Integer id) {
return emailService.getEmailById(id);
}
@ResponseBody
@GetMapping("/list")
public List<Email> getList() {
return emailService.getAllEmails();
}
@ResponseBody
@PostMapping("/saveEmail")
public Email saveEmail(@RequestBody Email email) {
if (email.getTo().isEmpty()) {
throw new RuntimeException("Поле 'Кому' не должно быть пустым");
}
Email previousEmail = emailService.getEmailById(email.getId());
previousEmail.setMessage(email.getMessage());
previousEmail.setSubject(email.getSubject());
previousEmail.setTo(email.getTo());
return emailService.save(previousEmail);
}
}

View File

@ -1,6 +1,8 @@
package email;
import email.model.Email;
import email.model.EmailForm;
import email.service.EmailService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@ -9,6 +11,11 @@ import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class EmailController {
private final EmailService emailService;
public EmailController(EmailService emailService) {
this.emailService = emailService;
}
@GetMapping("/")
public String indexForm(Model model) {
@ -22,7 +29,14 @@ public class EmailController {
model.addAttribute("error", "'Кому' не должно быть пустым");
return "index";
}
return "result";
emailService.save(new Email(emailForm.getTo(), emailForm.getSubject(), emailForm.getMessage()));
model.addAttribute("emails", emailService.getAllEmails());
return "list";
}
@GetMapping("/list")
public String list(Model model) {
model.addAttribute("emails", emailService.getAllEmails());
return "list";
}
}

View File

@ -0,0 +1,48 @@
package email;
import email.model.Email;
import email.service.EmailService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/rest")
public class EmailRestController {
private final EmailService emailService;
public EmailRestController(EmailService emailService) {
this.emailService = emailService;
}
@ResponseBody
@GetMapping("/getEmail/{id}")
public Email getEmail(@PathVariable("id") Integer id) {
return emailService.getEmailById(id);
}
@ResponseBody
@GetMapping("/list")
public List<Email> getList() {
return emailService.getAllEmails();
}
@ResponseBody
@PostMapping("/saveEmail")
public Email saveEmail(@RequestBody Email email) {
if (email.getTo().isEmpty()) {
throw new RuntimeException("Поле 'Кому' не должно быть пустым");
}
Email previousEmail = emailService.getEmailById(email.getId());
previousEmail.setMessage(email.getMessage());
previousEmail.setSubject(email.getSubject());
previousEmail.setTo(email.getTo());
return emailService.save(previousEmail);
}
}

View File

@ -0,0 +1,49 @@
package email.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
@Bean
public LocaleResolver localeResolver() {
return new CookieLocaleResolver();
}
@Bean
public LocaleChangeInterceptor localeInterceptor() {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
localeInterceptor.setParamName("lang");
return localeInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeInterceptor());
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

View File

@ -0,0 +1,83 @@
package email.core;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
@Version
private Integer version;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().isAssignableFrom(obj.getClass())) {
return false;
}
BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
return result;
}
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"id=" + id +
", version=" + version +
'}';
}
@Override
public int compareTo(@NotNull BaseEntity o) {
return id != null ? id.compareTo(o.getId()) : -1;
}
public void reset() {
this.id = null;
this.version = null;
}
}

View File

@ -0,0 +1,46 @@
package email.model;
import email.core.BaseEntity;
import javax.persistence.Entity;
@Entity
public class Email extends BaseEntity {
private String to;
private String subject;
private String message;
public Email() {
}
public Email(String to, String subject, String message) {
this.to = to;
this.subject = subject;
this.message = message;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,10 @@
package email.repository;
import email.model.Email;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmailRepository extends JpaRepository<Email, Integer> {
}

View File

@ -0,0 +1,33 @@
package email.service;
import email.model.Email;
import email.repository.EmailRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmailService {
private final EmailRepository emailRepository;
public EmailService(EmailRepository emailRepository) {
this.emailRepository = emailRepository;
}
public List<Email> getAllEmails() {
return emailRepository.findAll();
}
public Email save(Email email) {
return emailRepository.save(email);
}
public Email getEmailById(Integer id) {
return emailRepository.getById(id);
}
public void delete(Integer setId) {
emailRepository.deleteById(setId);
}
}

View File

@ -0,0 +1,15 @@
# Server Settings
spring.main.banner-mode=off
server.port=8080
# Log settings (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
logging.level.ru.ulstu=DEBUG
#JPA
spring.jackson.serialization.fail-on-empty-beans=false
# go to http://localhost:8080/h2-console
spring.datasource.url=jdbc:h2:file:./data/emails
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,51 @@
function edit(id) {
$.get("ajax/getEmail/"+id, function( data ) {
$('#editId').text(data.id);
$('#editTo').val(data.to);
$('#editMessage').val(data.message);
$('#editSubject').val(data.subject);
$('#editModal').modal('show');
});
}
function save() {
postData = {
id:$('#editId').text(),
to:$('#editTo').val(),
message:$('#editMessage').val(),
subject:$('#editSubject').val(),
version:0
};
$.ajax({
url: 'ajax/saveEmail',
cache: false,
dataType: "json",
data: JSON.stringify(postData),
contentType: "application/json; charset=utf-8",
processData: false,
method: "POST",
success: function (response) {
$('#editModal').modal('hide');
$("#records").html('');
loadList();
},
error: function( error) {
alert(error.responseText);
}
});
}
function loadList() {
$.get("ajax/list", function( data ) {
$.each(data, function(key, value) {
$("#records").append(
"<div class='col-md-2'>"+value.to+"</div>"+
"<div class='col-md-4'>"+value.subject+"</div>"+
"<div class='col-md-4'>"+value.message+"</div>"+
"<div class='col-md-2' onclick='edit("+value.id+")'><i class='fa-solid fa-pen-to-square'></i></div>"
);
});
});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,127 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Список записей в БД</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/fa/fa.min.css" rel="stylesheet">
<script src="/js/bootstrap.bundle.min.js"></script>
<script src="/js/jquery-3.6.1.min.js"></script>
<script src="/js/ajax.js"></script>
</head>
<body>
<!-- компонент меню-->
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Название web-приложения</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Главная страница</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/list">Список отправленных сообщений</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/ajax">Динамическая страница</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Выпадающее меню
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Пункт 1</a></li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Недоступно</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 col-sm-12">
<h2>Список записей в БД:</h2>
<div class="row">
<div class="col-md-2" style="font-weight: bold">
Кому
</div>
<div class="col-md-4" style="font-weight: bold">
Тема
</div>
<div class="col-md-4" style="font-weight: bold">
Сообщение
</div>
</div>
<div class="row" id="records">
</div>
<a class="btn btn-primary" href="/">Отправить другое сообщение</a>
<!-- <img src="img/logo.png"/>-->
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p style="color:red"></p>
<div class="d-none" id="editId"></div>
<div class="form-group">
<label for="editSubject">Тема</label>
<input type="text" class="form-control" id="editSubject" placeholder="Введите тему">
</div>
<div class="form-group">
<label for="editTo">Кому</label>
<input class="form-control" type="email" id="editTo" placeholder="Кому"/>
</div>
<div class="form-group">
<label for="editMessage">Сообщение</label>
<textarea class="form-control" id="editMessage" placeholder="Сообщение"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"
onclick="$('#editModal').modal('hide');">Close
</button>
<button type="button" class="btn btn-primary" onclick="save()">Сохранить</button>
</div>
</div>
</div>
</div>
</div>
<script src="/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
console.log("load");
loadList();
});
</script>
</body>
</html>

View File

@ -2,29 +2,80 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Простая обработка формы на Spring MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<h1>Форма</h1>
<form action="#" th:action="@{/sendEmail}" th:object="${emailForm}" method="post">
<p style="color:red" th:text="${error}"></p>
<table>
<tr>
<td>Тема:</td>
<td><input type="text" th:field="*{subject}"/></td>
</tr>
<tr>
<td>Кому:</td>
<td><input type="text" th:field="*{to}"/></td>
</tr>
<tr>
<td>Сообщение:</td>
<td><textarea th:field="*{message}"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Отправить"/></td>
</tr>
</table>
</form>
<!-- компонент меню-->
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Название web-приложения</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Главная страница</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/list">Список отправленных сообщений</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/ajax">Динамическая страница</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Выпадающее меню
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Пункт 1</a></li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Недоступно</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 col-sm-12">
<h2>Форма</h2>
<form action="#" th:action="@{/sendEmail}" th:object="${emailForm}" method="post">
<p style="color:red" th:text="${error}"></p>
<div class="form-group">
<label for="theme">Тема</label>
<input type="text" class="form-control" id="theme" placeholder="Введите тему" th:field="*{subject}">
</div>
<div class="form-group">
<label for="to">Кому</label>
<input class="form-control" type="email" id="to" th:field="*{to}" placeholder="Кому"/>
</div>
<div class="form-group">
<label for="message">Сообщение</label>
<textarea class="form-control" id="message" th:field="*{message}" placeholder="Сообщение"/>
</div>
<input class="form-group" type="submit" value="Отправить"/>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Список записей в БД</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<!-- компонент меню-->
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Название web-приложения</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Главная страница</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/list">Список отправленных сообщений</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/ajax">Динамическая страница</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Выпадающее меню
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Пункт 1</a></li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Недоступно</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 col-sm-12">
<h2>Список записей в БД:</h2>
<div class="row">
<div class="col-md-4" style="font-weight: bold">
Кому
</div>
<div class="col-md-4" style="font-weight: bold">
Тема
</div>
<div class="col-md-4" style="font-weight: bold">
Сообщение
</div>
</div>
<div class="row" th:each="email: ${emails}">
<div class="col-md-4" th:text="${email.to}"/>
<div class="col-md-4" th:text="${email.subject}"/>
<div class="col-md-4" th:text="${email.message}"/>
</div>
<!--<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">Кому</th>
<th scope="col">Тема</th>
<th scope="col">Сообщение</th>
</tr>
</thead>
<tbody>
<tr th:each="email: ${emails}">
<td th:text="${email.to}">
</td>
<td th:text="${email.subject}">
</td>
<td th:text="${email.message}">
</td>
</tr>
</tbody>
</table>-->
<a class="btn btn-primary" href="/">Отправить другое сообщение</a>
<!-- <img src="img/logo.png"/>-->
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
crossorigin="anonymous"></script>
</body>
</html>