diff --git a/class.png b/class.png index 07bbe4a..720e895 100644 --- a/class.png +++ b/class.png Binary files differ diff --git a/class.pu b/class.pu index a82b155..2ea8599 100644 --- a/class.pu +++ b/class.pu @@ -28,7 +28,22 @@ point :VARCHAR 255 city : City@ManyToOne } - city --|{ citymesh + + city |o--|{ citymesh + + entity task { + +currentId : VARCHAR 255 + preId : VARCHAR 255 + citycode : VARCHAR 255 + meshcode : VARCHAR 255 + status : Status + username : VARCHAR 255 + validator : VARCHAR 255 + operation : Operation + updateTime : Date + mesh : @ManyToOne + } + citymesh ||--o{ task } note bottom of db : spring.datasource.url=jdbc:h2:./taskdb\nspring.jpa.hibernate.ddl-auto=update @@ -137,7 +152,6 @@ CitymeshRepository <|-- Citymesh class Citymesh <> { - + id : Long - citycode : String@NumberFormat - meshcode : String@NumberFormat version : String @@ -168,6 +182,18 @@ operation : Operation updateTime : Date } +class TaskPK { + currentId : String + + equals(Object) : boolean + + hashCode() : int +} + +Task .. task +Task . TaskPK + +interface TaskRepository <> { +} + interface CommandLineRunner diff --git a/controller.png b/controller.png index 419d522..5ca6380 100644 --- a/controller.png +++ b/controller.png Binary files differ diff --git a/controller.pu b/controller.pu index b5851bf..fb655e7 100644 --- a/controller.pu +++ b/controller.pu @@ -64,6 +64,22 @@ state mesh_list } +state tasks { + state task_履歴 +} + +state task { + task : citycode + task : meshcode + task : operation + task : username + task : updateTime +} + +meshes --> tasks : /tasks +tasks --> task : /task +tasks <-- task : /tasks + state form { state city { city : citycode diff --git a/src/main/java/osm/surveyor/task/city/CitymeshRepository.java b/src/main/java/osm/surveyor/task/city/CitymeshRepository.java index 1faa3b9..693fbef 100644 --- a/src/main/java/osm/surveyor/task/city/CitymeshRepository.java +++ b/src/main/java/osm/surveyor/task/city/CitymeshRepository.java @@ -5,8 +5,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import osm.surveyor.task.city.model.Citymesh; +import osm.surveyor.task.city.model.CitymeshPK; -public interface CitymeshRepository extends JpaRepository { +public interface CitymeshRepository extends JpaRepository { List findByCitycode(String citycode); } diff --git a/src/main/java/osm/surveyor/task/city/DataLoader.java b/src/main/java/osm/surveyor/task/city/DataLoader.java index 8be2540..f9691c0 100644 --- a/src/main/java/osm/surveyor/task/city/DataLoader.java +++ b/src/main/java/osm/surveyor/task/city/DataLoader.java @@ -16,6 +16,7 @@ import osm.surveyor.task.city.model.City; import osm.surveyor.task.city.model.CityJson; import osm.surveyor.task.city.model.Citymesh; +import osm.surveyor.task.city.model.Status; import osm.surveyor.task.util.Geojson; import osm.surveyor.task.util.JsonFeature; import osm.surveyor.task.util.JsonGeometryPoint; @@ -41,6 +42,10 @@ city.setCitycode(citiesJson.getCode()); city.setCityname(citiesJson.getName()); city.setFolder(citiesJson.getPath()); + Status status = citiesJson.getStatus(); + if (status != null) { + city.setStatus(status); + } Point coordinates = citiesJson.toCoordinates(); city.setLng(coordinates.getLng()); @@ -77,6 +82,10 @@ mesh.setPath(prop.getPath()); mesh.setPoint(geometryPoint.getCoordinates().toString()); mesh.setCity(city); + Status status = city.getStatus(); + if (status != null) { + mesh.setStatus(status); + } meshRepository.save(mesh); } } diff --git a/src/main/java/osm/surveyor/task/city/TaskController.java b/src/main/java/osm/surveyor/task/city/TaskController.java index 2e9264b..eb04458 100644 --- a/src/main/java/osm/surveyor/task/city/TaskController.java +++ b/src/main/java/osm/surveyor/task/city/TaskController.java @@ -1,5 +1,11 @@ package osm.surveyor.task.city; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -10,12 +16,18 @@ import org.springframework.web.bind.annotation.RequestParam; import lombok.RequiredArgsConstructor; +import osm.surveyor.task.city.model.City; +import osm.surveyor.task.city.model.Citymesh; import osm.surveyor.task.city.model.CitymeshPK; +import osm.surveyor.task.city.model.Operation; +import osm.surveyor.task.city.model.Status; import osm.surveyor.task.city.model.Task; @RequiredArgsConstructor @Controller public class TaskController { + private final CityRepository cityRepository; + private final CitymeshRepository meshRepository; private final TaskRepository taskRepository; /** @@ -24,34 +36,104 @@ * @return */ @GetMapping("/tasks") - public String showList(Model model) { - model.addAttribute("tasks", taskRepository.findAll()); - return "tasks"; - } - - @GetMapping("/task") - public String showTask(@RequestParam(name="citycode") String citycode, - @RequestParam(name="meshcode") String meshcode, Model model) { + public String showList(@AuthenticationPrincipal UserDetails user, Model model, + @RequestParam(name="citycode") String citycode, + @RequestParam(name="meshcode") String meshcode) + { + // ログイン名を取得 + String loginName = ""; + if (user != null) { + loginName = user.getUsername(); + } + model.addAttribute("username", loginName); + + City city = cityRepository.getById(citycode); + model.addAttribute("citycode", citycode); + model.addAttribute("cityname", city.getCityname()); + model.addAttribute("meshcode", meshcode); + CitymeshPK pk = new CitymeshPK(); pk.setCitycode(citycode); pk.setMeshcode(meshcode); - model.addAttribute("tasks", taskRepository.findById(pk)); + Citymesh mesh = meshRepository.getById(pk); + model.addAttribute("mesh", mesh); + + List tasks = taskRepository.serchByMesh(citycode, meshcode); + model.addAttribute("tasks", tasks); return "tasks"; } + /** + * 「予約登録」 + * @param user + * @param model + * @param citycode + * @param meshcode + * @return + */ + @GetMapping("/task/reserve") + public String showTask(@AuthenticationPrincipal UserDetails user, Model model, + @RequestParam(name="citycode") String citycode, + @RequestParam(name="meshcode") String meshcode) + { + // ログイン名を取得 + String loginName = ""; + if (user != null) { + loginName = user.getUsername(); + } + model.addAttribute("username", loginName); + + City city = cityRepository.getById(citycode); + model.addAttribute("citycode", citycode); + model.addAttribute("cityname", city.getCityname()); + model.addAttribute("meshcode", meshcode); + + CitymeshPK pk = new CitymeshPK(); + pk.setCitycode(citycode); + pk.setMeshcode(meshcode); + Citymesh mesh = meshRepository.getById(pk); + + List tasks = taskRepository.serchByMesh(citycode, meshcode); + for (Task t : tasks) { + model.addAttribute("task", t); + return "task"; + } + + // Taskが無い場合は生成する + String uuid = UUID.randomUUID().toString(); + Task task = new Task(); + task.setCurrentId(uuid); + task.setPreId(uuid); + task.setCitycode(citycode); + task.setMeshcode(meshcode); + task.setMesh(mesh); + task.setStatus(Status.PREPARATION); + task.setUsername(loginName); + task.setOperation(Operation.RESERVE); + model.addAttribute("task", task); + return "task"; + } + @GetMapping("/task/add") - public String addTask(@RequestParam(name="citycode") String citycode, - @RequestParam(name="meshcode") String meshcode, @ModelAttribute Task task) { + public String addTask( + @RequestParam(name="citycode") String citycode, + @RequestParam(name="meshcode") String meshcode, + @ModelAttribute Task task) + { return "task"; } @PostMapping("/task/process") - public String process(@Validated @ModelAttribute Task task, BindingResult result) { + public String process(@AuthenticationPrincipal UserDetails user, + @Validated @ModelAttribute Task task, + BindingResult result) + { if (result.hasErrors()) { return "task"; } - + task.setUpdateTime(new Date()); taskRepository.save(task); - return "redirect:/tasks"; + + return "redirect:/tasks?citycode="+ task.getCitycode() +"&meshcode="+ task.getMeshcode(); } } diff --git a/src/main/java/osm/surveyor/task/city/TaskRepository.java b/src/main/java/osm/surveyor/task/city/TaskRepository.java index 9564a8e..4ef1a9e 100644 --- a/src/main/java/osm/surveyor/task/city/TaskRepository.java +++ b/src/main/java/osm/surveyor/task/city/TaskRepository.java @@ -1,10 +1,16 @@ package osm.surveyor.task.city; -import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; -import osm.surveyor.task.city.model.CitymeshPK; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + import osm.surveyor.task.city.model.Task; -public interface TaskRepository extends JpaRepository { +public interface TaskRepository extends JpaRepository { + + @Query("SELECT t FROM Task t WHERE t.citycode = :citycode AND t.meshcode = :meshcode order by update_time") + List serchByMesh(@Param("citycode")String citycode,@Param("meshcode")String meshcode); } diff --git a/src/main/java/osm/surveyor/task/city/model/City.java b/src/main/java/osm/surveyor/task/city/model/City.java index 273d9f1..b91acb4 100644 --- a/src/main/java/osm/surveyor/task/city/model/City.java +++ b/src/main/java/osm/surveyor/task/city/model/City.java @@ -3,8 +3,9 @@ import java.math.BigDecimal; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.Id; -import javax.persistence.IdClass; import javax.persistence.Table; import javax.validation.constraints.NotBlank; @@ -18,7 +19,6 @@ @Setter @Entity @Table(name = "city") -@IdClass(CityPK.class) public class City { private static String site; // 全体に適用する @@ -42,6 +42,12 @@ private String lat = "0.0"; /** + * ステータス + */ + @Enumerated(EnumType.STRING) + private Status status = Status.PREPARATION; + + /** * リレーション: to Citymesh 1..* */ //@OneToMany diff --git a/src/main/java/osm/surveyor/task/city/model/CityJson.java b/src/main/java/osm/surveyor/task/city/model/CityJson.java index 4666876..0c5401d 100644 --- a/src/main/java/osm/surveyor/task/city/model/CityJson.java +++ b/src/main/java/osm/surveyor/task/city/model/CityJson.java @@ -17,6 +17,8 @@ private String path; + private Status status; + private List coordinates = new ArrayList<>(); public Point toCoordinates() { @@ -36,6 +38,7 @@ sb.append("\"code\":\""+ getCode() +"\""); sb.append(",\"name\":\""+ getName() +"\""); sb.append(",\"path\":\""+ getPath() +"\""); + sb.append(",\"status\":\""+ getStatus() +"\""); sb.append(",\"coordinates\":"+ getCoordinates().toString()); sb.append("}"); return sb.toString(); diff --git a/src/main/java/osm/surveyor/task/city/model/Task.java b/src/main/java/osm/surveyor/task/city/model/Task.java index 324f4b0..b89dd2b 100644 --- a/src/main/java/osm/surveyor/task/city/model/Task.java +++ b/src/main/java/osm/surveyor/task/city/model/Task.java @@ -7,7 +7,6 @@ import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; -import javax.persistence.IdClass; import javax.persistence.ManyToOne; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -21,7 +20,6 @@ @Getter @Setter @Entity -@IdClass(CitymeshPK.class) public class Task { @Id @@ -46,7 +44,7 @@ /** * ステータス */ - @Enumerated(EnumType.ORDINAL) + @Enumerated(EnumType.STRING) private Status status = Status.PREPARATION; /** diff --git a/src/main/java/osm/surveyor/task/city/model/TaskPK.java b/src/main/java/osm/surveyor/task/city/model/TaskPK.java index 1e12339..b9076ac 100644 --- a/src/main/java/osm/surveyor/task/city/model/TaskPK.java +++ b/src/main/java/osm/surveyor/task/city/model/TaskPK.java @@ -12,28 +12,22 @@ @Setter @Embeddable public class TaskPK implements Serializable { - private String username; - private String citycode; - private String meshcode; + private String currentId; public TaskPK() { } public boolean equals(Object obj) { if (obj instanceof TaskPK) { - if (((TaskPK)obj).getUsername().equals(this.username)) { - if (((TaskPK)obj).getCitycode().equals(this.citycode)) { - if (((TaskPK)obj).getMeshcode().equals(this.meshcode)) { - return true; - } - } + if (((TaskPK)obj).getCurrentId().equals(this.currentId)) { + return true; } } return false; } public int hashCode() { - String s = this.username + this.citycode + this.meshcode; + String s = this.currentId; return s.hashCode(); } } diff --git a/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java b/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java index fe2810a..52b1c19 100644 --- a/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java +++ b/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java @@ -32,10 +32,8 @@ // 通常、cssやjs、imgなどの静的リソースを指定します web.ignoring().antMatchers( "/favicon.ico", + "/custom/**", "/pref/**", - "/city/**", - "/task/**", - "/tasks/**", "/js/**", "/css/**", "/img/**", @@ -57,7 +55,7 @@ // ログイン時のURLを指定 .loginPage("/login") // 認証後にリダイレクトする場所を指定 - .defaultSuccessUrl("/") + .defaultSuccessUrl("/city") .and() // ログアウトの設定 .logout() diff --git a/src/main/resources/static/city/index.json b/src/main/resources/static/city/index.json index 20b5b13..fa4c9ab 100644 --- a/src/main/resources/static/city/index.json +++ b/src/main/resources/static/city/index.json @@ -27,7 +27,7 @@ {"code": "17206", "name": "石川県 加賀市", "path": "17206_kaga-shi_2021", "coordinates":[136.31501,36.30282]}, {"code": "20202", "name": "長野県 松本市", "path": "20202_matsumoto-shi_2020", "coordinates":[137.96847,36.23800]}, {"code": "20204", "name": "長野県 岡谷市", "path": "20204_okaya-shi_2020", "coordinates":[138.04970,36.07857]}, - {"code": "20209", "name": "長野県 伊那市", "path": "20209_ina-shi_2020", "coordinates":[137.95746,35.82935]}, + {"code": "20209", "name": "長野県 伊那市", "path": "20209_ina-shi_2020", "status": "ACCEPTING", "coordinates":[137.95746,35.82935]}, {"code": "20214", "name": "長野県 茅野市", "path": "20214_chino-shi_2020", "coordinates":[138.15793,35.98550]}, {"code": "21201", "name": "岐阜県 岐阜市", "path": "21201_gifu-shi_2020", "coordinates":[136.76315,35.42288]}, {"code": "22213", "name": "静岡県 掛川市", "path": "22213_kakegawa-shi_2020", "coordinates":[138.01897,34.79317]}, diff --git a/src/main/resources/static/css/surveyor.css b/src/main/resources/static/css/surveyor.css index 010c24e..563d033 100644 --- a/src/main/resources/static/css/surveyor.css +++ b/src/main/resources/static/css/surveyor.css @@ -19,47 +19,3 @@ width: 50%; height: 50%; } - -p.middle { - vertical-align: middle; -} - -h1 { - font-style: italic; -} - -.carto { - padding-left: 40px; -} - -table { - margin: 20px 0 50px; - border-top: 1px solid #663300; - border-left: 1px solid #663300; - border-collapse: collapse; - border-spacing: 0; - background-color: #ffffff; - empty-cells: show; -} - -table caption { - caption-side: top; - text-decoration: underline; -} - -table tr th, table tr td { - font-size: 12px; - border-right: 1px solid #CCC; - border-bottom: 1px solid #CCC; - padding: 7px; -} - -table tr th { - background: #E6EAFF; - font-size: 11px; -} - -table tr th.name, - -table tr th.denominator, -table tr td.denominator{text-align: right} diff --git a/src/main/resources/static/custom/task.js b/src/main/resources/static/custom/task.js new file mode 100644 index 0000000..1472990 --- /dev/null +++ b/src/main/resources/static/custom/task.js @@ -0,0 +1,22 @@ +var dir = "./"; +var cityname = ""; +var line = []; + +var queryString = window.location.search; +var queryObject = new Object(); +if(queryString){ + queryString = queryString.substring(1); + var parameters = queryString.split('&'); + + for (var i = 0; i < parameters.length; i++) { + var element = parameters[i].split('='); + + var paramName = decodeURIComponent(element[0]); + var paramValue = decodeURIComponent(element[1]); + + queryObject[paramName] = paramValue; + } +} + +const citycode = queryObject['citycode']; +const meshcode = queryObject['meshcode']; diff --git a/src/main/resources/static/custom/tasks.js b/src/main/resources/static/custom/tasks.js new file mode 100644 index 0000000..95ad478 --- /dev/null +++ b/src/main/resources/static/custom/tasks.js @@ -0,0 +1,173 @@ +const geojson = "index.geojson"; + +var __map = null; +var __markerLayer = null; +var __lineLayer = null; + +var dir = "./"; +var cityname = ""; +var line = []; + +var queryString = window.location.search; +var queryObject = new Object(); +if(queryString){ + queryString = queryString.substring(1); + var parameters = queryString.split('&'); + + for (var i = 0; i < parameters.length; i++) { + var element = parameters[i].split('='); + + var paramName = decodeURIComponent(element[0]); + var paramValue = decodeURIComponent(element[1]); + + queryObject[paramName] = paramValue; + } +} + +const mesh = /*[[${mesh}]]*/"mesh"; +const citycode = queryObject['citycode']; +const meshcode = queryObject['meshcode']; + +function loadMap() { + + // 'citycode'に対応するデータを読む + var lonlat = [139.7637,35.6808]; + $.when( + $.getJSON("/city/index.json") + ).done(function(data1) { + site = data1.site; + $(data1.list).each(function() { + if (this.code == citycode) { + dir = this.path + "/bldg/"; + cityname = this.name; + loadMesh(dir, citycode, meshcode); + } + }) + }); + + + // マップの作成 + __map = new ol.Map({ + target: 'map', + layers: [ + new ol.layer.Tile({ + source: new ol.source.OSM() + }) + ], + view: new ol.View({ + center: ol.proj.fromLonLat(lonlat), + zoom: 15 + }) + }); + + // 表示するためのレイヤーを作成する + __markerLayer = new ol.layer.Vector({ + source: new ol.source.Vector() + }); + __map.addLayer(__markerLayer); + + // ポップアップを表示するためのオーバーレイを作成する + __overlay = new ol.Overlay({ + element: document.getElementById('popup'), + positioning: 'bottom-center' + }); + + + // 地図のクリックイベントを設定 + __map.on('click', function (evt) { + var feature = __map.forEachFeatureAtPixel( + evt.pixel, + function (feature) { + return feature; + } + ); + if (feature) { + var coordinates = feature.getGeometry().getCoordinates(); + var info = feature.information; + var element = __overlay.getElement(); + var descriptionHTML = + "
code: " + info.properties.id + "
" + + "
version: " + info.properties.version + "
" + + ""; + element.innerHTML = descriptionHTML; + __overlay.setPosition(coordinates); + __map.addOverlay(__overlay); + } else { + __map.removeOverlay(__overlay); + } + }); + + +} + + +// マップ表示のための中心位置を読み取る +function loadMesh(dir) { + $.when( + $.getJSON("/city/"+ dir + geojson) + ).done(function(data2) { + features = data2.features; + $(features).each(function() { + if (this.properties != null) { + if (this.properties.id == meshcode) { + if (this.geometry != null) { + if (this.geometry.type == "Point") { + lonlat = this.geometry.coordinates; // 中心位置 + + // マーカーの表示 + featurePoint = new ol.Feature({ + geometry: new ol.geom.Point(ol.proj.fromLonLat(lonlat)) + }); + featurePoint.information = this; + featurePoint.setStyle(new ol.style.Style({ + image: new ol.style.Icon({ + src: '/img/osm_200x200.png', + anchor: [0.5, 0.5], + scale: 0.2 + }), + stroke: new ol.style.Stroke({color: '#ff33ff', width: 10}) + })); + __markerLayer.getSource().addFeature(featurePoint); + __map.getView().setCenter(ol.proj.fromLonLat(lonlat)); + } + if (this.geometry.type == "LineString") { + drawPolygon([this.geometry.coordinates]); + } + } + } + } + }); + }); +} + + +/** + * ポリゴンを描画する + ret: routeLayer + */ +function drawPolygon(coordinates) { + // ジオメトリの作成 + var polygon = new ol.geom.Polygon([]); + polygon.setCoordinates(coordinates); + + // 地物オブジェクトの作成 〜 レイヤーの作成 + var feature = new ol.Feature( + polygon.transform('EPSG:4326', 'EPSG:3857') + ); + feature.setId(meshcode); + + var vector = new ol.source.Vector({ + features: [feature] + }); + routeLayer = new ol.layer.Vector({ + source: vector, + style: new ol.style.Style({ + stroke: new ol.style.Stroke({ color: '#000000', width: 2 }) + //fill: new ol.style.Fill({ color: [0, 0, 0, 0.2] }) + }) + }); + + // 作成したポリゴンをレイヤーにのせる + __map.addLayer(routeLayer); +} + diff --git a/src/main/resources/static/img/photo.jpg b/src/main/resources/static/img/photo.jpg new file mode 100644 index 0000000..3dc82c0 --- /dev/null +++ b/src/main/resources/static/img/photo.jpg Binary files differ diff --git a/src/main/resources/static/js/usertables.js b/src/main/resources/static/js/usertables.js index d42f0fc..307b998 100644 --- a/src/main/resources/static/js/usertables.js +++ b/src/main/resources/static/js/usertables.js @@ -2,7 +2,7 @@ $("#user-table").dataTable({ // DataTablesを日本語化する language: { - url: "/webjars/datatables-plugins/i18n/Japanese.json" + url: "/webjars/datatables-plugins/i18n/ja.json" }, // 各種ボタンを有効化する dom: "Bfrtip", diff --git a/src/main/resources/templates/cities.html b/src/main/resources/templates/cities.html index 7373f42..43c5eba 100644 --- a/src/main/resources/templates/cities.html +++ b/src/main/resources/templates/cities.html @@ -61,7 +61,7 @@ - 準備中 + diff --git a/src/main/resources/templates/fragments/sidebar.html b/src/main/resources/templates/fragments/sidebar.html index cc46eef..1681625 100644 --- a/src/main/resources/templates/fragments/sidebar.html +++ b/src/main/resources/templates/fragments/sidebar.html @@ -30,13 +30,13 @@