first commit
							
								
								
									
										11
									
								
								src/main/java/searchengine/Application.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,11 @@ | ||||
| package searchengine; | ||||
|  | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
|  | ||||
| @SpringBootApplication | ||||
| public class Application { | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(Application.class, args); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								src/main/java/searchengine/config/Site.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,11 @@ | ||||
| package searchengine.config; | ||||
|  | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
|  | ||||
| @Setter | ||||
| @Getter | ||||
| public class Site { | ||||
|     private String url; | ||||
|     private String name; | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/main/java/searchengine/config/SitesList.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,16 @@ | ||||
| package searchengine.config; | ||||
|  | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @Getter | ||||
| @Setter | ||||
| @Component | ||||
| @ConfigurationProperties(prefix = "indexing-settings") | ||||
| public class SitesList { | ||||
|     private List<Site> sites; | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/main/java/searchengine/controllers/ApiController.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| package searchengine.controllers; | ||||
|  | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import searchengine.config.SitesList; | ||||
| import searchengine.dto.statistics.StatisticsResponse; | ||||
| import searchengine.services.StatisticsService; | ||||
|  | ||||
| @RestController | ||||
| @RequestMapping("/api") | ||||
| public class ApiController { | ||||
|  | ||||
|     private final StatisticsService statisticsService; | ||||
|  | ||||
|     public ApiController(StatisticsService statisticsService) { | ||||
|         this.statisticsService = statisticsService; | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/statistics") | ||||
|     public ResponseEntity<StatisticsResponse> statistics() { | ||||
|         return ResponseEntity.ok(statisticsService.getStatistics()); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/startIndexing") | ||||
|     public ResponseEntity<StatisticsResponse> startIndexing() { | ||||
|         System.out.println(new SitesList().getSites()); | ||||
|         return ResponseEntity.ok(statisticsService.getStatistics()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package searchengine.controllers; | ||||
|  | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
|  | ||||
| @Controller | ||||
| public class DefaultController { | ||||
|  | ||||
|     /** | ||||
|      * Метод формирует страницу из HTML-файла index.html, | ||||
|      * который находится в папке resources/templates. | ||||
|      * Это делает библиотека Thymeleaf. | ||||
|      */ | ||||
|     @RequestMapping("/") | ||||
|     public String index() { | ||||
|         return "index"; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,14 @@ | ||||
| package searchengine.dto.statistics; | ||||
|  | ||||
| import lombok.Data; | ||||
|  | ||||
| @Data | ||||
| public class DetailedStatisticsItem { | ||||
|     private String url; | ||||
|     private String name; | ||||
|     private String status; | ||||
|     private long statusTime; | ||||
|     private String error; | ||||
|     private int pages; | ||||
|     private int lemmas; | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| package searchengine.dto.statistics; | ||||
|  | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @Data | ||||
| public class StatisticsData { | ||||
|     private TotalStatistics total; | ||||
|     private List<DetailedStatisticsItem> detailed; | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| package searchengine.dto.statistics; | ||||
|  | ||||
| import lombok.Data; | ||||
|  | ||||
| @Data | ||||
| public class StatisticsResponse { | ||||
|     private boolean result; | ||||
|     private StatisticsData statistics; | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| package searchengine.dto.statistics; | ||||
|  | ||||
| import lombok.Data; | ||||
|  | ||||
| @Data | ||||
| public class TotalStatistics { | ||||
|     private int sites; | ||||
|     private int pages; | ||||
|     private int lemmas; | ||||
|     private boolean indexing; | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/main/java/searchengine/model/PageEntity.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,30 @@ | ||||
| package searchengine.model; | ||||
|  | ||||
| import jakarta.persistence.*; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
|  | ||||
| @Getter | ||||
| @Setter | ||||
| @Entity | ||||
| @Table(name = "page", indexes = @Index(columnList = "path")) | ||||
| public class PageEntity { | ||||
|     @Id | ||||
|     @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||
|     @Column(nullable = false) | ||||
|     private int id; | ||||
|  | ||||
|     @ManyToOne(cascade = CascadeType.ALL) | ||||
|     @JoinColumn(name = "site_id", nullable = false) | ||||
|     private SiteEntity site; | ||||
|  | ||||
|     @Column(columnDefinition = "TEXT NOT NULL, UNIQUE KEY INDEX_PATH (path(255))") // Unique index version | ||||
| //    @Column(columnDefinition = "TEXT NOT NULL, INDEX PATH_INDEX USING BTREE(path(255))") // Non-unique index version | ||||
|     private String path; | ||||
|  | ||||
|     @Column(nullable = false) | ||||
|     private int code; | ||||
|  | ||||
|     @Column(nullable = false, columnDefinition = "MEDIUMTEXT") | ||||
|     private String content; | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/main/java/searchengine/model/SiteEntity.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,34 @@ | ||||
| package searchengine.model; | ||||
|  | ||||
| import jakarta.persistence.*; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| @Getter | ||||
| @Setter | ||||
| @Entity | ||||
| @Table(name = "site") | ||||
| public class SiteEntity { | ||||
|     @Id | ||||
|     @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||
|     @Column(nullable = false) | ||||
|     private int id; | ||||
|  | ||||
|     @Enumerated(EnumType.STRING) | ||||
|     @Column(nullable = false) | ||||
|     private StatusType status; | ||||
|  | ||||
|     @Column(nullable = false) | ||||
|     private LocalDateTime status_time; | ||||
|  | ||||
|     @Column(columnDefinition = "TEXT") | ||||
|     private String last_error; | ||||
|  | ||||
|     @Column(nullable = false, columnDefinition = "VARCHAR(255)") | ||||
|     private String url; | ||||
|  | ||||
|     @Column(nullable = false, columnDefinition = "VARCHAR(255)") | ||||
|     private String name; | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/main/java/searchengine/model/StatusType.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,7 @@ | ||||
| package searchengine.model; | ||||
|  | ||||
| public enum StatusType { | ||||
|     INDEXING, | ||||
|     INDEXED, | ||||
|     FAILED | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| package searchengine.repository; | ||||
|  | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import searchengine.model.PageEntity; | ||||
|  | ||||
| @Repository | ||||
| public interface PageRepository extends CrudRepository<PageEntity, Integer> { | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| package searchengine.repository; | ||||
|  | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import searchengine.model.SiteEntity; | ||||
|  | ||||
| @Repository | ||||
| public interface SiteRepository extends CrudRepository<SiteEntity, Integer> { | ||||
| } | ||||
							
								
								
									
										4
									
								
								src/main/java/searchengine/services/IndexingService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,4 @@ | ||||
| package searchengine.services; | ||||
|  | ||||
| public interface IndexingService { | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/main/java/searchengine/services/IndexingServiceImpl.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,16 @@ | ||||
| package searchengine.services; | ||||
|  | ||||
| public class IndexingServiceImpl implements IndexingService { | ||||
|     boolean indexingIsRunning = false; | ||||
|  | ||||
|     public void startIndexing() { | ||||
|         if (indexingIsRunning) { | ||||
|             System.out.println("Индексация уже запущена"); | ||||
|             return; | ||||
|         } | ||||
|         // Логика для запуска индексации или перенидексации сайтов | ||||
|         System.out.println("Запуск индексации"); | ||||
|         indexingIsRunning = true; | ||||
|         System.out.println("Индексация запущена"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,7 @@ | ||||
| package searchengine.services; | ||||
|  | ||||
| import searchengine.dto.statistics.StatisticsResponse; | ||||
|  | ||||
| public interface StatisticsService { | ||||
|     StatisticsResponse getStatistics(); | ||||
| } | ||||
| @@ -0,0 +1,64 @@ | ||||
| package searchengine.services; | ||||
|  | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.stereotype.Service; | ||||
| import searchengine.config.Site; | ||||
| import searchengine.config.SitesList; | ||||
| import searchengine.dto.statistics.DetailedStatisticsItem; | ||||
| import searchengine.dto.statistics.StatisticsData; | ||||
| import searchengine.dto.statistics.StatisticsResponse; | ||||
| import searchengine.dto.statistics.TotalStatistics; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Random; | ||||
|  | ||||
| @Service | ||||
| @RequiredArgsConstructor | ||||
| public class StatisticsServiceImpl implements StatisticsService { | ||||
|  | ||||
|     private final Random random = new Random(); | ||||
|     private final SitesList sites; | ||||
|  | ||||
|     @Override | ||||
|     public StatisticsResponse getStatistics() { | ||||
|         String[] statuses = { "INDEXED", "FAILED", "INDEXING" }; | ||||
|         String[] errors = { | ||||
|                 "Ошибка индексации: главная страница сайта не доступна", | ||||
|                 "Ошибка индексации: сайт не доступен", | ||||
|                 "" | ||||
|         }; | ||||
|  | ||||
|         TotalStatistics total = new TotalStatistics(); | ||||
|         total.setSites(sites.getSites().size()); | ||||
|         total.setIndexing(true); | ||||
|  | ||||
|         List<DetailedStatisticsItem> detailed = new ArrayList<>(); | ||||
|         List<Site> sitesList = sites.getSites(); | ||||
|         for(int i = 0; i < sitesList.size(); i++) { | ||||
|             Site site = sitesList.get(i); | ||||
|             DetailedStatisticsItem item = new DetailedStatisticsItem(); | ||||
|             item.setName(site.getName()); | ||||
|             item.setUrl(site.getUrl()); | ||||
|             int pages = random.nextInt(1_000); | ||||
|             int lemmas = pages * random.nextInt(1_000); | ||||
|             item.setPages(pages); | ||||
|             item.setLemmas(lemmas); | ||||
|             item.setStatus(statuses[i % 3]); | ||||
|             item.setError(errors[i % 3]); | ||||
|             item.setStatusTime(System.currentTimeMillis() - | ||||
|                     (random.nextInt(10_000))); | ||||
|             total.setPages(total.getPages() + pages); | ||||
|             total.setLemmas(total.getLemmas() + lemmas); | ||||
|             detailed.add(item); | ||||
|         } | ||||
|  | ||||
|         StatisticsResponse response = new StatisticsResponse(); | ||||
|         StatisticsData data = new StatisticsData(); | ||||
|         data.setTotal(total); | ||||
|         data.setDetailed(detailed); | ||||
|         response.setStatistics(data); | ||||
|         response.setResult(true); | ||||
|         return response; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										2393
									
								
								src/main/resources/static/assets/css/basic.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1144
									
								
								src/main/resources/static/assets/css/extra.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										117
									
								
								src/main/resources/static/assets/css/fonts.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat Black"; | ||||
|     src: url("Montserrat-Black.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Black.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Black.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Black.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Black.svg#Montserrat Black") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 50 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat"; | ||||
|     src: url("Montserrat-Bold.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Bold.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Bold.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Bold.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Bold.svg#Montserrat") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 52 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat ExtraBold"; | ||||
|     src: url("Montserrat-ExtraBold.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-ExtraBold.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-ExtraBold.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-ExtraBold.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-ExtraBold.svg#Montserrat ExtraBold") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 51 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat ExtraLight"; | ||||
|     src: url("Montserrat-ExtraLight.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-ExtraLight.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-ExtraLight.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-ExtraLight.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-ExtraLight.svg#Montserrat ExtraLight") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 53 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat Light"; | ||||
|     src: url("Montserrat-Light.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Light.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Light.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Light.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Light.svg#Montserrat Light") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 53 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat Medium"; | ||||
|     src: url("Montserrat-Medium.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Medium.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Medium.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Medium.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Medium.svg#Montserrat Medium") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 53 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat"; | ||||
|     src: url("Montserrat-Regular.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Regular.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Regular.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Regular.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Regular.svg#Montserrat") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 53 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat SemiBold"; | ||||
|     src: url("Montserrat-SemiBold.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-SemiBold.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-SemiBold.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-SemiBold.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-SemiBold.svg#Montserrat SemiBold") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 52 KiB | 
| @@ -0,0 +1,12 @@ | ||||
| @font-face { | ||||
|     font-family: "Montserrat Thin"; | ||||
|     src: url("Montserrat-Thin.eot"); /* IE9 */ | ||||
|     src: url("Montserrat-Thin.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ | ||||
|     url("Montserrat-Thin.woff") format("woff"), /* chrome, firefox */ | ||||
|     url("Montserrat-Thin.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ | ||||
|     url("Montserrat-Thin.svg#Montserrat Thin") format("svg"); /* iOS 4.1- */ | ||||
|     font-style: normal; | ||||
|     font-weight: normal; | ||||
| } | ||||
|  | ||||
|  | ||||
| After Width: | Height: | Size: 54 KiB | 
| @@ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 386.257 386.257"><path d="M0 96.879l193.129 192.5 193.128-192.5z"/></svg> | ||||
| After Width: | Height: | Size: 126 B | 
							
								
								
									
										1
									
								
								src/main/resources/static/assets/img/icons/cancel.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 0C115.3 0 0 115.3 0 256s115.3 256 256 256 256-115.3 256-256S396.7 0 256 0z" fill="#ff3636"/><path d="M512 256c0 140.7-115.3 256-256 256V0c140.7 0 256 115.3 256 256z" fill="#f40000"/><path fill="#e7e7e7" d="M298.299 256l84.901 84.901-42.299 42.299L256 298.299 171.099 383.2 128.8 340.901 213.701 256 128.8 171.099l42.299-42.299L256 213.701l84.901-84.901 42.299 42.299z"/><path fill="#d3d3d8" d="M298.299 256l84.901 84.901-42.299 42.299L256 298.299v-84.598l84.901-84.901 42.299 42.299z"/></svg> | ||||
| After Width: | Height: | Size: 568 B | 
							
								
								
									
										1
									
								
								src/main/resources/static/assets/img/icons/checked.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 0C115.3 0 0 115.3 0 256s115.3 256 256 256 256-115.3 256-256S396.7 0 256 0z" fill="#7d0"/><path d="M512 256c0 140.7-115.3 256-256 256V0c140.7 0 256 115.3 256 256z" fill="#6b0"/><path fill="#e7e7e7" d="M401.8 212.5L226 388.299l-126.301-126 42.602-42.6 83.699 84 30-30L359.5 170.2z"/><path fill="#d3d3d8" d="M401.8 212.5L256 358.299v-84.6L359.5 170.2z"/></svg> | ||||
| After Width: | Height: | Size: 433 B | 
							
								
								
									
										1
									
								
								src/main/resources/static/assets/img/icons/dashboard.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#ffb74f" d="M432.106 250.534v219.487H296.578V336.975h-75.179v133.046H79.894V250.534L256 115.075z"/><path d="M439.485 183.135V90.306h-74.167v35.772L256 41.979 0 238.92l53.633 69.712L256 152.959l202.367 155.672L512 238.92l-72.515-55.785z" fill="#ff7d3c"/><path fill="#ff9a00" d="M432.106 250.534v219.487H296.578V336.975H256v-221.9z"/><path fill="#ff4e19" d="M512 238.92l-53.633 69.712L256 152.959V41.979l109.318 84.099V90.306h74.167v92.829z"/></svg> | ||||
| After Width: | Height: | Size: 521 B | 
| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										1
									
								
								src/main/resources/static/assets/img/icons/pause.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M0 256c0 141.384 114.615 256 256 256l22.261-256L256 0C114.615 0 0 114.615 0 256z" fill="#bfdcff"/><path d="M256 0v512c141.384 0 256-114.616 256-256S397.384 0 256 0z" fill="#8bc0ff"/><path fill="#3897ff" d="M155.826 144.696h66.783v222.609h-66.783z"/><path fill="#2d79cc" d="M289.391 144.696h66.783v222.609h-66.783z"/></svg> | ||||
| After Width: | Height: | Size: 393 B | 
							
								
								
									
										1
									
								
								src/main/resources/static/assets/img/icons/search.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M179.907 317.89l63.63-63.63 17.675 17.676-63.63 63.63z" fill="#83a3ab"/><path d="M176.371 314.355l63.63-63.63 10.605 10.605-63.63 63.63zM66.192 403.381l-53.033 95.46c17.545 17.545 46.094 17.546 63.64 0l21.213-21.213z" fill="#93b7c0"/><path d="M34.373 413.988L13.16 435.201c-17.546 17.546-17.545 46.094 0 63.64l74.246-74.246z" fill="#acd5df"/><path d="M98.012 477.627L240.06 335.58l-31.82-31.82-92.237 49.811-49.811 92.237z" fill="#3a6fd8"/><path d="M34.335 413.954L176.36 271.93l31.815 31.815L66.15 445.769z" fill="#3b88f5"/><path d="M463.526 48.474l-175.539 58.513-58.513 175.539c64.632 64.632 169.421 64.632 234.052 0s64.632-169.42 0-234.052z" fill="#93b7c0"/><path d="M229.474 48.474c-64.632 64.632-64.632 169.421 0 234.052L463.526 48.474c-64.632-64.632-169.42-64.632-234.052 0z" fill="#acd5df"/><path d="M421.1 90.9l-111.9 37.3-37.3 111.9c41.2 41.2 107.999 41.2 149.2 0s41.2-107.999 0-149.2z" fill="#c4f3ff"/><path d="M271.9 90.9c-41.2 41.2-41.2 107.999 0 149.2L421.1 90.9c-41.201-41.2-107.999-41.2-149.2 0z" fill="#fff"/></svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										1954
									
								
								src/main/resources/static/assets/js/scripts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1193
									
								
								src/main/resources/static/assets/plg/form/jquery.form.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								src/main/resources/static/assets/plg/form/jquery.maskedinput.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,7 @@ | ||||
| /* | ||||
|     jQuery Masked Input Plugin | ||||
|     Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com) | ||||
|     Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) | ||||
|     Version: 1.4.1 | ||||
| */ | ||||
| !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b,c=navigator.userAgent,d=/iphone/i.test(c),e=/chrome/i.test(c),f=/android/i.test(c);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(c,g){var h,i,j,k,l,m,n,o;if(!c&&this.length>0){h=a(this[0]);var p=h.data(a.mask.dataName);return p?p():void 0}return g=a.extend({autoclear:a.mask.autoclear,placeholder:a.mask.placeholder,completed:null},g),i=a.mask.definitions,j=[],k=n=c.length,l=null,a.each(c.split(""),function(a,b){"?"==b?(n--,k=a):i[b]?(j.push(new RegExp(i[b])),null===l&&(l=j.length-1),k>a&&(m=j.length-1)):j.push(null)}),this.trigger("unmask").each(function(){function h(){if(g.completed){for(var a=l;m>=a;a++)if(j[a]&&C[a]===p(a))return;g.completed.call(B)}}function p(a){return g.placeholder.charAt(a<g.placeholder.length?a:0)}function q(a){for(;++a<n&&!j[a];);return a}function r(a){for(;--a>=0&&!j[a];);return a}function s(a,b){var c,d;if(!(0>a)){for(c=a,d=q(b);n>c;c++)if(j[c]){if(!(n>d&&j[c].test(C[d])))break;C[c]=C[d],C[d]=p(d),d=q(d)}z(),B.caret(Math.max(l,a))}}function t(a){var b,c,d,e;for(b=a,c=p(a);n>b;b++)if(j[b]){if(d=q(b),e=C[b],C[b]=c,!(n>d&&j[d].test(e)))break;c=e}}function u(){var a=B.val(),b=B.caret();if(o&&o.length&&o.length>a.length){for(A(!0);b.begin>0&&!j[b.begin-1];)b.begin--;if(0===b.begin)for(;b.begin<l&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}else{for(A(!0);b.begin<n&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}h()}function v(){A(),B.val()!=E&&B.change()}function w(a){if(!B.prop("readonly")){var b,c,e,f=a.which||a.keyCode;o=B.val(),8===f||46===f||d&&127===f?(b=B.caret(),c=b.begin,e=b.end,e-c===0&&(c=46!==f?r(c):e=q(c-1),e=46===f?q(e):e),y(c,e),s(c,e-1),a.preventDefault()):13===f?v.call(this,a):27===f&&(B.val(E),B.caret(0,A()),a.preventDefault())}}function x(b){if(!B.prop("readonly")){var c,d,e,g=b.which||b.keyCode,i=B.caret();if(!(b.ctrlKey||b.altKey||b.metaKey||32>g)&&g&&13!==g){if(i.end-i.begin!==0&&(y(i.begin,i.end),s(i.begin,i.end-1)),c=q(i.begin-1),n>c&&(d=String.fromCharCode(g),j[c].test(d))){if(t(c),C[c]=d,z(),e=q(c),f){var k=function(){a.proxy(a.fn.caret,B,e)()};setTimeout(k,0)}else B.caret(e);i.begin<=m&&h()}b.preventDefault()}}}function y(a,b){var c;for(c=a;b>c&&n>c;c++)j[c]&&(C[c]=p(c))}function z(){B.val(C.join(""))}function A(a){var b,c,d,e=B.val(),f=-1;for(b=0,d=0;n>b;b++)if(j[b]){for(C[b]=p(b);d++<e.length;)if(c=e.charAt(d-1),j[b].test(c)){C[b]=c,f=b;break}if(d>e.length){y(b+1,n);break}}else C[b]===e.charAt(d)&&d++,k>b&&(f=b);return a?z():k>f+1?g.autoclear||C.join("")===D?(B.val()&&B.val(""),y(0,n)):z():(z(),B.val(B.val().substring(0,f+1))),k?b:l}var B=a(this),C=a.map(c.split(""),function(a,b){return"?"!=a?i[a]?p(b):a:void 0}),D=C.join(""),E=B.val();B.data(a.mask.dataName,function(){return a.map(C,function(a,b){return j[b]&&a!=p(b)?a:null}).join("")}),B.one("unmask",function(){B.off(".mask").removeData(a.mask.dataName)}).on("focus.mask",function(){if(!B.prop("readonly")){clearTimeout(b);var a;E=B.val(),a=A(),b=setTimeout(function(){B.get(0)===document.activeElement&&(z(),a==c.replace("?","").length?B.caret(0,a):B.caret(a))},10)}}).on("blur.mask",v).on("keydown.mask",w).on("keypress.mask",x).on("input.mask paste.mask",function(){B.prop("readonly")||setTimeout(function(){var a=A(!0);B.caret(a),h()},0)}),e&&f&&B.off("input.mask").on("input.mask",u),A()})}})}); | ||||
							
								
								
									
										2
									
								
								src/main/resources/static/assets/plg/jQuery/jquery-3.5.0.slim.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2
									
								
								src/main/resources/static/assets/plg/jQuery/jquery-3.5.1.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										162
									
								
								src/main/resources/templates/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,162 @@ | ||||
|  | ||||
| <!--END--> | ||||
| <!--END--><!DOCTYPE html><!--[if IE 7]> | ||||
| <html class="ie7" lang="ru"> | ||||
| <![endif]--> | ||||
| <!--[if IE 8]> | ||||
| <html class="ie8" lang="ru"> | ||||
| <![endif]--> | ||||
| <!--[if IE 9]> | ||||
| <html class="ie9" lang="ru"> | ||||
| <![endif]--> | ||||
| <!--[if gt IE 9]><!--> <html lang="ru"> <!--<![endif]--> | ||||
| <head> | ||||
|   <title>Site Search Engine</title> | ||||
|   <meta name="description" content="Site Search Engine"> | ||||
|   <meta charset="utf-8"> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> | ||||
|   <!--meta( http-equiv="cache-control" content="no-cache")--> | ||||
|   <!--meta( http-equiv="expires" content="0")--> | ||||
|   <!--link(rel="preload" href="assets/css/extra.min.css?v=" + version as="style" crossorigin="anonymous")--> | ||||
|   <link href="favicon.ico" rel="shortcut icon"> | ||||
|   <link rel="preload" href="/assets/fonts/Montserrat/Montserrat-SemiBold.woff2" as="font" crossorigin="anonymous"> | ||||
|   <link rel="preload" href="/assets/fonts/Montserrat/Montserrat-Light.woff2" as="font" crossorigin="anonymous"> | ||||
|   <link rel="preload" href="/assets/fonts/Montserrat/Montserrat-Medium.woff2" as="font" crossorigin="anonymous"> | ||||
|   <link rel="preload" href="/assets/fonts/Montserrat/Montserrat-ExtraBold.woff2" as="font" crossorigin="anonymous"> | ||||
|   <link rel="stylesheet" href="/assets/css/fonts.css?v=82368483"> | ||||
|   <link rel="stylesheet" href="/assets/css/basic.css?v=82368483"> | ||||
|   <link rel="stylesheet" href="/assets/css/extra.css?v=82368483"><!--[if lt IE 9]> | ||||
|   <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]--> | ||||
|  | ||||
|   <script> | ||||
|      var backendApiUrl = 'api' | ||||
|   </script> | ||||
|    | ||||
|   <script defer src="/assets/js/scripts.js?v=38874865"></script> | ||||
|  | ||||
| </head> | ||||
| <body class="Site"> | ||||
|   <!--if lt IE 8 | ||||
|   p.error-browser | ||||
|       | Ваш браузер  | ||||
|       em устарел!  | ||||
|       a(href="http://browsehappy.com/") Выберите новую версию | ||||
|           +s | ||||
|           | браузера здесь  | ||||
|       | для правильного отображения сайта. | ||||
|   --> | ||||
|   <div class="Site-loader"> | ||||
|     <div class="Site-loader-block"> | ||||
|       <div> | ||||
|       </div> | ||||
|       <div> | ||||
|       </div> | ||||
|       <div> | ||||
|       </div> | ||||
|       <div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="Middle"> | ||||
|     <div class="wrap"> | ||||
|       <div class="Site-loadingIsComplete"> | ||||
|         <main class="Tabs Tabs_column Middle-main"> | ||||
|           <div class="Column"> | ||||
|             <div class="Tabs-links"><a class="Tabs-link Tabs-link_ACTIVE" href="#dashboard"><img class="Tabs-icon" src="/assets/img/icons/dashboard.svg" alt="dashboard.svg"/><span class="Tabs-linkText">Dashboard</span></a><a class="Tabs-link" href="#management"><img class="Tabs-icon" src="/assets/img/icons/management.svg" alt="management.svg"/><span class="Tabs-linkText">Management</span></a><a class="Tabs-link" href="#search"><img class="Tabs-icon" src="/assets/img/icons/search.svg" alt="search.svg"/><span class="Tabs-linkText">Search</span></a> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="Tabs-wrap"> | ||||
|             <div class="Tabs-block" id="dashboard"> | ||||
|               <div class="Section"> | ||||
|                 <div class="Section-header"> | ||||
|                   <h2 class="Section-title">Dashboard | ||||
|                   </h2> | ||||
|                 </div> | ||||
|                 <div class="Statistics"> | ||||
|                   <div class="Statistics-info"> | ||||
|                     <div class="Statistics-block"><span class="Statistics-amount" id="totalSites"></span><span class="Statistics-title">sites</span> | ||||
|                     </div> | ||||
|                     <div class="Statistics-block"><span class="Statistics-amount" id="totalPages"></span><span class="Statistics-title">pages</span> | ||||
|                     </div> | ||||
|                     <div class="Statistics-block"><span class="Statistics-amount" id="totalLemmas"></span><span class="Statistics-title">lemmas</span> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   <div class="HideBlock Statistics-example"> | ||||
|                     <header class="HideBlock-header HideBlock-trigger"> | ||||
|                       <strong class="HideBlock-title"><span class="Statistics-status"></span> | ||||
|                       </strong> | ||||
|                       <button class="HideBlock-btn" type="button"> | ||||
|                       </button> | ||||
|                     </header> | ||||
|                     <div class="HideBlock-content"> | ||||
|                       <p class="Statistics-description"> | ||||
|                       </p> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="Tabs-block" id="management"> | ||||
|               <div class="Section"> | ||||
|                 <div class="Section-header"> | ||||
|                   <h2 class="Section-title">Management | ||||
|                   </h2> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                   <button class="btn btn_primary API-startIndexing" data-btntype="check" data-check="false" data-alttext="Stop indexing" data-send="startIndexing" data-altsend="stopIndexing"><span class="btn-content">Start indexing</span> | ||||
|                   </button> | ||||
|                 </div><br> | ||||
|                 <div class="UpdatePageBlock"> | ||||
|                   <h3>Add/update page: | ||||
|                   </h3> | ||||
|                   <form class="form form_close" action="#" method="post" data-send="indexPage"> | ||||
|                     <div class="form-group form-group_row"> | ||||
|                       <input class="form-input" id="page" name="page" type="text"/> | ||||
|                       <button class="btn btn_primary form-btn" type="submit">Add/update | ||||
|                       </button> | ||||
|                     </div> | ||||
|                   </form> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="Tabs-block" id="search"> | ||||
|               <div class="Section"> | ||||
|                 <div class="Section-header"> | ||||
|                   <h2 class="Section-title">Search | ||||
|                   </h2> | ||||
|                 </div> | ||||
|                 <form class="form form_close" action="#" method="post" data-send="search" data-sendlimit="10"> | ||||
|                   <div class="form-group"> | ||||
|                     <div class="form-selectWrap"> | ||||
|                       <!-- - var options = setOptions(items, ['value', 'selected', 'disabled']);--> | ||||
|                       <select class="form-select" name="site"> | ||||
|                         <option value="" selected="selected">All sites | ||||
|                         </option> | ||||
|                       </select> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   <div class="form-group form-group_row"> | ||||
|                     <input class="form-input" id="query" name="query" type="text" placeholder="Query"/> | ||||
|                     <button class="btn btn_primary form-btn" type="submit">Search | ||||
|                     </button> | ||||
|                   </div> | ||||
|                 </form> | ||||
|                 <div class="SearchResult"> | ||||
|                   <strong class="SearchResult-title">Found <span class="SearchResult-amount">0</span> results | ||||
|                   </strong> | ||||
|                   <div class="SearchResult-content"> | ||||
|                   </div> | ||||
|                   <div class="SearchResult-footer SearchResult-footer_hide"> | ||||
|                     <button class="btn btn_primary" data-send="search" data-sendtype="next">Show more<span class="SearchResult-remain">(0)</span> | ||||
|                     </button> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </main> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
|   <script src="/assets/plg/jQuery/jquery-3.5.1.min.js"></script> | ||||
| </body></html> | ||||
 Eduard Kuksa
					Eduard Kuksa