diff --git a/build.gradle b/build.gradle index 45fcb47b7dee31bbaa3bdf84773eb6d13e86c62a..cb5f573cc10ea35ff24ce651c551df82c32873e7 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.1.5' id 'io.spring.dependency-management' version '1.1.3' + id "com.github.node-gradle.node" version "7.0.1" } group = 'Team.5' @@ -26,7 +27,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.mariadb.jdbc:mariadb-java-client:2.1.2' - testImplementation 'junit:junit:4.13.1' + implementation 'org.springframework.boot:spring-boot-starter-security' + testImplementation 'junit:junit:4.13.1' compileOnly 'org.projectlombok:lombok' testImplementation 'org.projectlombok:lombok:1.18.28' compileOnly 'org.projectlombok:lombok' @@ -34,26 +36,23 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-validation' - // https://mvnrepository.com/artifact/org.springframework/spring-dao -// implementation group: 'org.springframework', name: 'spring-tx', version: '6.1.1' -// implementation 'org.springframework:spring-dao:2.0.8' -// implementation 'org.springframework.dao.DataAccessException' - // https://mvnrepository.com/artifact/org.springframework/spring-core -// implementation 'org.springframework:spring-core:6.0.6' -// implementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.0.1' -// implementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.0.1' - -//Thanks for using https://jar-download.com - -// https://mvnrepository.com/artifact/com.h2database/h2 // if breaks - - + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE' + // https://mvnrepository.com/artifact/org.webjars/openlayers + implementation group: 'org.webjars', name: 'openlayers', version: '5.2.0' } tasks.named('bootBuildImage') { builder = 'paketobuildpacks/builder-jammy-base:latest' } +test { + useJUnitPlatform() +} tasks.named('test') { useJUnitPlatform() } + +task myScript(type: NodeTask) { + script = file('src/main/resources/static/scripts/mapAPI.js') +} diff --git a/src/main/java/Team5/SmartTowns/data/Location.java b/src/main/java/Team5/SmartTowns/data/Location.java index 0f1e73ad5aa68a592d5131c448be2602cf58d800..882489ffb4ac7c160fd45162a0f48d8e5c53bf1c 100644 --- a/src/main/java/Team5/SmartTowns/data/Location.java +++ b/src/main/java/Team5/SmartTowns/data/Location.java @@ -14,7 +14,7 @@ public class Location { private String locationEmail; private String locationDescription; private String locationPlace; - private int locationTrailID; + private String locationTrailID; private boolean locationApproved; @@ -51,7 +51,7 @@ public class Location { return locationPlace; } - public int getLocationTrailID() { + public String getLocationTrailID() { return locationTrailID; } @@ -72,4 +72,29 @@ public class Location { this.locationTrailID = locationTrailID; this.locationApproved = locationApproved; } + + + public void setLocationName(String locationName) { + this.locationName = locationName; + } + + public void setLocationEmail(String locationEmail) { + this.locationEmail = locationEmail; + } + + public void setLocationDescription(String locationDescription) { + this.locationDescription = locationDescription; + } + + public void setLocationPlace(String locationPlace) { + this.locationPlace = locationPlace; + } + + public void setLocationTrailID(String locationTrailID) { + this.locationTrailID = locationTrailID; + } + + public void setLocationApproved(boolean locationApproved) { + this.locationApproved = locationApproved; + } } diff --git a/src/main/java/Team5/SmartTowns/data/LocationRepository.java b/src/main/java/Team5/SmartTowns/data/LocationRepository.java index 5e7e8b8578ab840eda371f59fb2655e90d34c6fc..cbc980a816f339bae030bd1848d26c34d2376670 100644 --- a/src/main/java/Team5/SmartTowns/data/LocationRepository.java +++ b/src/main/java/Team5/SmartTowns/data/LocationRepository.java @@ -1,10 +1,6 @@ //Holds locations data repository (landmarks) - package Team5.SmartTowns.data; - -import Team5.SmartTowns.data.Location; - import java.util.List; @@ -13,16 +9,14 @@ public interface LocationRepository { void addLocation(Location loc); - - List<Location> getApprovedLocations(); + List<Location> getAllApprovedLocations(); // List<Location> getApprovedLocations2(List<Location> list); - List<Location> getUnapprovedLocations(); + List<Location> getAllUnapprovedLocations(); // List<Location> approvedLocations(); - } diff --git a/src/main/java/Team5/SmartTowns/data/LocationRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/data/LocationRepositoryJDBC.java index 186151ea6c33d96b542bc33267476110e3942fad..457366e8caa54f63f2b18011231a99c600753caa 100644 --- a/src/main/java/Team5/SmartTowns/data/LocationRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/data/LocationRepositoryJDBC.java @@ -1,26 +1,16 @@ //Implements the locations repository using JDBC - package Team5.SmartTowns.data; - -import Team5.SmartTowns.data.LocationRepository; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; - -import javax.sql.DataSource; - import java.util.ArrayList; - import java.util.List; @Repository public class LocationRepositoryJDBC implements LocationRepository { - - private JdbcTemplate jdbc; - private RowMapper<Location> locationMapper; public LocationRepositoryJDBC(JdbcTemplate aJdbc) { @@ -28,7 +18,6 @@ public class LocationRepositoryJDBC implements LocationRepository { setlocationMapper(); } - // public LocationRepositoryJDBC() { // JdbcTemplate ajdbc = new JdbcTemplate(); // this.jdbc =ajdbc; @@ -44,34 +33,14 @@ public class LocationRepositoryJDBC implements LocationRepository { rs.getString("locationEmail"), rs.getString("locationDescription"), rs.getString("locationPlace"), - rs.getInt("locationTrailID"), - rs.getBoolean() - ); - } - public String getCountOfEmployees() { - return jdbc.queryForObject("SELECT COUNT(*) FROM locations",String.class); - } - - public List<Location> getAllLocation2(JdbcTemplate aJdbc){ - String sql= "SELECT * FROM locations"; - return aJdbc.query(sql, locationMapper); - } - - rs.getInt("locationTrailID"), + rs.getString("locationTrailID"), rs.getBoolean("locationApproved") ); } - public List<Location> getAllLocation(){ String sql= "SELECT * FROM locations"; return jdbc.query(sql, locationMapper); } - - -// @Override // intended implementation at current: user data from templates/Landmarks/LandmarkFormTh.html is added to the Location table -// public void addLocation(Location loc) { -// String sql = "insert into locations( locationName , locationEmail,locationDescription,locationPlace, locationTrailID) values (?,?,?,?,?)";} - // public LocationRepositoryJDBC() { // JdbcTemplate ajdbc = new JdbcTemplate(); // this.jdbc =ajdbc; @@ -83,35 +52,50 @@ public class LocationRepositoryJDBC implements LocationRepository { // this.locationMapper = locationMapper; // } - @Override // intended implementation at current: user data from templates/Landmarks/LandmarkFormTh.html is added to the Location table - public void addLocation(Location loc) { - String sql = "insert into locations( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) values (?,?,?,?,?,?)"; - jdbc.update(sql,loc.getLocationName(),loc.getLocationEmail(),loc.getLocationDescription(),loc.getLocationPlace(),loc.getLocationTrailID()); + @Override + public List<Location> getAllApprovedLocations(){ + String sql= "SELECT * FROM locations"; + List<Location> lis = jdbc.query(sql, locationMapper); + List<Location> lisFiltered = new ArrayList<>(); + for (Location li : lis){ + if (li.isLocationApproved()){ + lisFiltered.add(li); + } + } + return lisFiltered; } - - public void setDataSource(DataSource dataSource) { - jdbc = new JdbcTemplate(dataSource); + @Override + public List<Location> getAllUnapprovedLocations(){ + String sql= "SELECT * FROM locations"; + List<Location> lis = jdbc.query(sql, locationMapper); + List<Location> lisFiltered = new ArrayList<>(); + for (Location li : lis){ + if (!li.isLocationApproved()){ + lisFiltered.add(li); + } + } + return lisFiltered; } - public LocationRepositoryJDBC() { - } + @Override // intended implementation at current: user data from templates/Landmarks/LandmarkFormTh.html is added to the Location table + public void addLocation(Location loc) { + String sql = "insert into locations( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) values (?,?,?,?,?,?)"; - public void setJdbc(JdbcTemplate jdbc) { - this.jdbc = jdbc; + jdbc.update(sql,loc.getLocationName(),loc.getLocationEmail(),loc.getLocationDescription(),loc.getLocationPlace(),loc.getLocationTrailID(), false); } - @Override - public List<Location> getApprovedLocations(){ - JdbcTemplate jdbc = new JdbcTemplate(); - List<Location> locations = new LocationRepositoryJDBC(jdbc).getAllLocation(); - List<Location> locationApprovalList= new ArrayList<Location>(); - for (Location loc :locations){ - if (loc.isLocationApproved()) { - locationApprovalList.add(loc); - } - } return locationApprovalList; - } +// @Override +// public List<Location> getApprovedLocations(){ +// JdbcTemplate jdbc = new JdbcTemplate(); +// List<Location> locations = new LocationRepositoryJDBC(jdbc).getAllLocation(); +// List<Location> locationApprovalList= new ArrayList<Location>(); +// for (Location loc :locations){ +// if (loc.isLocationApproved()) { +// locationApprovalList.add(loc); +// } +// } return locationApprovalList; +// } // // @Override // public List<Location> getApprovedLocations2(List<Location> list){ @@ -126,16 +110,16 @@ public class LocationRepositoryJDBC implements LocationRepository { // - @Override - public List<Location> getUnapprovedLocations(){ - List<Location> locations = getAllLocation(); - List<Location> locationUnapprovedList= new ArrayList<Location>(); - for (Location loc :locations){ - if (!loc.isLocationApproved()) { - locationUnapprovedList.add(loc); - } - } return locationUnapprovedList; - } +// @Override +// public List<Location> getUnapprovedLocations(){ +// List<Location> locations = getAllLocation(); +// List<Location> locationUnapprovedList= new ArrayList<Location>(); +// for (Location loc :locations){ +// if (!loc.isLocationApproved()) { +// locationUnapprovedList.add(loc); +// } +// } return locationUnapprovedList; +// } // public JdbcTemplate getJdbc() { @@ -143,5 +127,4 @@ public class LocationRepositoryJDBC implements LocationRepository { // } - } diff --git a/src/main/java/Team5/SmartTowns/data/Trail.java b/src/main/java/Team5/SmartTowns/data/Trail.java index 61ab540fce97c94b709c888e3c261db35c318849..f9056d64b47f0f5104216b6eb15f50f9301d843c 100644 --- a/src/main/java/Team5/SmartTowns/data/Trail.java +++ b/src/main/java/Team5/SmartTowns/data/Trail.java @@ -7,7 +7,22 @@ import lombok.Data; @Data @AllArgsConstructor public class Trail { - private int trailsId; - private String name; - private Boolean tru; + private String trailsId; + private String trailName; + private String trailNumber; + + + public String getTrailsId() { + return trailsId; + } + + public String getTrailName() { + return trailName; + } + + public String getTrailNumber() { + return trailNumber; + } + + } diff --git a/src/main/java/Team5/SmartTowns/data/TrailsRepository.java b/src/main/java/Team5/SmartTowns/data/TrailsRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..7e55ce7d32a732cf645dedabf478d77dbc1b26a9 --- /dev/null +++ b/src/main/java/Team5/SmartTowns/data/TrailsRepository.java @@ -0,0 +1,9 @@ +//Holds trails data repository +package Team5.SmartTowns.data; + +import java.util.List; + +public interface TrailsRepository { + List<Trail> getAllTrails(); + String getTrailNameWithID(String trailsID); +} diff --git a/src/main/java/Team5/SmartTowns/data/TrailsRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/data/TrailsRepositoryJDBC.java index 0bb20867153d77c2fd47f3e031bf63c7c1fdac7e..695ba5b9faff496b3ee941f6cae25b40ab2996ad 100644 --- a/src/main/java/Team5/SmartTowns/data/TrailsRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/data/TrailsRepositoryJDBC.java @@ -17,13 +17,23 @@ public class TrailsRepositoryJDBC implements TrailsRepository { } private void settrailsMapper(){ trailMapper = (rs, i) -> new Trail( - rs.getInt("trailID"), - rs.getString("name"), - rs.getBoolean("tru") + rs.getString("trailID"), + rs.getString("trailName"), + rs.getString("trailNumber") ); } public List<Trail> getAllTrails(){ String sql= "SELECT * FROM trails"; return jdbc.query(sql, trailMapper); } + @Override + public String getTrailNameWithID(String trailsID){ + String resultName = jdbc.queryForObject( + "SELECT trailName FROM trails WHERE trailID=?", String.class, trailsID); + return resultName; + + + } + + } diff --git a/src/main/java/Team5/SmartTowns/landmarks/Landmarks.java b/src/main/java/Team5/SmartTowns/landmarks/Landmarks.java index 6974c1e997c5b2dd6d7396f44ea0cbe4565331c7..8f7471fcc84f95669e9a07aaa3e1f9782dc780d6 100644 --- a/src/main/java/Team5/SmartTowns/landmarks/Landmarks.java +++ b/src/main/java/Team5/SmartTowns/landmarks/Landmarks.java @@ -20,7 +20,7 @@ public class Landmarks { new Landmarks( 1, "A scent of...Dragon", "The Dragon has been spotted near by, find the QR code to continue" , "Start your discovery, at the sweet shop."), new Landmarks( 2, "They've been found!", "Don't let them escape, find the next QR code to continue!", "Location test") ); - private Integer trailID; + private String trailID; private int landmarkID; @NotEmpty(message = "You must type in a username.") private String landmarkName; diff --git a/src/main/java/Team5/SmartTowns/landmarks/LandmarksController.java b/src/main/java/Team5/SmartTowns/landmarks/LandmarksController.java index d5d326cdb733339ff3c3ab298090776af9036fc3..a5679aad7406be423fa165f553694ef1d02878a5 100644 --- a/src/main/java/Team5/SmartTowns/landmarks/LandmarksController.java +++ b/src/main/java/Team5/SmartTowns/landmarks/LandmarksController.java @@ -38,7 +38,6 @@ public class LandmarksController { } else{ // converts valid response using Location constructor into a submittable format to the sql table Location loc= new Location(landmarks.getLandmarkName(), landmarks.getLandmarkEmail(), landmarks.getLandmarkDescription(), landmarks.getLandmarkLocation(), landmarks.getTrailID(), false); - System.out.println(loc); locationRepository.addLocation(loc); // adds valid landmark to locations table ModelAndView modelAndView = new ModelAndView("redirect:/home"); return modelAndView; diff --git a/src/main/java/Team5/SmartTowns/placeswithcoordinates/LocationsCoordinates.java b/src/main/java/Team5/SmartTowns/placeswithcoordinates/LocationsCoordinates.java index 349adc85e3752bd0f523750e2b5bc8dff25f6e76..a242df3e8b84cee08f3fcdf044e550a49b111343 100644 --- a/src/main/java/Team5/SmartTowns/placeswithcoordinates/LocationsCoordinates.java +++ b/src/main/java/Team5/SmartTowns/placeswithcoordinates/LocationsCoordinates.java @@ -92,16 +92,16 @@ public class LocationsCoordinates { // JdbcTemplate jdbcSuper= new LocationRepositoryJDBC().getJdbc(); // return new LocationRepositoryJDBC(jdbcSuper).getApprovedLocations(); // } - - public List<Location> getFullUnapprovedLocations(JdbcTemplate aJdbc){ -// LocationsCoordinates jdbcSuper= new LocationsCoordinates(aJdbc); - return new LocationRepositoryJDBC(aJdbc).getUnapprovedLocations(); - } +// +// public List<Location> getFullUnapprovedLocations(JdbcTemplate aJdbc){ +//// LocationsCoordinates jdbcSuper= new LocationsCoordinates(aJdbc); +// return new LocationRepositoryJDBC(aJdbc).getUnapprovedLocations(); +// } - /// Need a constructor to create a lcoations list, approved lcoatiosn lsit, unapproved lcoations list. + /// Need a constructor to create a locations list, approved collation list, unapproved locations list. diff --git a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesController.java b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesController.java index 8d142f83569aa8816ea8d9d1b32c6b795ab96c00..6511067e9e636a29d96063357df1e3c7bc4f34e6 100644 --- a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesController.java +++ b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesController.java @@ -2,6 +2,9 @@ package Team5.SmartTowns.placeswithcoordinates; import Team5.SmartTowns.data.Location; import Team5.SmartTowns.data.LocationRepository; +import Team5.SmartTowns.data.Trail; +import Team5.SmartTowns.data.TrailsRepository; +import jakarta.validation.constraints.Max; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -22,55 +25,91 @@ public class PlacesController { @Autowired private LocationRepository locationRepo; - + @Autowired + private TrailsRepository trailsRepo; @GetMapping("/checkpoints") public ModelAndView getLocationPages(){ ModelAndView modelAndView = new ModelAndView("landmarks/locationPage.html"); - List<Location> locations = locationRepo.getAllLocation(); -// List<Location> approvedLocations = locationRepo.getApprovedLocations2(locations); List<LocationsCoordinates> locCoords = placeRepo.getAllLocationCoords(); - List<Integer> locationIDIndex = new ArrayList<Integer>(); - List<Location> locationCoordsWorkaround = new ArrayList<Location>(); - for (LocationsCoordinates coord: locCoords){ - locationIDIndex.add(coord.getLocationID()-1); - locationCoordsWorkaround.add(locations.get(coord.getLocationID()-1)); - } - modelAndView.addObject("location", locationCoordsWorkaround); + List<Location> approvedLocations = locationRepo.getAllApprovedLocations(); + + modelAndView.addObject("location", approvedLocations); modelAndView.addObject("locationCoords", locCoords); return modelAndView; } @RequestMapping(value="/location", method= RequestMethod.POST) - public String sendHtmlFragment(Model map) { + public String sendHtmlFragmentLocation(Model map) { map.addAttribute("foo", "bar"); return "checkpoint/checkpoint"; } + + + @GetMapping("/checkpoints/{location}") - public ModelAndView getResultBySearchKey(@PathVariable String location) { - List<Location> locations = locationRepo.getAllLocation(); + public ModelAndView getResultBySearchKeyLocation(@PathVariable String location) { List<LocationsCoordinates> locCoords = placeRepo.getAllLocationCoords(); + List<Location> approvedLocations = locationRepo.getAllApprovedLocations(); - List<Integer> locationIDIndex = new ArrayList<Integer>(); - List<Location> locationCoordsWorkaround = new ArrayList<Location>(); int locationID = 999; - int workAroundID=0;// otherwise cases errors e.g. null used. 999 unlikely to be used so safe until then - for (int i=0;i<locCoords.size();i++){ /// for loop iterating over coordinates table need to match coordinate index with lcoation index manually - locationIDIndex.add(locCoords.get(i).getLocationID()-1); // gets location ID and therefore location list index number - locationCoordsWorkaround.add(locations.get(locCoords.get(i).getLocationID()-1)); - if ( (locations.get(locCoords.get(i).getLocationID() - 1).getLocationName().replace(' ', '-').trim().equals(location)) ){ + for (int i=0;i<approvedLocations.size();i++){ + if ( (approvedLocations.get(i).getLocationName().replace(' ', '-').trim().equals(location)) ){ locationID= i; - break; - } workAroundID++; - }System.out.println(locationCoordsWorkaround); - System.out.println("ag"+locationID); + } + } + + String trailName=trailsRepo.getTrailNameWithID(approvedLocations.get(locationID).getLocationTrailID()).replace(' ', '-').trim(); ModelAndView modelAndView= new ModelAndView("fragments/locationPageFrags :: locationSection"); - System.out.println("ag"+locationID); modelAndView.addObject("locCoord", locCoords.get(locationID)); - System.out.println("sd"+workAroundID); - modelAndView.addObject("location", locationCoordsWorkaround.get(locationID)); + modelAndView.addObject("trail", trailName); + modelAndView.addObject("location", approvedLocations.get(locationID)); + return modelAndView; + } + + + + /// Trail webpage mapping + + + @GetMapping("/trails") + public ModelAndView getTrailsPage(){ + ModelAndView modelAndView = new ModelAndView("landmarks/trailsPage.html"); + List<LocationsCoordinates> locCoords = placeRepo.getAllLocationCoords(); + List<Location> approvedLocations = locationRepo.getAllApprovedLocations(); + List<Trail> trailslocations = trailsRepo.getAllTrails(); + List<Location> locationCoordsWorkaround = new ArrayList<Location>(); + + modelAndView.addObject("trails", trailslocations); + modelAndView.addObject("locations", approvedLocations); + modelAndView.addObject("locationCoords", locCoords); + return modelAndView; + } + + @RequestMapping(value="/trail", method= RequestMethod.POST) + public String sendHtmlFragmentTrail(Model map) { + map.addAttribute("foo", "bar"); + return "trail/trail"; + } + + @GetMapping("/trails/{trail}") + public ModelAndView getResultBySearchKeyTrails(@PathVariable String trail) { + List<LocationsCoordinates> locCoords = placeRepo.getAllLocationCoords(); + List<Location> approvedLocations = locationRepo.getAllApprovedLocations(); + List<Trail> trailslocations = trailsRepo.getAllTrails(); + int trailID = 999;// otherwise cases errors e.g. null used. 999 unlikely to be used so safe until then + for (int i=0;i<trailslocations.size();i++){ + + if (trailslocations.get(i).getTrailName().replace(' ', '-').trim().equals(trail)){ + trailID=i; + break;} + } + ModelAndView modelAndView= new ModelAndView("fragments/trailsPageFrags :: trailsSection"); + modelAndView.addObject("trail", trailslocations.get(trailID)); + modelAndView.addObject("locCoords", locCoords); + modelAndView.addObject("locations", approvedLocations); return modelAndView; } diff --git a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepository.java b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepository.java index a5e03d93ab75a20f3c380ca5c1b3d11c6f0b5807..deea368752b4b41bebd49147ce2266e64d942440 100644 --- a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepository.java +++ b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepository.java @@ -13,7 +13,7 @@ public interface PlacesCoordinatesRepository { List<TownWithTrails> getAllTownCoords(); void addTownWithCoords(TownWithTrails town); - List<Location> getFullApprovedLocations(JdbcTemplate aJdbc); +// List<Location> getFullApprovedLocations(JdbcTemplate aJdbc); diff --git a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepositoryJDBC.java index dfca28ecd791d6ec0dc2a3040bc62274c07ff8c3..b90ee0b152d8734e8034e7cc33cd31585ea85fc4 100644 --- a/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesRepositoryJDBC.java @@ -53,6 +53,9 @@ public class PlacesCoordinatesRepositoryJDBC implements PlacesCoordinatesReposit String sql= "SELECT * FROM locationCoordinates"; return jdbc.query(sql, locationCoordMapper); } + + + public List<TownWithTrails> getAllTownCoords(){ String sql= "SELECT * FROM townswithtrails"; return jdbc.query(sql, townCoordMapper); @@ -74,10 +77,10 @@ public class PlacesCoordinatesRepositoryJDBC implements PlacesCoordinatesReposit } - public List<Location> getFullApprovedLocations(JdbcTemplate aJdbc) { -// LocationsCoordinates jdbcSuper= new LocationsCoordinates(aJdbc); - return new LocationRepositoryJDBC(aJdbc).getApprovedLocations(); - } +// public List<Location> getFullApprovedLocations(JdbcTemplate aJdbc) { +//// LocationsCoordinates jdbcSuper= new LocationsCoordinates(aJdbc); +// return new LocationRepositoryJDBC(aJdbc).getApprovedLocations(); +// } // @Override //TODO CHECK // public List<Location> getFullApprovedLocations(JdbcTemplate aJdbc) { diff --git a/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java index 65eaa9843ec3af33e994ea34ed8d219ce712ffaf..74c97a5f29319ab6dbefc042bcbc10e364b4bd03 100644 --- a/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java @@ -10,7 +10,6 @@ import java.util.List; @Repository public class RewardsRepositoryJDBC implements RewardsRepository { private final JdbcTemplate jdbc; - private RowMapper<Badge> badgeMapper; private RowMapper<Sticker> stickerMapper; private RowMapper<Pack> packMapper; @@ -51,8 +50,8 @@ public class RewardsRepositoryJDBC implements RewardsRepository { @Override public List<Sticker> getAllStickersFromPack(int packID){ - String sql= "SELECT * FROM stickers WHERE packID="+packID; - return jdbc.query(sql, stickerMapper); + String sql= "SELECT * FROM stickers WHERE packID=?"; + return jdbc.query(sql, stickerMapper, packID); } @Override @@ -60,14 +59,14 @@ public class RewardsRepositoryJDBC implements RewardsRepository { /* FINDS ALL STICKERS UNLOCKED BY THE GIVEN USER */ String sql= "SELECT * FROM stickers LEFT JOIN stickerprogress " + "ON (stickers.id, stickers.packID) = (stickerprogress.stickerID, stickerprogress.packID) " + - "WHERE stickerprogress.userID="+userID; - return jdbc.query(sql, stickerMapper); + "WHERE stickerprogress.username = ? "; + return jdbc.query(sql, stickerMapper, userID); } @Override public Pack findPackByID(int id){ - String sql= "SELECT * FROM packs WHERE id="+id; - List<Pack> result = jdbc.query(sql, packMapper); + String sql= "SELECT * FROM packs WHERE id= ?"; + List<Pack> result = jdbc.query(sql, packMapper, id); return result.isEmpty() ? null : result.get(0); } } diff --git a/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java b/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..afce617e22c6e82aa040896794e144ba0558ae37 --- /dev/null +++ b/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java @@ -0,0 +1,51 @@ +package Team5.SmartTowns.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.JdbcUserDetailsManager; +import org.springframework.security.provisioning.UserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + +import javax.sql.DataSource; + + +@Configuration +@EnableWebSecurity +public class SecurityConfiguration { + /* Configures the longin features and tracks logged on users on the page */ + + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests((requests) -> requests + .requestMatchers("/user/**", "/userProfile").authenticated() + .anyRequest().permitAll() + ) + .formLogin((login) -> login + .loginPage("/login").permitAll() + .defaultSuccessUrl("/userProfile") + ) + .logout((logout) -> logout.permitAll()); + + return http.build(); + } + @Bean + public PasswordEncoder passwordEncoder(){ + /* Nothing here yet, this just saves passwords in plaintext. TODO password encryption */ + return NoOpPasswordEncoder.getInstance(); + } + + @Bean + public UserDetailsManager userDetailsManager(DataSource dataSource){ + JdbcUserDetailsManager manager = new JdbcUserDetailsManager(dataSource); + return manager; + } + + +} diff --git a/src/main/java/Team5/SmartTowns/users/NewUser.java b/src/main/java/Team5/SmartTowns/users/NewUser.java new file mode 100644 index 0000000000000000000000000000000000000000..aa47adac9931083fb0d199375e50032ce30ccd60 --- /dev/null +++ b/src/main/java/Team5/SmartTowns/users/NewUser.java @@ -0,0 +1,26 @@ +package Team5.SmartTowns.users; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class NewUser { + + + @NotEmpty(message = "You must type in a username.") + @NotNull + String name; + + @NotEmpty(message = "You must type in a password.") + @NotNull + String password; + + @NotEmpty(message = "You must type in an email.") + @NotNull + String email; +} diff --git a/src/main/java/Team5/SmartTowns/users/User.java b/src/main/java/Team5/SmartTowns/users/User.java index 4ef65c3b288f9433e37d60e8e984b869f3a8d53e..96949fb1b8543684407118138878b21db47826fe 100644 --- a/src/main/java/Team5/SmartTowns/users/User.java +++ b/src/main/java/Team5/SmartTowns/users/User.java @@ -27,8 +27,7 @@ public class User { this.dragonProgress = dragonProgress; imgPath = findImagePath(); } - public User(int id, String email, String name) { - this.id = id; + public User(String email, String name) { this.email = email; this.name = name; imgPath = findImagePath(); diff --git a/src/main/java/Team5/SmartTowns/users/UserController.java b/src/main/java/Team5/SmartTowns/users/UserController.java index 989d13b7161f783dc75bdcb9dbf379808b1584e4..e1acd4b66f1546db506ec5313c5680122e05587d 100644 --- a/src/main/java/Team5/SmartTowns/users/UserController.java +++ b/src/main/java/Team5/SmartTowns/users/UserController.java @@ -4,10 +4,15 @@ package Team5.SmartTowns.users; import Team5.SmartTowns.rewards.Pack; import Team5.SmartTowns.rewards.RewardsRepository; import Team5.SmartTowns.rewards.Sticker; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import java.util.List; @@ -17,45 +22,87 @@ public class UserController { @Autowired private UserRepository userRepository; + @Autowired private RewardsRepository rewardsRepository; + /* LOGIN MAPPING & FUNCTIONS */ @GetMapping("/login") public ModelAndView getLoginPage() { ModelAndView mav = new ModelAndView("users/login"); -// List<User> users = userRepository.getAllUsers(); -// mav.addObject("users", users); + mav.addObject("user", new NewUser( "", "", "")); + mav.addObject("error", ""); + mav.addObject("status", ""); + System.out.println(userRepository.findUserByName("Admin").getName()); return mav; } - @GetMapping("/userList") - public ModelAndView userList() { - ModelAndView mav = new ModelAndView("towns/userData"); - List<User> users = userRepository.getAllUsers(); - mav.addObject("users", users); +// @GetMapping("/logout") +// public ModelAndView getLogOutPage(){ +// ModelAndView mav = new ModelAndView("users/logout"); +// return mav; +// } + + @PostMapping("/login/register") + public ModelAndView registerUser(@Valid @ModelAttribute("user") NewUser user, BindingResult bindingResult, Model model) { + ModelAndView mav = new ModelAndView("users/login", model.asMap()); + // TODO VALIDATE EMAIL INPUT + mav.addObject("status", "active"); + if (bindingResult.hasErrors()) { + ModelAndView modelAndView = new ModelAndView("users/login"); + modelAndView.addObject("errors", bindingResult); + return modelAndView; + } + + if ( userRepository.doesUserExist(user.getEmail()) ) { + mav.addObject("errors", "Email already in use"); + return mav; + } + + try { + userRepository.addUser(user.name, user.email, user.password); + mav.addObject("error", ""); + //TODO return user creation success + return mav; + } catch (DataAccessException e) { + mav.addObject("error", "User exists"); + } return mav; } - @GetMapping("/user/{id}") - public ModelAndView getUserPage(@PathVariable int id) { + @GetMapping("/userProfile") + public ModelAndView userProfile(){ ModelAndView mav = new ModelAndView("users/userProfile"); List<Pack> allPacks = rewardsRepository.getAllPacks(); - mav.addObject("user", userRepository.getUserById(id)); mav.addObject("packs", allPacks); - mav.addAllObjects(getPackInfo(id, 1).getModelMap()); + User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + mav.addObject("user", userRepository.findUserByName("Admin")); + mav.addAllObjects(getPackInfo("Admin", 1).getModelMap()); + return mav; + } + + /* USER MAPPING & FUNCTIONS */ + @GetMapping("/user/{username}") + public ModelAndView getUserPage(@PathVariable String username) { + ModelAndView mav = new ModelAndView("users/userProfile"); + List<Pack> allPacks = rewardsRepository.getAllPacks(); + mav.addObject("user", userRepository.findUserByName("Admin")); + mav.addObject("packs", allPacks); + mav.addAllObjects(getPackInfo(username, 1).getModelMap()); return mav; } - @GetMapping("/packInfo/{userID}/{packID}") - public ModelAndView getPackInfo(@PathVariable int userID, @PathVariable int packID) { + @GetMapping("/packInfo/{username}/{packID}") + public ModelAndView getPackInfo(@PathVariable String username, @PathVariable int packID) { /* Displays on page the stickers present in the pack and colour the ones the * user has acquired */ ModelAndView mav = new ModelAndView("users/userFrags :: stickersBox"); List<Sticker> allStickers = rewardsRepository.getAllStickersFromPack(packID); - List<Long> userStickers = userRepository.getUserStickersFromPack(userID, packID); + List<Long> userStickers = userRepository.getUserStickersFromPack(username, packID); + System.out.println(userStickers); @@ -86,4 +133,7 @@ public class UserController { return displayedStickers; } + + + } diff --git a/src/main/java/Team5/SmartTowns/users/UserRepository.java b/src/main/java/Team5/SmartTowns/users/UserRepository.java index f0f01269786128dd9afaa8d3becd5b3ada4944fa..097598e24dce331a62b34346c3ec2326fa215934 100644 --- a/src/main/java/Team5/SmartTowns/users/UserRepository.java +++ b/src/main/java/Team5/SmartTowns/users/UserRepository.java @@ -5,7 +5,10 @@ import java.util.List; public interface UserRepository { List<User> getAllUsers(); - List<Long> getUserStickersFromPack(int userID, int packID); - User getUserById(int userID); - boolean unlockSticker(int userID, int packID, int stickerID); + List<Long> getUserStickersFromPack(String username, int packID); + boolean unlockSticker(String username, int packID, int stickerID); + boolean addUser(String username, String email, String password); + boolean doesUserExist(String email); + User findUserByEmail(String email); + User findUserByName(String name); } diff --git a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java index 8b46fc3a568455e91c180b66fc91b65f20d20c81..a88ac6e1c91fc85e5eb19fb6f0f7fcef3b9cb833 100644 --- a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java @@ -1,16 +1,23 @@ //Implements the users repository using JDBC package Team5.SmartTowns.users; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.object.SqlQuery; import org.springframework.stereotype.Repository; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.HashMap; import java.util.List; +import java.util.Objects; @Repository public class UserRepositoryJDBC implements UserRepository{ - private JdbcTemplate jdbc; + private final JdbcTemplate jdbc; private RowMapper<User> userMapper; public UserRepositoryJDBC(JdbcTemplate aJdbc){ @@ -20,9 +27,8 @@ public class UserRepositoryJDBC implements UserRepository{ private void setUserMapper(){ userMapper = (rs, i) -> new User( - rs.getInt("id"), rs.getString("email"), - rs.getString("name") + rs.getString("username") ); } @@ -34,23 +40,57 @@ public class UserRepositoryJDBC implements UserRepository{ @Override - public User getUserById(int userID){ - String sql= "SELECT * FROM users WHERE id="+userID; - List<User> result = jdbc.query(sql, userMapper); - return result.isEmpty() ? null : result.get(0); + public List<Long> getUserStickersFromPack(String username, int packID) { + /* Returns a list with the stickerIDs of stickers that the specified user has unlocked from the given pack */ + String sql = "SELECT stickerID FROM stickerprogress WHERE (username, packID)= (?,?)"; + return jdbc.queryForList(sql, Long.class, username, packID); } @Override - public List<Long> getUserStickersFromPack(int userID, int packID) { - String sql = "SELECT stickerID FROM stickerprogress WHERE (userID, packID)= (" + userID + "," + packID + ")"; - return jdbc.queryForList(sql, Long.class); + public boolean unlockSticker(String username, int packID, int stickerID){ + /* Adds entry in the stickerprogress database, effectively unlocking the sticker for the user + * Returns false if no sticker is unlocked */ + String query = "SELECT COUNT(id) FROM stickers WHERE (stickerID, packID) = (?, ?)"; + + int stickerCount = jdbc.queryForObject(query, Integer.class, stickerID, packID); + + if (stickerCount == 1){ //Checks if sticker exists + String sql = "INSERT INTO stickerprogress (username, packID, stickerID) VALUES (?,?,?)"; + jdbc.update(sql, username, packID, stickerID); + return true; + } + return false; } @Override - public boolean unlockSticker(int userID, int packID, int stickerID){ - String sql = "INSERT INTO stickerprogress (userID, packID, stickerID) VALUES (" + - userID + ", " + packID + "," + stickerID + ")"; - jdbc.update(sql); + public boolean addUser(String username, String email, String password) throws DataAccessException{ + /* Adds new user to the database */ + String query = "INSERT INTO users (username, email, password) VALUES (?, ?, ?);"; + String query2= "INSERT INTO authorities (username, authority) VALUES (?,?);"; + jdbc.update(query, username, email, password); + jdbc.update(query2, username, "USER"); return true; } + @Override + public boolean doesUserExist(String email){ + /* Returns true if a user with given email already exists in the database */ + String query = "SELECT COUNT(email) FROM users WHERE (email) = (?)"; + return !(jdbc.queryForObject(query, Integer.class, email) == 0); + } + + @Override + public User findUserByEmail(String email) { + /* Finds user matching given email */ + String query = "SELECT * FROM users WHERE (email) = (?)"; + List<User> result = jdbc.query(query, userMapper, email); + return result.isEmpty() ? null : result.get(0); + } + @Override + public User findUserByName(String name) { + /* Finds user matching given name */ + String query = "SELECT * FROM users WHERE (username) = (?)"; + List<User> result = jdbc.query(query, userMapper, name); + return result.isEmpty() ? null : result.get(0); + } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 95f46c69ab2c6b38e1c520a5b8438c8f87aba0a3..52e81d219c68d4702643665e6f9d58c7aebb8308 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,3 +3,4 @@ spring.datasource.username=root spring.datasource.password=comsc spring.sql.init.mode=always +spring.sql.init.data-locations=classpath:data.sql, classpath:/static/sql/user-data.sql, classpath:/static/sql/user-progress-data.sql diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 592b70f73184ea557fe68d2e5c410724e6a3e6c0..389042e16e7a3acdc3cb53ca62ce1a7438747069 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,32 +1,37 @@ -delete from users; -insert into users (email, name) value ('hannah@gmail.com', 'Hannah'); -insert into users (email, name) value ('nigel@gmail.com', 'Nigel'); +# delete from users; +# insert into users (email, name) value ('hannah@gmail.com', 'Hannah'); +# insert into users (email, name) value ('nigel@gmail.com', 'Nigel'); delete from trails; -insert into trails ( Name,tru) value ( 'Caerphilly Coffee Trail',false); -insert into trails ( Name,tru) value ( 'Penarth Dragon Trail',true); +insert into trails ( trailID, trailName, trailNumber) value ( 0101,'Caerphilly Castle Trail','0101'); +insert into trails ( trailID, trailName, trailNumber) value ( 0102,'Caerphilly Pub Trail','0102'); +insert into trails ( trailID, trailName, trailNumber) value ( 0103,'Caerphilly Heritage Trail','0103'); +insert into trails ( trailID, trailName, trailNumber) value ( 0201,'Risca Heritage Trail','0201'); +insert into trails ( trailID, trailName, trailNumber) value ( 0301,'Penarth Esplanade Trail','0301'); delete from locations; -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, false); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Castle','','Location description here','Caerphilly',0101, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Medieval Trades','','Location description here','Caerphilly',0101, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Queen''s War','','Location description here','Caerphilly',0101, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, false); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'JD Wetherspoons-Malcolm Uphill','','Location description here','Caerphilly',0102, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Cwtch','','Location description here','Caerphilly',0102, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, false); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Bus Station','','Location description here','Caerphilly',0103, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Medieval Courthouse','','Location description here','Caerphilly',0103, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, true); -insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, false); + insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Risca Colliery','','Location description here','Risca',0201, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201, true); + insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Esplanade','','Location description here','Penarth',0301, true); insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301, true); @@ -46,20 +51,20 @@ insert into packs (name, description) value ('Wales Rugby Team', 'Pack of Welsh insert into packs (name, description) value ('Welsh Heritage', 'Pack About Welsh Heritage'); -delete from stickers; -insert into stickers (packID, stickerID, name, description, rarity) value (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2'); -insert into stickers (packID, stickerID, name, description, rarity) value (1, 2, 'neco_williams', 'Wales Football Team Player', '2'); -insert into stickers (packID, stickerID, name, description, rarity) value (1, 3, 'joe_morrell', 'Wales Football Team Player', '2'); -insert into stickers (packID, stickerID, name, description, rarity) value (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2'); -insert into stickers (packID, stickerID, name, description, rarity) value (1, 5, 'connor_roberts', 'Wales Football Team Player', '2'); -insert into stickers (packID, stickerID, name, description, rarity) value (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (3, 1, 'Welsh Lady', 'Welsh Heritage', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (3, 2, 'Welsh Outline', 'Welsh Heritage', '1'); -insert into stickers (packID, stickerID, name, description, rarity) value (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1'); +DELETE FROM stickers; +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 2, 'neco_williams', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 3, 'joe_morrell', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 5, 'connor_roberts', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 1, 'Welsh Lady', 'Welsh Heritage', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 2, 'Welsh Outline', 'Welsh Heritage', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1'); # delete from stickerprogress; # insert into stickerprogress (userID, stickerID, hasSticker) value ('1', '1', true); @@ -71,7 +76,7 @@ insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLon insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (3, 51.575372, -3.219186); insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (4, 51.576363, -3.220712 ); insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (9, 51.57239, -3.21992); -insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (10, 51.57229, -3.21937 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (10, 51.57230, -3.21938 ); insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (13, 51.57168, -3.21861); insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (14, 51.57465, -3.22022 ); insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (17, 51.61117, -3.10198 ); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 83a9327f1be3a0cb598bac93df6edfbaede42c39..6a2f0ee317773ffb4f36e8b87037a5c250bcb1c4 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,9 +1,30 @@ + +/* DELETES AND RECREATES DATABASE EVERY TIME THE SYSTEM IS BOOTED*/ +DROP DATABASE IF EXISTS towns; +CREATE DATABASE IF NOT EXISTS towns; +USE towns; +/****************************************************************/ + +/* DROPS ALL TABLES IF THEY EXIST (they wont but just in case) */ + +drop table if exists locationCoordinates; +drop table if exists locations; drop table if exists trails; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS stickers; +DROP TABLE IF EXISTS packs; +DROP TABLE IF EXISTS stickerProgress; + + + +/****************************************************************/ + +/* CREATES ALL TABLES */ create table if not exists trails ( - trailID bigint auto_increment primary key, - name varchar(128), - tru boolean + trailID varchar(128) primary key, + trailName varchar(128), + trailNumber varchar(128) ) engine=InnoDB; drop table if exists locationCoordinates; @@ -20,52 +41,52 @@ create table if not exists locations ) engine=InnoDB; -drop table if exists users; -drop table if exists stickers; -drop table if exists packs; -drop table if exists stickerProgress; - -create table if not exists users -( - id bigint auto_increment primary key, +CREATE TABLE IF NOT EXISTS users ( + username varchar(30) primary key NOT NULL, + id bigint auto_increment unique, /*DEPRECATED COLUMN, LEFT IN WHILE SOME OTHER FUNCTIONS STILL USE IT*/ email varchar(128), - name varchar(30), - dragonProgress int, - dragonsLandmarkIDs longtext -) engine=InnoDB; + password varchar(30) NOT NULL, + enabled boolean default true +); +CREATE TABLE IF NOT EXISTS authorities ( + id bigint primary key auto_increment NOT NULL, + username varchar(30) NOT NULL , + authority varchar(45) NOT NULL +); -create table if not exists packs -( +CREATE TABLE IF NOT EXISTS packs ( id bigint auto_increment primary key, - name varchar(20), + name varchar(20) NOT NULL, description text -) engine=InnoDB; +); -create table if not exists stickers -( +CREATE TABLE IF NOT EXISTS stickers ( id bigint auto_increment primary key, - packID bigint, + packID bigint NOT NULL, FOREIGN KEY (packID) REFERENCES packs(id) ON DELETE CASCADE ON UPDATE RESTRICT, - stickerID bigint, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/ - name varchar(30), - description text, + stickerID bigint NOT NULL, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/ + name varchar(30) NOT NULL, + description text NOT NULL, rarity tinyint - -) engine=InnoDB; - -create table if not exists stickerProgress -( +); +CREATE TABLE IF NOT EXISTS stickerProgress ( id bigint auto_increment primary key, - userID bigint, - stickerID bigint -) engine=InnoDB; - - - - + username varchar(30) NOT NULL, + FOREIGN KEY (username) REFERENCES users(username) + ON DELETE CASCADE + ON UPDATE RESTRICT, + packID bigint NOT NULL, + FOREIGN KEY (packID) REFERENCES packs(id) + ON DELETE CASCADE + ON UPDATE RESTRICT, + stickerID bigint NOT NULL, + FOREIGN KEY (stickerID) REFERENCES stickers(id) + ON DELETE CASCADE + ON UPDATE RESTRICT +); create table if not exists locationCoordinates ( diff --git a/src/main/resources/static/css/locationPageFragsStyle.css b/src/main/resources/static/css/locationPageFragsStyle.css index 53cf211001f02daf8ff1874a25d6546015115b37..db091e112e77a7abc0c507fc0305e6a2a2244317 100644 --- a/src/main/resources/static/css/locationPageFragsStyle.css +++ b/src/main/resources/static/css/locationPageFragsStyle.css @@ -14,6 +14,9 @@ color: wheat; } +#return{ + padding-bottom: 10px; +} iframe{ margin-top: 20px; margin-bottom: 60px; diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css new file mode 100644 index 0000000000000000000000000000000000000000..023566c253e9354e789e85744cd1e4989d523845 --- /dev/null +++ b/src/main/resources/static/css/login.css @@ -0,0 +1,372 @@ +@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap'); + +:root { + --container-colour: #2a2a2a; + --details-colour: var(--primary-light); + --details-light: #512da8; + + --font-buttons: 14px; + --font-size-1: 14px; + --font-size-2: 200px; + --font-size-3: 300px; + + --error-colour: red; +} + +*{ + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Montserrat', sans-serif; + color: white; +} + +body{ + align-items: center; + height: 100svh; +} + +main { + height: 90%; + width: 90%; + display: flex; + align-items: center; + justify-content: center; +} + +@keyframes move{ + 0%, 49.99%{ + opacity: 0; + z-index: 1; + } + 50%, 100%{ + opacity: 1; + z-index: 5; + } +} + +@media only screen +and (min-device-width: 650px) { + .container{ + background-color: var(--container-colour); + border-radius: 30px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35); + position: relative; + overflow: hidden; + min-width: 768px; + max-width: 100%; + min-height: 480px; + } + + .container p{ + font-size: 14px; + line-height: 20px; + letter-spacing: 0.3px; + margin: 20px 0; + } + + + .container a{ + font-size: var(--font-size-1); + text-decoration: none; + margin: 15px 0 10px; + } + + .container button{ + background-color: var(--details-colour)/*#512da8*/; + color: #fff; + font-size: var(--font-buttons); + padding: 10px 45px; + border: 1px solid transparent; + border-radius: 8px; + font-weight: 600; + letter-spacing: 0.5px; + text-transform: uppercase; + margin-top: 10px; + cursor: pointer; + } + + .container button.hidden{ + background-color: transparent; + border-color: #fff; + } + + .container form{ + background-color: var(--container-colour); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0 40px; + height: 100%; + } + + .container input{ + background-color: #eee; + border: none; + margin: 8px 0; + padding: 10px 15px; + font-size: 13px; + border-radius: 8px; + width: 100%; + outline: none; + } + + .form-container{ + position: absolute; + top: 0; + height: 100%; + transition: all 0.6s ease-in-out; + } + + .sign-in{ + left: 0; + width: 50%; + z-index: 2; + } + + .container.active .sign-in{ + transform: translateX(100%); + } + + .sign-up{ + left: 0; + width: 50%; + opacity: 0; + z-index: 1; + } + + .container.active .sign-up{ + transform: translateX(100%); + opacity: 1; + z-index: 5; + animation: move 0.6s; + } + + + + .toggle-container{ + position: absolute; + top: 0; + left: 50%; + width: 50%; + height: 100%; + overflow: hidden; + transition: all 0.6s ease-in-out; + border-radius: 150px 0 0 100px; + z-index: 1000; + } + + .container.active .toggle-container{ + transform: translateX(-100%); /*BG THING*/ + border-radius: 0 150px 100px 0; + } + + .toggle{ + background-color: var(--details-colour); + height: 100%; + background: linear-gradient(to right, var(--details-light), var(--details-colour)); + color: #fff; + position: relative; + left: -100%; + height: 100%; + width: 200%; + transform: translateX(0); + transition: all 0.6s ease-in-out; + } + + .container.active .toggle{ + transform: translateX(50%); + } + + .toggle-panel{ + position: absolute; + width: 50%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0 30px; + text-align: center; + top: 0; + transform: translateX(0); + transition: all 0.6s ease-in-out; + } + + .toggle-left{ + transform: translateX(-200%); + } + + .container.active .toggle-left{ + transform: translateX(0); + } + + .toggle-right{ + right: 0; + transform: translateX(0); + } + + .container.active .toggle-right{ + transform: translateX(200%); + } + .input { + color: black; + } + +} +@media only screen +and (max-device-width: 640px) { + .container { + position: relative; + + background-color: var(--container-colour); + border-radius: 30px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35); + + overflow: hidden; + + width: 100%; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: space-evenly; + } + .form-container { + height: 100%; + transition: all 0.6s ease-in-out; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + .form-container form { + display: flex; + + flex-direction: column; + align-items: center; + font-size: 3em; + margin-inline: 5%; + } + .form-container input { + flex: 1 1; + font-size: 1em; + color: black; + margin-block: 5%; + padding: 2%; + border-radius: 30px; + } + + .form-container button { + flex: 1 1; + font-size: 1em; + } + .toggle-container { + position: absolute; + top: 0; + width: 100%; + height: 50%; + transition: all 0.6s ease-in-out; + overflow: hidden; + border-radius: 0 0 150px 150px; + z-index: 1000; + + } + .container.active .toggle-container{ + transform: translateY(100%); /*BG THING*/ + border-radius: 150px 150px 0 0; + } + .toggle { + position: absolute; + width: 100%; + height: 200%; + display: flex; + flex-direction: column-reverse; + align-items: center; + justify-content: space-evenly; + background: linear-gradient(to bottom, var(--details-light), var(--details-colour)); + /*background-color: red;*/ + } + .toggle-panel { + flex: 1 1; + width: 100%; + } + .container .toggle-right { + transform: translateY(0); + opacity: 1; + } + .container .toggle-left { + transform: translateY(-100%); + opacity: 0; + } + .container.active .toggle-right{ + transform: translateY(-100%); + opacity: 0; + } + .container.active .toggle-left{ + transform: translateY(-100%); + opacity: 1; + } + + .container .sign-up { + opacity: 0; + z-index: -1; + transform: translateY(100%); + } + .container .sign-in { + opacity: 1; + z-index: 5; + } + + .container.active .sign-in{ + transform: translateY(-100%); + opacity: 0; + z-index: -1; + } + .container.active .sign-up{ + animation: move 0.6s; + opacity: 1; + z-index: 5; + transform: translateY(0); + } + + + .toggle-panel { + transition: all 0.6s ease-in-out; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: xxx-large; + + } + .toggle-panel p { + margin-inline: 10%; + margin-block: 5%; + line-height: 1.5em; + } + .container button{ + background-color: var(--details-colour)/*#512da8*/; + color: #fff; + font-size: xxx-large; + padding: 40px 40px; + border: 5px solid transparent; + border-radius: 14px; + font-weight: 600; + letter-spacing: 1px; + text-transform: uppercase; + margin-top: 30px; + cursor: pointer; + } + + .container button.hidden{ + background-color: transparent; + border-color: #fff; + } +} +.alert { + color: var(--error-colour); + text-shadow: var(--error-colour) 0 0 10px; +} + diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index 08273bc1bba5a74c518361f71f7d88bb53774811..934cac13d9ed4bfebab932cc72b6839e0869b25b 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -1,210 +1,87 @@ * { - box-sizing: border-box; - padding: 0; - margin: 0; + margin: 0; + padding: 0; + box-sizing: border-box; } -#homeHead{ - color: inherit; - text-decoration: none; - padding: 0; - margin: 0;} +* { + /*COLOUR PALETTE*/ + @media (prefers-color-scheme: dark) { + --primary-darker: hsl(272, 100%, 10%); + --primary-dark: hsl(271, 100%, 20%); + --primary-colour: hsl(271, 100%, 30%); + --primary-light: hsl(271, 100%, 40%); + --primary-lighter: hsl(271, 100%, 50%); + + --secondary-colour: hsl(12, 81%, 46%); + --accent-colour: hsl(12, 82%, 32%); + --accent-border: hsl(12, 81%, 25%); + + --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; + + color: white; -.center { - text-align: center; -} -body { - background-color: rgb(41, 41, 41); - margin: 0%; -} -.headerBlock { - background-color: rgb(15, 15, 15); - padding-bottom: 20px; - box-shadow: 0 10px 20px black; - .headerTitle { - text-align: center; - padding: 10px 10px 0 10px; - margin: 0 50px 0 50px; - letter-spacing: 10px; - font-size: 50px; - font-style: italic; - color: blueviolet; - text-shadow: black 3px 3px 5px; - border-bottom: 3px blueviolet solid; - } - .headerBanner { - display: flex; - flex-direction: column; - justify-content: center; - overflow: hidden; - position: relative; - height: 200px; - border-top: grey solid 2px; - border-bottom: grey solid 2px; - - .bannerBack { - opacity: 0.6; - width: 100%; - left: 0; - top: 0; - position: absolute - } - .bigTitle { - color:white; - text-align: center; - position: relative; - font-size: 50px; - margin: 20px 20px 5px; - } - .smallTitle { - position: relative; - color:white; - text-align: center; - font-size: 20px; - margin: 5px 20px 20px; - } } -} + @media (prefers-color-scheme: light) { + --primary-darker: hsl(272, 100%, 10%); + --primary-dark: hsl(271, 100%, 20%); + --primary-colour: hsl(271, 100%, 30%); + --primary-light: hsl(271, 100%, 40%); + --primary-lighter: hsl(271, 100%, 50%); + --secondary-colour: hsl(12, 81%, 46%); + --accent-colour: hsl(12, 82%, 32%); + --accent-border: hsl(12, 81%, 25%); + + --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; + + color: white; -.mainTrails{ - overflow: hidden; - position: relative; - height: 200px; - border-top: grey solid 2px; - border-bottom: grey solid 2px; -} -.trailList { - .ulHeader { - margin: 30px; - display: flex; - list-style: none; - justify-content: center; - padding: 0px; - border-bottom: solid black 5px; - - .liHeader { - - flex: 1 1 0px; - padding-left: 10px; - padding-right: 10px; - color: white; - text-align: center; - } - .liHeader:hover { - color: blueviolet; - border-bottom: solid blueviolet 2px; - } - .selected { - flex: 1 1 0px; - padding-left: 10px; - padding-right: 10px; - color: rgb(154, 69, 234); - border-bottom: solid blueviolet 2px; - text-align: center; - } } - } -.mainBlock { + +body { + background: linear-gradient(to bottom right, + var(--primary-darker), + var(--primary-dark), + var(--primary-darker)); + display: flex; - min-width: 300px; - flex-wrap: wrap; - margin-top: 20px; - margin-bottom: 100px; + flex-direction: column; + justify-content: center; + align-content: center; } -.mainBlock .trailStats{ - background-color: rgb(206, 153, 253); - flex: 0 0 0px; - min-width: 400px; - height: 600px; - margin: auto; - margin-bottom: 20px; - box-shadow: 0px 0px 20px rgb(20, 20, 20); - border-radius: 30px; - .stats { - display: block; - width: 200px; - margin: auto; - } - .textStats { - display: block; - text-align: left; - margin: 20px; - } -} -.mainBlock .trailInfo{ - background-color: rgb(206, 153, 253); - flex: 0 0 0px; - min-width: 400px; - height: 600px; - margin: auto; - margin-bottom: 20px; - box-shadow: 0px 10px 10px rgb(20, 20, 20); - border-radius: 30px; - .trailInfoTxt { - margin: 15px; - } -} -.titleH1 { - padding: 0px; - margin: 10px 30px 20px 30px; - text-align: center; - font-size: 40px; - font-style: italic; - border-bottom: solid black 1px; -} -.mainBlock p { - font-size: 25px; - text-align: left; - padding: 1px; -} -main .badgesBlock{ - bottom: 0%; - background-color: rgb(222, 75, 255); - flex: 0 0 0px; - min-width: 500px; - min-height: 100px; - margin: auto; - margin-bottom: 10px; - box-shadow: 0px 10px 10px rgb(20, 20, 20); - border-radius: 30px; -} -.badgesList { +.centerAll { display: flex; -} -.badgeImg { - flex: 0 1 0px; - width: 60px; - margin: auto; - margin-bottom: 20px; - + flex-direction: column; + align-items: center; + justify-content: center; } -footer { - z-index: 99; - bottom: 0%; - left: 0%; - position: fixed; - width: 100%; - min-width: 300px; -} -footer .footerBar { - display: flex; - list-style: none; - padding: 0; - margin: 0; - +/*PHONES PORTRAIT*/ +@media only screen +and (min-device-width: 320px) +and (max-device-width: 640px) { + body { + position: fixed; + width: 100vw; + height: 100svh; + } + html { + position: fixed; + width: 100vw; + height: 100svh; + } } -footer .footerButton { - padding: 20px; - text-align: center; - flex: 1 1 0px; - color:crimson; - background-color: white; - + +/*PHONES LANDSCAPE*/ +@media only screen +and (min-device-width: 640px) +and (max-device-width: 1000px) { + + } -footer .footerButton:hover { - background-color: black; -} \ No newline at end of file + +/*LARGER SCREENS*/ +@media only screen and (min-device-width: 1000px) {} \ No newline at end of file diff --git a/src/main/resources/static/css/trailsPageFragsStyle.css b/src/main/resources/static/css/trailsPageFragsStyle.css new file mode 100644 index 0000000000000000000000000000000000000000..1e2a067eb8819da6c8d0b69c8486cc5055795023 --- /dev/null +++ b/src/main/resources/static/css/trailsPageFragsStyle.css @@ -0,0 +1,36 @@ +.trailsFragment{ + background-color: rgb(206, 153, 253); + color: black; + border-color: white; + align-content: center; + text-align: center; + border-radius: 25px; + max-width: 800px; + margin: 0 auto; + +} +.trailsPageFrag{ + background: rgb(41, 41, 41); + color: wheat; +} + +iframe{ + margin-top: 20px; + margin-bottom: 20px; + border: white 2px solid; +} +H1{ + padding-top: 15px; + padding-bottom:3px ; + margin-bottom: 0; +} +#trailHeader{ + margin: 0; + padding: 0; + +} + +#checkpointList{ + list-style: none; + padding-bottom: 10px; +} \ No newline at end of file diff --git a/src/main/resources/static/css/userProfile.css b/src/main/resources/static/css/userProfile.css deleted file mode 100644 index 878ab054fc53828cb76726775109ca7d3f4bcc80..0000000000000000000000000000000000000000 --- a/src/main/resources/static/css/userProfile.css +++ /dev/null @@ -1,408 +0,0 @@ -/* AUTHOR: Gabriel Copat*/ -@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); - -/*COLOUR PALETTE*/ -* { - --main-colour: #e47201; - --secondary-colour: #e47201; - --accent-colour: #e47201; - --accent-border: #b25901; - - --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; -} - - -/*FONTS, TYPOGRAPHY & BACKGROUNDS*/ -* { - margin: 0; - padding: 0; - - & h1, & h2 { - letter-spacing: 0.25vw; - line-height: 1.3; - text-align: center; - color: white; - text-justify: inter-word; - } - & label { - color: white; - } - -} -@media only screen and (max-device-width: 500px) { - /*ADJUSTING FOR SMALLER SCREENS*/ - * { - & h1, & h2 { text-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1svh;} - & p { line-height: 1.1; color: white;} - } -} -html{ - height: 100%; - @media only screen and (min-device-width: 1500px) { - height: auto; - } -} -body { - background: linear-gradient(135deg, #f7e8fd, #9914d1); - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-evenly; - @media only screen and (min-device-width: 1500px) { - height: auto; - } -} -main { - background: linear-gradient(to bottom, #1e1e1e 10%, darkgoldenrod 50%, #1e1e1e 90%); - border-radius: 1vw; - margin-inline: 5%; - /*margin-block: 5%;*/ - width: auto; - padding-block: 2svh; - margin-top: 6em; - padding-inline: 1vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em); - transition: all linear 2s; - overflow-y: scroll; - height: 90%; - @media only screen and (min-device-width: 1500px) { - padding-inline: 20%; - overflow: visible; - } -} -.rewards { - position: relative; -} -.userInfo { - display: flex; - flex-direction: column; - /*padding: min(2vw, 4em);*/ - text-align: center; - - & #userPicture { - width: min(30vw, 30em); - margin-inline: auto; - border-radius: 100%; - border: solid #a2a2a2 4px; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em); - } - - & h1 { - font-size: max(5vw, 2em); - margin: 1svh 25%; - color:white; - border-bottom: #36454F solid 2px; - border-radius: 5vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw; - } -} -#packsBar::-webkit-scrollbar { - display: none; - -ms-scrollbar-darkshadow-color: transparent; -} -#packsBar { - position: static; - display: grid; - grid-template-areas: - "header" - "packs"; - overflow-x: scroll; - overflow-y: hidden; - color: white; - padding-bottom: 2%; - @media only screen and (min-device-width: 501px) { - height: 24vw; - } - & h2 { - position: absolute; - grid-area: header; - margin-inline: 5vw; - padding-inline: 2vw; - margin-block: -1svh; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw; - border-bottom: #36454F solid 2px; - font-size: 4vw; - width: 7em; - height: 1.2em; - - } - & #allPacksContainer { - margin-top: 3svh; - grid-area: packs; - height: 12svh; - width: 100%; - display: flex; - justify-content: space-between; - @media only screen and (min-device-width: 501px) { - height: 20vw; - margin-top: 6vw; - } - } - & .packContainer{ - position: relative; - height: 12svh; - width: 20vw; - display: flex; - flex-direction: column; - text-align: center; - justify-content: center; - overflow: visible; - } - - & .packImg { - position: relative; - margin-inline: 3vw; - height: 8svh; - /*width: 25%;*/ - z-index: 50; - @media only screen and (min-device-width: 501px) { - height: 15vw; - } - transition: 0.3s ease-out 100ms; - } - & .packImg:hover { - /*box-shadow: 0 0 20px 10px #bbbb00;*/ - transform: scale(1.5,1.5); - - } - & .packName { - height: 4svh; - display: flex; - justify-content: center; - font-size: 2em; - overflow: hidden; - align-items: flex-end; - - } -} - -#stickersBox { - padding-top: 5%; - display: flex; - flex-direction: column; - /* border-bottom-left-radius: 2vw; */ - /* border-bottom-right-radius: 2vw; */ - /*background: linear-gradient(to bottom, darkgoldenrod, transparent 90%);*/ - margin-top: -1%; - height: 500px; - & h2 { - font-size: 4em; - text-align: center; - box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw; - border-bottom: #36454F solid 2px; - margin-block: 1svh; - margin-inline: 25%; - } - & .stickersContainer { - margin-block: 1svh; - display: flex; - flex-wrap: wrap; - justify-content: space-around; - width: 100%; - - & .stickerImg { - width: 20vw; - margin-block: 1em; - - } - } -} -.locked { - filter: grayscale(100%); -} - -.dragonProgression { - position: relative; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - height: 16svh; - box-sizing: content-box; - /*background: linear-gradient(to bottom, transparent -50%, darkgoldenrod 50%);*/ - width: 100%; - /*padding-top: 1svh;*/ - - @media only screen and (min-device-width: 501px) { - height: 28vw; - margin-bottom: 0; - padding-bottom: 5svh; - } - & h1 { - font-size: 3em; - font-family: 'MedievalSharp', cursive; - letter-spacing: 1vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw; - border-bottom: #36454F solid 2px; - border-top: #36454F solid 2px; - margin-inline: 15%; - margin-bottom: 1%; - } - & .dragonContainer { - position: relative; - margin: auto; - } - & .dragonImg { - height: 10svh; - width: 16svh; - @media only screen and (min-device-width: 501px) { - height: 22vw; - width: 30vw; - } - - } - & .dragonFill { - position: absolute; - overflow: hidden; - width: 40%; - } - & .dragonOut { - /*position: absolute;*/ - overflow: hidden; - } -} -header { - z-index: 99; - top: 0.5svh; - left: 0; - position: fixed; - width: 100vw; - justify-content: center; - display: flex; -} -header .footerBar { - display: flex; - list-style: none; - border-radius: 1vw; - overflow: hidden; - justify-content: space-evenly; - background-color: rgba(0, 0, 0, 0.7); -} -header .footerButton { - padding: 1vw; - text-align: center; - /*flex: 1 1;*/ - color:crimson; - background-color: rgba(31, 31, 31, 0.7); - font-size: 2.5em; - width: 15vw; -} -header .footerButton:hover { - background-color: #36454F; -} - -.grayedOut { - filter: grayscale(1); -} - -.solidBg { - background: #1e1e1e; - display: flex; -} -.loginWrapper { - margin-inline: auto; - margin-block: 5svh; - display: flex; - text-align: center; - justify-content: center; - background: rgba(196, 92, 239, 0.75); - padding: 2em; - flex: 0 0; - border-radius: 1vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em); - & h2 { - margin-left: 0; - margin-right: auto; - margin-bottom: 0.5em; - } - & form{ - margin-block: auto; - font-size: 3em; - display: flex; - flex-direction: column; - } - & label { - position: relative; - margin-top: 1em; - /*width: fit-content;*/ - font-size: 0.8em; - & b { - float: left; - } - & a { - position: absolute; - font-size: 0.4em; - right: 0.2em; - bottom: 0.2em; - height: fit-content; - } - - } - & input { - font-size: 0.6em; - height: 1.5em; - width: 40vw; - border-radius: 0.2em; - padding-inline: 0.4em; - border: transparent solid 0.1em; - margin-bottom: 1em; - } - & button { - font-size: 1em; - height: 2em; - width: 4em; - box-shadow: var(--accent-shadow); - margin:auto; - margin-top: 1em; - background-color: var(--accent-colour); - border: 0.1em solid var(--accent-border); - border-radius: 1em; - color: white; - - } - & button:hover{ - background-color: var(--accent-border); - border: 0.1em solid var(--accent-colour); - } -} -.label { - position: relative; -} -.invalid-tooltip { - color: red; - width: fit-content; - opacity: 0; - font-size: 0.6em; - text-shadow: red 0 0.2em 1em; - transition: 0.3s ease-in-out 1ms; - padding:0.1em; - position: absolute; - right: 0.2em; - bottom: 0.2em; - height: fit-content; -} -.invalid-field { - box-shadow: red 0 0 1em; - transition: 0.3s ease-in-out 1ms; -} -.valid-field { - box-shadow: #40ff00 0 0 1em; - border: #40ff00 solid 0.1em; - transition: 0.3s ease-in-out 1ms; -} - - -#invalidLogin { - color: red; - text-shadow: black 0 0.1em 0.2em; - width: auto; - height: auto; - font-size: 0.6em; - opacity: 0; - transition: 0.5s ease-in-out 1ms; -} - -.rewards { - transition: 1s ease-in-out 1ms; -} \ No newline at end of file diff --git a/src/main/resources/static/css/userProfile2.css b/src/main/resources/static/css/userProfile2.css index 0728cbc6e973473051420fd817d243d5d484c489..0c5c0e9c4aef739bda2f4d38039fa4735a3e30bb 100644 --- a/src/main/resources/static/css/userProfile2.css +++ b/src/main/resources/static/css/userProfile2.css @@ -2,46 +2,7 @@ @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); -* { - margin: 0; - padding: 0; - box-sizing: border-box; - /*COLOUR PALETTE*/ - @media (prefers-color-scheme: dark) { - --primary-darker: hsl(272, 100%, 10%); - --primary-dark: hsl(271, 100%, 20%); - --primary-colour: hsl(271, 100%, 30%); - --primary-light: hsl(271, 100%, 40%); - --primary-lighter: hsl(271, 100%, 50%); - - --secondary-colour: hsl(12, 81%, 46%); - --accent-colour: hsl(12, 82%, 32%); - --accent-border: hsl(12, 81%, 25%); - - --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; - - color: white; - - } - @media (prefers-color-scheme: light) { - --primary-darker: hsl(272, 100%, 10%); - --primary-dark: hsl(271, 100%, 20%); - --primary-colour: hsl(271, 100%, 30%); - --primary-light: hsl(271, 100%, 40%); - --primary-lighter: hsl(271, 100%, 50%); - - --secondary-colour: hsl(12, 81%, 46%); - --accent-colour: hsl(12, 82%, 32%); - --accent-border: hsl(12, 81%, 25%); - - --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; - - color: white; - - - } -} @@ -237,8 +198,14 @@ main { height: 17em; margin: 1.5em; } -/*}*/ +/* LOGIN FORM PAGE */ + + + + + +/* MEDIA TYPE UPDATES*/ @media only screen and (min-device-width: 320px) and (max-device-width: 640px) { @@ -306,4 +273,21 @@ and (min-device-width: 1000px) { .progressionContainer { height: 20svh; } -} \ No newline at end of file +} + +.container { + width: 500px; + margin-block: 5%; + background-color: var(--accent-colour); + border-radius: 10em; + display: flex; + flex-direction: column; + align-items: center; + & form { + margin-inline: auto; + margin-block: 5%; + } +} +.container-active { + background: black; +} diff --git a/src/main/resources/static/scripts/login.js b/src/main/resources/static/scripts/login.js index 38ef327134aa8ae03ddc44ddf796b2df139fc3bb..df3b4ddf21b32933d0b283c60141be8e8eb5197c 100644 --- a/src/main/resources/static/scripts/login.js +++ b/src/main/resources/static/scripts/login.js @@ -1,51 +1,73 @@ -let username = document.forms["loginForm"]["username"]; -let password = document.forms["loginForm"]["password"]; -let pattern = new RegExp("^[a-z0-9_-]{3,15}$"); - -username.addEventListener("input", validateUsername) -password.addEventListener("input", validatePassword) - -function validateUsername() { - if (!(username.value === "") && pattern.test(username.value)){ - username.classList.remove("invalid-field"); - username.classList.add("valid-field"); - document.getElementById(username.name+"Invalid").style.opacity = 0; - username.style.borderColor = "green"; - return true; - } else if( ! (username.classList.contains("invalid-field") ) ){ - username.classList.add("invalid-field"); - username.classList.remove("valid-field"); - document.getElementById(username.name+"Invalid").style.opacity = 1; - username.style.borderColor = "red"; +const container = document.getElementById('container'); +const registerBtn = document.getElementById('register'); +const loginBtn = document.getElementById('login'); + +registerBtn.addEventListener('click', () => { + container.classList.add("active"); +}); + +loginBtn.addEventListener('click', () => { + container.classList.remove("active"); +}); + + +const emailRegEx = new RegExp(/^[A-Za-z0-9.-_]+@[A-Za-z0-9.-]+\.[A-Za-z]+$/m); +const passwordRegEx = new RegExp(/^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+$/m); +const usernameRegEx = new RegExp(/^[A-Za-z ]+$/m); + +function loginFormValidation(){ + let pass= true; + let email = $("#login-email").val(); + let password = $("#login-password").val(); + if (email === "") { + alert("Email cannot be empty"); + pass = false; + } else if ( !(emailRegEx.test(email)) ) { + pass = false; + alert("Invalid Email address") } - return false; -} -function validatePassword(){ - if (password.value === "") { - password.classList.add("invalid-field"); - password.classList.remove("valid-field"); - document.getElementById(password.name+"Invalid").style.opacity = 1; - password.style.borderColor = "red"; - return false; - } else if( ! (password.classList.contains("valid-field") ) ) { - password.classList.remove("invalid-field"); - password.classList.add("valid-field"); - document.getElementById(password.name+"Invalid").style.opacity = 0; - password.style.borderColor = "green"; + if (password === "") { + alert("Password cannot be empty"); + pass = false; + } else if ( !(passwordRegEx.test(password)) ) { + pass = false; + alert("Password contains invalid characters"); } - return true; + return pass; } -function validateForm(){ - if (validateUsername() & validatePassword()) { //Using just & so it checks both, even if the first is false (it applies the style) - console.log("VALID"); - return false; - } else { - console.log("Invalid"); - document.getElementById("invalidLogin").style.opacity = 1; - return false; +function registerFormValidation(){ + /*WHYTF THIS DONT WORK*/ + let pass=true; + let email = $("#register-email").val(); + let username = $("#register-username").val(); + let password = $("#register-password").val(); + + if (email == "") { + console.log("Email empty bit") + pass = false; + alert("Email cannot be empty"); + } else if ( !(emailRegEx.test(email)) ) { + console.log("Email no match") + pass = false; + alert("Invalid Email address"); } - //TODO SERVER SIDE VALIDATION AND CHECK AGAINST USERS DB TABLE -} + if (username == "") { + pass = false; + alert("Username cannot be empty") + } else if ( !(usernameRegEx.test(username)) ) { + console.log(!usernameRegEx.test(username)); + pass = false; + alert("Invalid username"); + } + if (password == "") { + pass = false; + alert("Password cannot be empty"); + } else if ( !(passwordRegEx.test(password)) ) { + pass = false; + alert("Password contains invalid characters"); + } + return pass; +} \ No newline at end of file diff --git a/src/main/resources/static/scripts/mapAPI.js b/src/main/resources/static/scripts/mapAPI.js index 6af8c3b085396384779093efaca5f777112a7537..8b81c394af31962757934756bdd48a299881b03f 100644 --- a/src/main/resources/static/scripts/mapAPI.js +++ b/src/main/resources/static/scripts/mapAPI.js @@ -1,153 +1,153 @@ -import GeoJSON from '/nodeMods/node_modules/ol/format/GeoJSON.js'; -import Map from '/nodeMods/node_modules/ol/Map.js'; -import VectorLayer from '/nodeMods/node_modules/ol/source/Vector.js' -import VectorSource from '/nodeMods/node_modules/ol/source/Vector.js'; -import View from '/nodeMods/node_modules/ol/View.js'; -import {DragBox, Select} from '/nodeMods/node_modules/ol/interaction.js'; -import {Fill, Stroke, Style} from '/nodeMods/node_modules/ol/style.js'; -import {getWidth} from '/nodeMods/node_modules/ol/extent.js'; -import {platformModifierKeyOnly} from '/nodeMods/node_modules/ol/events/condition.js'; -// //Invesitgate created directories mnode module mapstest and extent.js -// import GeoJSON from '/node_modules/ol/format/GeoJSON.js'; -// import Map from '/ol/Map.js'; -// import VectorLayer from '/ol/layer/Vector.js'; -// import VectorSource from '/ol/source/Vector.js'; -// import View from '/ol/View.js'; -// import {DragBox, Select} from '/ol/interaction.js'; -// import {Fill, Stroke, Style} from '/ol/style.js'; -// import {getWidth} from '/ol/extent.js'; -// import {platformModifierKeyOnly} from '/ol/events/condition.js'; - - -const vectorSource = new VectorSource({ - url: 'https://openlayers.org/data/vector/ecoregions.json', - format: new GeoJSON(), -}); - -const style = new Style({ - fill: new Fill({ - color: '#eeeeee', - }), -}); - -const map = new Map({ - layers: [ - new VectorLayer({ - source: vectorSource, - background: '#1a2b39', - style: function (feature) { - const color = feature.get('COLOR_BIO') || '#eeeeee'; - style.getFill().setColor(color); - return style; - }, - }), - ], - target: 'map', - view: new View({ - center: [0, 0], - zoom: 2, - constrainRotation: 16, - }), -}); - -const selectedStyle = new Style({ - fill: new Fill({ - color: 'rgba(255, 255, 255, 0.6)', - }), - stroke: new Stroke({ - color: 'rgba(255, 255, 255, 0.7)', - width: 2, - }), -}); - -// a normal select interaction to handle click -const select = new Select({ - style: function (feature) { - const color = feature.get('COLOR_BIO') || '#eeeeee'; - selectedStyle.getFill().setColor(color); - return selectedStyle; - }, -}); -map.addInteraction(select); - -const selectedFeatures = select.getFeatures(); - -// a DragBox interaction used to select features by drawing boxes -const dragBox = new DragBox({ - condition: platformModifierKeyOnly, -}); - -map.addInteraction(dragBox); - -dragBox.on('boxend', function () { - const boxExtent = dragBox.getGeometry().getExtent(); - - // if the extent crosses the antimeridian process each world separately - const worldExtent = map.getView().getProjection().getExtent(); - const worldWidth = getWidth(worldExtent); - const startWorld = Math.floor((boxExtent[0] - worldExtent[0]) / worldWidth); - const endWorld = Math.floor((boxExtent[2] - worldExtent[0]) / worldWidth); - - for (let world = startWorld; world <= endWorld; ++world) { - const left = Math.max(boxExtent[0] - world * worldWidth, worldExtent[0]); - const right = Math.min(boxExtent[2] - world * worldWidth, worldExtent[2]); - const extent = [left, boxExtent[1], right, boxExtent[3]]; - - const boxFeatures = vectorSource - .getFeaturesInExtent(extent) - .filter( - (feature) => - !selectedFeatures.getArray().includes(feature) && - feature.getGeometry().intersectsExtent(extent) - ); - - // features that intersect the box geometry are added to the - // collection of selected features - - // if the view is not obliquely rotated the box geometry and - // its extent are equalivalent so intersecting features can - // be added directly to the collection - const rotation = map.getView().getRotation(); - const oblique = rotation % (Math.PI / 2) !== 0; - - // when the view is obliquely rotated the box extent will - // exceed its geometry so both the box and the candidate - // feature geometries are rotated around a common anchor - // to confirm that, with the box geometry aligned with its - // extent, the geometries intersect - if (oblique) { - const anchor = [0, 0]; - const geometry = dragBox.getGeometry().clone(); - geometry.translate(-world * worldWidth, 0); - geometry.rotate(-rotation, anchor); - const extent = geometry.getExtent(); - boxFeatures.forEach(function (feature) { - const geometry = feature.getGeometry().clone(); - geometry.rotate(-rotation, anchor); - if (geometry.intersectsExtent(extent)) { - selectedFeatures.push(feature); - } - }); - } else { - selectedFeatures.extend(boxFeatures); - } - } -}); - -// clear selection when drawing a new box and when clicking on the map -dragBox.on('boxstart', function () { - selectedFeatures.clear(); -}); - -const infoBox = document.getElementById('info'); - -selectedFeatures.on(['add', 'remove'], function () { - const names = selectedFeatures.getArray().map((feature) => { - return feature.get('ECO_NAME'); - }); - if (names.length > 0) { - infoBox.innerHTML = names.join(', '); - } else { - infoBox.innerHTML = 'None'; - } -}); \ No newline at end of file +// import GeoJSON from '/nodeMods/node_modules/ol/format/GeoJSON.js'; +// import Map from '/nodeMods/node_modules/ol/Map.js'; +// import VectorLayer from '/nodeMods/node_modules/ol/source/Vector.js' +// import VectorSource from '/nodeMods/node_modules/ol/source/Vector.js'; +// import View from '/nodeMods/node_modules/ol/View.js'; +// import {DragBox, Select} from '/nodeMods/node_modules/ol/interaction.js'; +// import {Fill, Stroke, Style} from '/nodeMods/node_modules/ol/style.js'; +// import {getWidth} from '/nodeMods/node_modules/ol/extent.js'; +// import {platformModifierKeyOnly} from '/nodeMods/node_modules/ol/events/condition.js'; +// // //Invesitgate created directories mnode module mapstest and extent.js +// // import GeoJSON from '/node_modules/ol/format/GeoJSON.js'; +// // import Map from '/ol/Map.js'; +// // import VectorLayer from '/ol/layer/Vector.js'; +// // import VectorSource from '/ol/source/Vector.js'; +// // import View from '/ol/View.js'; +// // import {DragBox, Select} from '/ol/interaction.js'; +// // import {Fill, Stroke, Style} from '/ol/style.js'; +// // import {getWidth} from '/ol/extent.js'; +// // import {platformModifierKeyOnly} from '/ol/events/condition.js'; +// // +// +// const vectorSource = new VectorSource({ +// url: 'https://openlayers.org/data/vector/ecoregions.json', +// format: new GeoJSON(), +// }); +// +// const style = new Style({ +// fill: new Fill({ +// color: '#eeeeee', +// }), +// }); +// +// const map = new Map({ +// layers: [ +// new VectorLayer({ +// source: vectorSource, +// background: '#1a2b39', +// style: function (feature) { +// const color = feature.get('COLOR_BIO') || '#eeeeee'; +// style.getFill().setColor(color); +// return style; +// }, +// }), +// ], +// target: 'map', +// view: new View({ +// center: [0, 0], +// zoom: 2, +// constrainRotation: 16, +// }), +// }); +// +// const selectedStyle = new Style({ +// fill: new Fill({ +// color: 'rgba(255, 255, 255, 0.6)', +// }), +// stroke: new Stroke({ +// color: 'rgba(255, 255, 255, 0.7)', +// width: 2, +// }), +// }); +// +// // a normal select interaction to handle click +// const select = new Select({ +// style: function (feature) { +// const color = feature.get('COLOR_BIO') || '#eeeeee'; +// selectedStyle.getFill().setColor(color); +// return selectedStyle; +// }, +// }); +// map.addInteraction(select); +// +// const selectedFeatures = select.getFeatures(); +// +// // a DragBox interaction used to select features by drawing boxes +// const dragBox = new DragBox({ +// condition: platformModifierKeyOnly, +// }); +// +// map.addInteraction(dragBox); +// +// dragBox.on('boxend', function () { +// const boxExtent = dragBox.getGeometry().getExtent(); +// +// // if the extent crosses the antimeridian process each world separately +// const worldExtent = map.getView().getProjection().getExtent(); +// const worldWidth = getWidth(worldExtent); +// const startWorld = Math.floor((boxExtent[0] - worldExtent[0]) / worldWidth); +// const endWorld = Math.floor((boxExtent[2] - worldExtent[0]) / worldWidth); +// +// for (let world = startWorld; world <= endWorld; ++world) { +// const left = Math.max(boxExtent[0] - world * worldWidth, worldExtent[0]); +// const right = Math.min(boxExtent[2] - world * worldWidth, worldExtent[2]); +// const extent = [left, boxExtent[1], right, boxExtent[3]]; +// +// const boxFeatures = vectorSource +// .getFeaturesInExtent(extent) +// .filter( +// (feature) => +// !selectedFeatures.getArray().includes(feature) && +// feature.getGeometry().intersectsExtent(extent) +// ); +// +// // features that intersect the box geometry are added to the +// // collection of selected features +// +// // if the view is not obliquely rotated the box geometry and +// // its extent are equalivalent so intersecting features can +// // be added directly to the collection +// const rotation = map.getView().getRotation(); +// const oblique = rotation % (Math.PI / 2) !== 0; +// +// // when the view is obliquely rotated the box extent will +// // exceed its geometry so both the box and the candidate +// // feature geometries are rotated around a common anchor +// // to confirm that, with the box geometry aligned with its +// // extent, the geometries intersect +// if (oblique) { +// const anchor = [0, 0]; +// const geometry = dragBox.getGeometry().clone(); +// geometry.translate(-world * worldWidth, 0); +// geometry.rotate(-rotation, anchor); +// const extent = geometry.getExtent(); +// boxFeatures.forEach(function (feature) { +// const geometry = feature.getGeometry().clone(); +// geometry.rotate(-rotation, anchor); +// if (geometry.intersectsExtent(extent)) { +// selectedFeatures.push(feature); +// } +// }); +// } else { +// selectedFeatures.extend(boxFeatures); +// } +// } +// }); +// +// // clear selection when drawing a new box and when clicking on the map +// dragBox.on('boxstart', function () { +// selectedFeatures.clear(); +// }); +// +// const infoBox = document.getElementById('info'); +// +// selectedFeatures.on(['add', 'remove'], function () { +// const names = selectedFeatures.getArray().map((feature) => { +// return feature.get('ECO_NAME'); +// }); +// if (names.length > 0) { +// infoBox.innerHTML = names.join(', '); +// } else { +// infoBox.innerHTML = 'None'; +// } +// }); \ No newline at end of file diff --git a/src/main/resources/static/scripts/userPage.js b/src/main/resources/static/scripts/userPage.js index 2c1d5069ad652b854abf6b8cb460d7ebf89d696f..a7b036197965493cbdd621b241350c56167bac08 100644 --- a/src/main/resources/static/scripts/userPage.js +++ b/src/main/resources/static/scripts/userPage.js @@ -1,6 +1,6 @@ -function updatePack(userid, packid) { - /* Updates the trail being shown on screen to the one requested by ID */ - $.get("/packInfo/" + userid + "/" + packid).done(function (fragment) { +function updatePack(url) { + /* Updates the trail being shown on screen */ + $.get(url).done(function (fragment) { let packRewardsWrapper = $("#packRewardsWrapper"); packRewardsWrapper.fadeTo("slow", 0, function () { diff --git a/src/main/resources/static/sql/user-data.sql b/src/main/resources/static/sql/user-data.sql new file mode 100644 index 0000000000000000000000000000000000000000..333ec4091f3ab1578e91009cca9fe9e3d9b7872d --- /dev/null +++ b/src/main/resources/static/sql/user-data.sql @@ -0,0 +1,7 @@ +INSERT INTO users (username, password) VALUE ('Admin', 'admin'); +INSERT INTO users (username, password) VALUE ('Hannah', 'root'); +INSERT INTO users (username, password) VALUE ('Nigel', 'root'); +INSERT INTO users (username, password) VALUE ('Oscar', 'root'); + +INSERT INTO authorities (username, authority) VALUE ('Admin', 'ADMIN'); +INSERT INTO authorities (username, authority) VALUE ('Hannah', 'USER'); diff --git a/src/main/resources/static/sql/user-progress-data.sql b/src/main/resources/static/sql/user-progress-data.sql new file mode 100644 index 0000000000000000000000000000000000000000..e9223384658ac8bd55456a60f9b8e52423b3d429 --- /dev/null +++ b/src/main/resources/static/sql/user-progress-data.sql @@ -0,0 +1,7 @@ +DELETE FROM stickerprogress; +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 1); +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 2); +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 3); +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 5); +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 1); +INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 3); \ No newline at end of file diff --git a/src/main/resources/templates/allTrails/allTrails.html b/src/main/resources/templates/allTrails/allTrails.html index d29d1ad91cf459383b4681678742ed0a2cacbcd6..0fefa92c95a928454c100894149bf18340015baf 100644 --- a/src/main/resources/templates/allTrails/allTrails.html +++ b/src/main/resources/templates/allTrails/allTrails.html @@ -11,7 +11,7 @@ <body> <header th:replace="~{/fragments/Templating.html :: header}"></header> - +<div>TEST</div> <main> <section id="allTrailsBar" class="centerFlex"> <img class="trailsImages" diff --git a/src/main/resources/templates/fragments/Templating.html b/src/main/resources/templates/fragments/Templating.html index 871e541bd8767e721d139cedfa8dd193b5212987..e3afc23854e38d5973a596f44e8d546305b59b83 100644 --- a/src/main/resources/templates/fragments/Templating.html +++ b/src/main/resources/templates/fragments/Templating.html @@ -9,15 +9,15 @@ <li><a id="homeHead" href="/home">Home</a></li> <li>FAQs</li> <li>Contact us</li> + <li th:if="${#authentication.principal}!=anonymousUser"><a href="/logout">Log Out</a></li> + <li th:if="${#authentication.principal}==anonymousUser"><a href="/login">Log In</a></li> </ul> - <label class="work">Who we Work with:</label> - <select> - <ul> - <option value="localauthorities">Local Authorities</option> - <option value="towns">Towns</option> - <option value="businesses">Businesses</option> - <option value="consumers">Consumers</option> - </ul> + <label for="stakeholders" class="work">Who we Work with:</label> + <select id="stakeholders"> + <option value="localauthorities">Local Authorities</option> + <option value="towns">Towns</option> + <option value="businesses">Businesses</option> + <option value="consumers">Consumers</option> </select> </nav> </header> diff --git a/src/main/resources/templates/fragments/locationPageFrags.html b/src/main/resources/templates/fragments/locationPageFrags.html index 9cb90e48b97924a4bc53092a7aa86593d20bbf8a..ba7813ecf7e24927302cd49b1ca1523d959cae17 100644 --- a/src/main/resources/templates/fragments/locationPageFrags.html +++ b/src/main/resources/templates/fragments/locationPageFrags.html @@ -1,6 +1,5 @@ <!DOCTYPE html> <html lang="en" th:fragment="locationSection" class="locationPageFrag"> -<!-- todo check if this is ok here--> <head> <meta charset="UTF-8"> <title th:text="${location.getLocationName()}"></title> @@ -29,6 +28,8 @@ marginwidth="0" th:src="'https://maps.google.com/maps?q='+ ${locCoord.getLocationCoordsLat()} +','+ ${locCoord.getLocationCoordsLong()} +'&hl=en&z=20&output=embed'"> </iframe> + <H2 id="return"> + <a th:href="@{'/trails/'+${trail}}">Return</a></H2> </article> <hr style="height:40px; visibility:hidden;" /> diff --git a/src/main/resources/templates/fragments/trailsPageFrags.html b/src/main/resources/templates/fragments/trailsPageFrags.html new file mode 100644 index 0000000000000000000000000000000000000000..296cd2d153d1671b467a27a78f5a1994bdb77806 --- /dev/null +++ b/src/main/resources/templates/fragments/trailsPageFrags.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html lang="en" th:fragment="trailsSection" class="trailsPageFrag"> +<head> + <meta charset="UTF-8"> + <title th:text="${trail.getTrailName()}"></title> + + <link rel="stylesheet" th:href="@{/css/templatingstyle.css}"> + <link rel="stylesheet" th:href="@{/css/trailsPageFragsStyle.css}"> + + +</head> +<body > +<header th:insert="~{/fragments/Templating.html::header}"></header> +<main> + + <hr style="height:40px; visibility:hidden;" /> + <article class="trailsFragment"> + + <H1 th:text="*{trail.getTrailName()}" id="trailHeader"></H1> + + <div th:if="*{trail.getTrailName()=='Caerphilly Castle Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + src="https://www.google.com/maps/dir/51.57623,-3.21910/51.575372,-3.219186/51.576363,-3.220712//@11z"> + </iframe> + <div><a href="https://www.google.com/maps/dir/51.57623,-3.21910/51.575372,-3.219186/51.576363,-3.220712//@11z">Trail Map</a></div> + + </div> + + <div th:if="*{trail.getTrailName()=='Caerphilly Pub Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.57239,-3.21992/51.57230,-3.21938//@&hl=en&z=20&output=embed'"> + </iframe> + <div><a href="https://www.google.com/maps/dir/51.57239,-3.21992/51.57230,-3.21938//@11z">Trail Map</a></div> + + </div> + <div th:if="*{trail.getTrailName()=='Caerphilly Heritage Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.57168,-3.21861/51.57465,-3.22022//@11z'"> + </iframe> + <div> + <a href="https://www.google.com/maps/dir/51.57168,-3.21861/51.57465,-3.22022//@11z">Trail Map</a></div> + + </div> + <div th:if="*{trail.getTrailName()=='Risca Heritage Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.61117,-3.10198/51.61655,-3.12371 //@11z'"> + </iframe> + <div><a href="https://www.google.com/maps/dir/51.61117,-3.10198/51.61655,-3.12371 //@11z">Trail Map</a></div> + </div> + <div th:if="*{trail.getTrailName()=='Penarth Esplanade Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.43484,-3.16492/51.43547,-3.16789//@11z'"> + </iframe> + <div> + <a href="https://www.google.com/maps/dir/51.43484,-3.16492/51.43547,-3.16789//@11z">Trail Map</a> + </div> + </div> + <H3>Checkpoints:</H3> +<!-- With the trial name, we go through locations list to get --> + <div th:each="locationCoord, indexValue:${locCoords}" > + <div th:if="${locations[indexValue.index].getLocationTrailID()==trail.getTrailsId()}"> + <li id="checkpointList"> + <div><a th:href="'/checkpoints/'+${locations[indexValue.index].getLocationName().replace(' ', '-')}" th:text="${locations[indexValue.index].getLocationName()}"></a></div> + <ul></ul> + </li> + + + + + </div> + + + + + + + </div> + </article> + <hr style="height:40px; visibility:hidden;" /> +</main> + +<footer th:insert="~{/fragments/Templating.html::footer}"></footer> +</body> +</html> diff --git a/src/main/resources/templates/landmarks/LandmarkFormTh.html b/src/main/resources/templates/landmarks/LandmarkFormTh.html index 0f7879d8277ad1012ffefaae75fc49d70b6932ca..646632ce015eb3e16d14e7da06c604cc2ae10c5b 100644 --- a/src/main/resources/templates/landmarks/LandmarkFormTh.html +++ b/src/main/resources/templates/landmarks/LandmarkFormTh.html @@ -42,7 +42,7 @@ <select th:field="*{trailID}"> <option value=0 hidden="true">Select Trail</option> <option value=0 disabled selected>Select Trail</option> - <option value=0101>(Caerphilly) Castle Trail</option> + <option value=101>(Caerphilly) Castle Trail</option> <option value=0102>(Caerphilly) Pub Trail</option> <option value=0103>(Caerphilly) Heritage Trail</option> <option value=0201>(Risca) Heritage and Culture Trail</option> diff --git a/src/main/resources/templates/landmarks/trailsPage.html b/src/main/resources/templates/landmarks/trailsPage.html new file mode 100644 index 0000000000000000000000000000000000000000..4316d94fe409ebeba57db4005b31fbba6178bc70 --- /dev/null +++ b/src/main/resources/templates/landmarks/trailsPage.html @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Trails</title> + <link rel="stylesheet" th:href="@{/css/templatingstyle.css}"> +</head> +<body> +<header th:insert="~{/fragments/Templating.html::header}"></header> +<main> + <div th:each="trail, indexValue:${trails}"> + <H1 th:text="*{trail.getTrailName()}"></H1> + + <div th:if="*{trail.getTrailName()=='Caerphilly Castle Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + src="https://www.google.com/maps/dir/51.57623,-3.21910/51.575372,-3.219186/51.576363,-3.220712//@11z"> + </iframe> + + </div> + + <div th:if="*{trail.getTrailName()=='Caerphilly Pub Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.57239,-3.21992/51.57230,-3.21938//@11z'"> + </iframe> + + </div> + <div th:if="*{trail.getTrailName()=='Caerphilly Heritage Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.57168,-3.21861/51.57465,-3.22022//@11z'"> + </iframe> + + </div> + <div th:if="*{trail.getTrailName()=='Risca Heritage Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.61117,-3.10198/51.61655,-3.12371 //@11z'"> + </iframe> + + </div> + <div th:if="*{trail.getTrailName()=='Penarth Esplanade Trail'}"> + <iframe + width="600" + height="400" + frameborder="0" + scrolling="yes" + marginheight="0" + marginwidth="0" + th:src="'https://www.google.com/maps/dir/51.43484,-3.16492/51.43547,-3.16789//@11z'"> + </iframe> + + </div> + <H3>Checkpoints:</H3> + + <div th:each="locationCoord, indexValue2:${locationCoords}" > + <div th:if="${locations[indexValue2.index].getLocationTrailID()==trail.getTrailsId()}"> + <li style="list-style: none"> + <a th:href="'/checkpoints/'+${locations[indexValue2.index].getLocationName().replace(' ', '-')}" th:text="${locations[indexValue2.index].getLocationName()}"></a> + <ul></ul> + </li> + + + + + </div> + + + + + + + </div> +</main> +<footer th:insert="~{/fragments/Templating.html::footer}"></footer> +</body> +</html> \ No newline at end of file diff --git a/src/main/resources/templates/users/login.html b/src/main/resources/templates/users/login.html index 9c7aea8b67c0d18e2910b8c067ea576899fa6340..82f791b9acfff17bada66a547b3f2e3e7d79d29b 100644 --- a/src/main/resources/templates/users/login.html +++ b/src/main/resources/templates/users/login.html @@ -3,41 +3,71 @@ <head> <meta charset="UTF-8"> <title>User Log In</title> - <link rel="stylesheet" th:href="@{/css/userProfile.css}"> + <link rel="stylesheet" th:href="@{/css/style.css}"> + <link rel="stylesheet" th:href="@{/css/login.css}"> + <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <header> - <ul class="footerBar"> - <li class="footerButton"><b>Home</b></li> - <li class="footerButton"><b>About</b></li> - <li class="footerButton"><b>Map</b></li> - <li class="footerButton"><b>Facilities</b></li> - <li class="footerButton"><b>Log In</b></li> - </ul> + <form name="logoutForm" th:action="@{/logout}" method="post" th:hidden="false"> + <input hidden type="submit" value="Sign Out"/> + <button type="submit">CLICK ME OT LOG OUT</button> + </form> </header> -<main class="solidBg"> - <div class="loginWrapper"> - <form action="" onsubmit="return validateForm()" method="post" name="loginForm"> - <h2>Log In</h2> - <div class="label"> - <label for="username"><b>Username</b><br></label> - <div id="usernameInvalid" class="invalid-tooltip">Please fill out this field.</div> - </div> - <input type="text" name="username" id="username" placeholder="Enter Username" title="Username Input"> - <div class="label"> - <label for="password"><b>Password</b><br></label> - <div id="passwordInvalid" class="invalid-tooltip">Please fill out this field.</div> +<main> + <!--CODE MODIFIED FROM: https://github.com/AsmrProg-YT/Modern-Login --> + <div class="container sign-in"> + <div class="container" th:classappend="${status}" id="container"> + <div class="form-container sign-up"> + <form th:object="${user}" action="#" th:action="@{/login/register}" th:method="POST" onsubmit="return registerFormValidation()"> + <h1>Create Account</h1> + <div th:if="${error.equals('User exists')}" class="alert alert-error">User already exist</div> + <label> + <input class="input" th:field="*{name}" id="register-username" type="text" placeholder="Name"> + </label> + <label> + <input class="input" th:field="*{email}" id="register-email" type="email" placeholder="Email"> + </label> + <label> + <input class="input" th:field="*{password}" id="register-password" type="password" placeholder="Password"> + </label> + <button type="submit" >Sign Up</button> + </form> </div> - <input type="password" id="password" name="password"> - <div id="invalidLogin">Username and/or Password incorrect. Please try again.</div> - <button type="submit"><b>Log In</b></button> - </form> - + <div class="form-container sign-in"> + <form name="f" th:action="@{/login}" th:method="POST"> + <h1>Sign In</h1> + <div th:if="${param.error}" class="alert alert-error">Invalid Username or Password</div> + <label> + <input class="input" id="username" type="text" name="username" placeholder="Email"> + </label> + <label> + <input class="input" id="password" type="password" name="password" placeholder="Password"> + </label> + <a href="#" class="text">Forget Your Password?</a> + <button type="submit">Sign In</button> + </form> + </div> + <div class="toggle-container"> + <div class="toggle"> + <div class="toggle-panel toggle-left"> + <h1>Welcome Back!</h1> + <p>Enter your personal details and start tracking your landmarks!</p> + <button class="hidden" id="login">Sign In</button> + </div> + <div class="toggle-panel toggle-right"> + <div th:if="${param.logout}" class="alert alert-success">Successfully Logged out</div> + <h1 th:if="!${param.logout}">Hello, Welcome!</h1> + <p th:if="!${param.logout}">Register with your personal details and start earning stickers!</p> + <button class="hidden" id="register">Sign Up</button> + </div> + </div> + </div> + </div> </div> - </main> diff --git a/src/main/resources/templates/users/logout.html b/src/main/resources/templates/users/logout.html new file mode 100644 index 0000000000000000000000000000000000000000..69107ce66e4b6c4b3ed49219e191e5335de6d9a2 --- /dev/null +++ b/src/main/resources/templates/users/logout.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Logged Out Successfully</title> + <link rel="stylesheet" th:href="@{/css/style.css}"> + <link rel="stylesheet" th:href="@{/css/login.css}"> +</head> +<body> +<main> + <div class="container centerAll"> + <h1>You have successfully logged out</h1> + </div> +</main> + +</body> +</html> \ No newline at end of file diff --git a/src/main/resources/templates/users/userProfile.html b/src/main/resources/templates/users/userProfile.html index 3e865175760bc4b0aa11c9b54aade5d312ac55b5..edbe13918a53d466e7194ba42ff9dcf86bebdc56 100644 --- a/src/main/resources/templates/users/userProfile.html +++ b/src/main/resources/templates/users/userProfile.html @@ -3,6 +3,7 @@ <head> <meta charset="UTF-8"> <title th:text="'VZLA Profile Page of ' + ${user.getName()}"></title> + <link rel="stylesheet" th:href="@{/css/style.css}"> <link rel="stylesheet" th:href="@{/css/userProfile2.css}"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- <link rel="stylesheet" th:href="@{/css/templatingstyle.css}">--> @@ -38,7 +39,8 @@ <div th:each="pack : ${packs}" class="packContainer"> <img class="packImg" th:src="@{'../' + ${pack.getDisplayImg()}}" th:id="'packImg' + ${pack.getId()}" th:alt="${pack.getName()}" - th:onclick="'updatePack(' + ${user.getId()} +',' + ${pack.getId()} +');'"> + th:data-url="@{/packInfo/{username}/{packID}(username=${user.getName()}, packID=${pack.getId()})}" + onclick="updatePack(this.getAttribute('data-url'))"> <h4 class="packName" th:text="${pack.getName()}"></h4> </div> </div> diff --git a/src/test/java/Team5/SmartTowns/DataSourceConfig.java b/src/test/java/Team5/SmartTowns/DataSourceConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..568065a262e3a45668c889f8a8ddc6c1048bba01 --- /dev/null +++ b/src/test/java/Team5/SmartTowns/DataSourceConfig.java @@ -0,0 +1,19 @@ +package Team5.SmartTowns; + +import javax.sql.DataSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +@Configuration +public class DataSourceConfig { + + @Bean + public DataSource dataSource(){ + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setUrl("jdbc:mariadb://localhost:3306/test_towns"); + dataSource.setUsername("root"); + dataSource.setPassword("comsc"); + return dataSource; + } +} \ No newline at end of file diff --git a/src/test/java/Team5/SmartTowns/LocationRepositoryTest.java b/src/test/java/Team5/SmartTowns/LocationRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0c029bd95f7e372481c2a64c0aa2394b8794ff73 --- /dev/null +++ b/src/test/java/Team5/SmartTowns/LocationRepositoryTest.java @@ -0,0 +1,120 @@ +package Team5.SmartTowns; + +import Team5.SmartTowns.data.Location; +import Team5.SmartTowns.data.LocationRepository; + +import Team5.SmartTowns.data.TrailsRepository; +import Team5.SmartTowns.placeswithcoordinates.LocationsCoordinates; +import Team5.SmartTowns.placeswithcoordinates.PlacesCoordinatesRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringBootTest +public class LocationRepositoryTest { + + @Autowired + TrailsRepository trailsRepo; + @Autowired + LocationRepository locationRepository; + + + @Autowired + PlacesCoordinatesRepository placesRepository; + + @Autowired + JdbcTemplate jdbcTemplate; + + + +// @BeforeEach +// public void beforeEachTest(){ +// jdbcTemplate.update("DELETE FROM locations"); +// } + + @Test + public void testGetAllApprovedLocations() { + List<Location> approvedLocations = locationRepository.getAllApprovedLocations(); + List<Location> allLocations = locationRepository.getAllLocation(); + for (int i=0;i<allLocations.size();i++){ // iterate over all location, removing authorised=true + for (Location app : approvedLocations){ + if (Objects.equals(allLocations.get(i).getLocationName(), app.getLocationName())){ + allLocations.remove(allLocations.get(i)); + } + } + } boolean noApporvedLeft=false; + for (Location loc2: allLocations){ + if (loc2.isLocationApproved()){ + noApporvedLeft=false; + break; + } else{ + noApporvedLeft=true; + } + } assertTrue(noApporvedLeft); + } + + + @Test + public void testGetAllUnapprovedLocations() { + List<Location> unapprovedLocations = locationRepository.getAllUnapprovedLocations(); + List<Location> allLocations = locationRepository.getAllLocation(); + for (int i=0;i<allLocations.size();i++){ // iterate over all location, removing authorised=false + for (Location app : unapprovedLocations){ + if (Objects.equals(allLocations.get(i).getLocationName(), app.getLocationName())){ + allLocations.remove(allLocations.get(i)); + } + } + } boolean noUnapporvedLeft=false; + for (Location loc2: allLocations){ + if (!loc2.isLocationApproved()){ + noUnapporvedLeft=false; + break; + } else{ + noUnapporvedLeft=true; + } + } assertTrue(noUnapporvedLeft); + } + @Test + public void ensureApprovedLocationsAndCoordinatessAreTheSameSize(){ + List<Location> approvedLocations = locationRepository.getAllApprovedLocations(); + List<LocationsCoordinates> coordinatesLocations = placesRepository.getAllLocationCoords(); + assertSame(approvedLocations.size(),coordinatesLocations.size() ); + + } + + + @Test + public void ensureApprovedLocationsAndCoordinatessTableLineUpTest(){ + List<Location> approvedLocations = locationRepository.getAllApprovedLocations(); + List<LocationsCoordinates> coordinatesLocations = placesRepository.getAllLocationCoords(); + List<Integer> coordinatesLocationsID = new ArrayList<>(); + boolean doTheyMatch=false; + for (int i=0;i<coordinatesLocations.size();i++){ + int locID=coordinatesLocations.get(i).getLocationID(); + String coordName = jdbcTemplate.queryForObject("SELECT locationName FROM locations WHERE locationID=?", String.class, locID); + + if (Objects.equals(coordName, approvedLocations.get(i).getLocationName())){ + doTheyMatch=true; + } else{ + doTheyMatch=false; + break; + } + // for loop goes through entire list, if there were any discrepancies, the loop would break, resulting in a fail + + + } assertTrue(doTheyMatch); + } +} diff --git a/src/test/java/Team5/SmartTowns/SmartTownsApplicationTests.java b/src/test/java/Team5/SmartTowns/SmartTownsApplicationTests.java index 47c720ca72fd244fb90d1b14109856674f6e399d..4b281aab3e06da893c6862fda7dd47b2b3c54e65 100644 --- a/src/test/java/Team5/SmartTowns/SmartTownsApplicationTests.java +++ b/src/test/java/Team5/SmartTowns/SmartTownsApplicationTests.java @@ -1,46 +1,73 @@ //package Team5.SmartTowns; // +//import Team5.SmartTowns.data.DatabaseController; +//import Team5.SmartTowns.data.Location; +//import Team5.SmartTowns.data.LocationRepository; +//import Team5.SmartTowns.data.LocationRepositoryJDBC; +//import Team5.SmartTowns.landmarks.Landmarks; +//import org.junit.jupiter.api.BeforeAll; //import org.junit.jupiter.api.Test; +//import org.mockito.InjectMocks; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +//import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; //import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.jdbc.core.JdbcTemplate; // -//@SpringBootTest +//import static org.junit.jupiter.api.Assertions.assertEquals; +// +//import java.lang.annotation.Inherited; +//import java.util.List; +// +// +// +//@DataJpaTest +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +////@SpringBootTest //class SmartTownsApplicationTests { // +// @Autowired +// private LocationRepository locationRepository; +// +// // @Test // void contextLoads() { // } // -//} -// -////// test2 -//// public void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount1() { -//// DataSource dataSource = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) -//// .addScript("classpath:jdbc/schema.sql") -//// .addScript("classpath:jdbc/test-data.sql") -//// .build(); -//// -//// LocationRepositoryJDBC employeeDAO = new LocationRepositoryJDBC(); -//// employeeDAO.setDataSource(dataSource); -//// -//// assertEquals(4, employeeDAO.getCountOfEmployees());} -//// -//// @Test -////// test 1 -//// void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount() { -//// LocationRepositoryJDBC employeeDAO = new LocationRepositoryJDBC(ajdbc); -////// employeeDAO.setJdbcTemplate(ajdbc); -//// assertEquals(4, employeeDAO.getAllLocation().size()); -//// -////// assertEquals(4, employeeDAO.getCountOfEmployees()); -//// }} -////// @Test -////// void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount() { -////// EmployeeDAO employeeDAO = new EmployeeDAO(); -////// employeeDAO.setJdbcTemplate(jdbcTemplate); -////// -////// assertEquals(4, employeeDAO.getCountOfEmployees()); -////// } -//// +// @Test +// void test(){ +// Location location = new Location(); +// location.setLocationName("Test"); +// location.setLocationEmail("test@test"); +// location.setLocationDescription("Description Here"); +// location.setLocationPlace("Caerphilly"); +// location.setLocationTrailID("0103"); +// location.setLocationApproved(false); +// +// int locSize1 = locationRepository.getAllLocation().size(); +// locationRepository.addLocation(location); +// int locSize2 = locationRepository.getAllLocation().size(); +// assertEquals(1, (locSize2-locSize1)); +// +// +// } +// +// +// +// +// +//// private static Location location; +//// private static locationRepositoryJDBC locationRepo; +//// private static JdbcTemplate jdbc; +//// @BeforeAll +//// public static void before() { +//// location = new Location(); +//// locationRepo = new locationRepositoryJDBC(jdbc);} +//// @BeforeAll +//// public static void before2() { +//// locationRepo = new locationRepositoryJDBC(jdbc); } +//// @Autowired +//// private locationRepository locationRepository; // //// @Test //// public void whenAddingLocationsNonApprovedLocationsDontShowInTrails(){ @@ -61,3 +88,5 @@ ////// assertEquals(1,( ApprovedNumber.size()-ApprovedNumberAfter.size())); //// } // } +// +//// create test where getFullListLocations and getFullApproved/Unapporved lcopations from lcoationcooirds matches locationJDBC diff --git a/src/test/java/Team5/SmartTowns/TrailsRepositoryTest.java b/src/test/java/Team5/SmartTowns/TrailsRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c0d8d91555c8a68955b49b61ba78c2589f7a507e --- /dev/null +++ b/src/test/java/Team5/SmartTowns/TrailsRepositoryTest.java @@ -0,0 +1,44 @@ +package Team5.SmartTowns; + +import Team5.SmartTowns.data.LocationRepository; +import Team5.SmartTowns.data.TrailsRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +@SpringBootTest +public class TrailsRepositoryTest { + @Autowired + TrailsRepository trailsRepo; + + @Autowired + JdbcTemplate jdbcTemplate; + + @Test + public void getTrailNameWithIDTest(){ + String trailsID="101"; + String trailName= trailsRepo.getTrailNameWithID(trailsID); + assertEquals("Caerphilly Castle Trail",trailName); + trailsID="102"; + trailName= trailsRepo.getTrailNameWithID(trailsID); + assertEquals("Caerphilly Pub Trail",trailName); + trailsID="103"; + trailName= trailsRepo.getTrailNameWithID(trailsID); + assertEquals("Caerphilly Heritage Trail",trailName); + trailsID="201"; + trailName= trailsRepo.getTrailNameWithID(trailsID); + assertEquals("Risca Heritage Trail",trailName); + trailsID="301"; + trailName= trailsRepo.getTrailNameWithID(trailsID); + assertEquals("Penarth Esplanade Trail",trailName); + } // test whether function works correctly for all instances + + + + +} diff --git a/src/test/java/Team5/SmartTowns/data/LocationRepositoryJDBCTest.java b/src/test/java/Team5/SmartTowns/data/LocationRepositoryJDBCTest.java new file mode 100644 index 0000000000000000000000000000000000000000..73792324a036bc848146988f73abe5bbc9a268c2 --- /dev/null +++ b/src/test/java/Team5/SmartTowns/data/LocationRepositoryJDBCTest.java @@ -0,0 +1,44 @@ +//package Team5.SmartTowns.data; +// +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.core.RowMapper; +// +//@SpringBootTest +//class LocationRepositoryJDBCTest { +// private JdbcTemplate jdbcTemplate; +// private LocationRepositoryJDBC locationRepositoryJDBC; +// +// private RowMapper<Location> locationMapper; +// +// +// @Autowired +// public void setlocationMapper(){ +// locationMapper = (rs, i) -> new Location( +// +// rs.getString("locationName"), +// rs.getString("locationEmail"), +// rs.getString("locationDescription"), +// rs.getString("locationPlace"), +// rs.getString("locationTrailID"), +// rs.getBoolean("locationApproved") +// ); +// } +// @Autowired +// public void LocationRepositoryJDBC(JdbcTemplate jdbc){ +// this.jdbcTemplate = jdbc; +// locationRepositoryJDBC = new LocationRepositoryJDBC(jdbc); +// } +// +// +// +// +// @Test +// public void test(){ +// +// } +// +// +//} \ No newline at end of file diff --git a/src/test/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesTest.java b/src/test/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..933541d774f1666db611121fd72377a02c73c78c --- /dev/null +++ b/src/test/java/Team5/SmartTowns/placeswithcoordinates/PlacesCoordinatesTest.java @@ -0,0 +1,82 @@ +package Team5.SmartTowns.placeswithcoordinates; + +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringBootTest +class PlacesCoordinatesTest { + + @Autowired + PlacesCoordinatesRepository placesCoordinatesRepository; + + @Autowired + JdbcTemplate jdbcTemplate; + + @BeforeEach + void setUp() { + /* Ensures that each test starts with a clean table*/ + jdbcTemplate.update("DELETE FROM locationCoordinates"); + } + + @AfterEach + void tearDown() { + jdbcTemplate.update("DELETE FROM locationCoordinates"); + } + + @Test + void getAllLocationCoords() { + jdbcTemplate.update("insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (2, 51.57623, -3.21910 )"); + jdbcTemplate.update("insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (3, 51.57623, -3.21910 )"); + jdbcTemplate.update("insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (4, 51.57623, -3.21910 )"); + + List<Long> expected = jdbcTemplate.queryForList("SELECT locationID FROM locationcoordinates", Long.class); + List<LocationsCoordinates> allObjects = placesCoordinatesRepository.getAllLocationCoords(); + assertEquals(expected.size(), allObjects.size()); + assertEquals(expected.get(0), allObjects.get(0).getLocationID()); + assertEquals(expected.get(1), allObjects.get(1).getLocationID()); + assertEquals(expected.get(2), allObjects.get(2).getLocationID()); + } + + @Test + void getAllTownCoords() { + } + + @Test + void addLocationCoord() { + int locationID = 1; + double locationCoordsLat = 1.5; + double locationCoordsLong = 1.5; + placesCoordinatesRepository.addLocationCoord( + new LocationsCoordinates(1, locationCoordsLat, locationCoordsLong) + ); + + double resultLat = jdbcTemplate.queryForObject( + "SELECT locationCoordsLat FROM locationcoordinates WHERE locationID=?", + Double.class, locationID); + double resultLong = jdbcTemplate.queryForObject( + "SELECT locationCoordsLat FROM locationcoordinates WHERE locationID=?", + Double.class, locationID); + + + + assertEquals(locationCoordsLat, resultLat); + assertEquals(locationCoordsLong, resultLong); + } + + + @Test + void getFullApprovedLocations() { + + } + + @Test + void getLocationTableIDValue() { + } +} \ No newline at end of file diff --git a/src/test/java/Team5/SmartTowns/testUsers.java b/src/test/java/Team5/SmartTowns/testUsers.java new file mode 100644 index 0000000000000000000000000000000000000000..2145c47165ed072b8a4c3478774da7410f881414 --- /dev/null +++ b/src/test/java/Team5/SmartTowns/testUsers.java @@ -0,0 +1,79 @@ +package Team5.SmartTowns; + +import Team5.SmartTowns.rewards.RewardsRepository; +import Team5.SmartTowns.users.NewUser; +import Team5.SmartTowns.users.User; +import Team5.SmartTowns.users.UserRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.TestCase.*; + +@SpringBootTest +public class testUsers { + + + @Autowired + UserRepository userRepository; + @Autowired + RewardsRepository rewardsRepository; + + @Test + public void getAllUsersTest(){ // test if we can get all users, admin is sa known user + List<User> users = userRepository.getAllUsers(); + User user = new User("Admin","Admin"); + Assertions.assertEquals("Admin", users.get(0).getName()); + } + + @Test // test if new users can be added + public void addAUserTest(){ + int userNumberBeforeAdd = userRepository.getAllUsers().size(); + NewUser newuser = new NewUser("Meow","Woof","Cat@Dogs.com"); + boolean trueIfAdded= userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword()); + int userNumberAfterAdd = userRepository.getAllUsers().size(); + assertTrue(trueIfAdded); + } + + @Test // test if new users and inserted users can be found + public void doesUserExistTest(){ + Boolean insertedUserFoundByEmail = userRepository.doesUserExist("Kevin@Gmail.com"); + NewUser newuser = new NewUser("MeowMeow","WoofMeow","CatMeow@Dogs.com"); + Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword()); + Boolean newUserFoundByEmail = userRepository.doesUserExist(newuser.getEmail()); + int compareTwoSearches = Boolean.compare(insertedUserFoundByEmail, newUserFoundByEmail); + assertEquals(0,compareTwoSearches); // if 0, both values are the same + + + } + + @Test + public void canUsersUnlockStickersTest(){ + NewUser newuser = new NewUser("MeowMeowMeow","WoofMeowMeow","CatMeowMeow@Dogs.com"); + Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword()); + Boolean doesStickerUnlock = userRepository.unlockSticker(newuser.getName(),2,2); + System.out.println(doesStickerUnlock); + assertTrue(doesStickerUnlock); + } + @Test + public void canUsersUnlockStickersAndViewThemTest(){ + NewUser newuser = new NewUser("MeowMeowMeowMeow","WoofMeowMeowMeow","CatMeowMeowMeow@Dogs.com"); + NewUser newuserTwo = new NewUser("Jumper","Baa","Sheep@Wool.com"); + Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword()); + Boolean newUserTwo = userRepository.addUser(newuserTwo.getName(), newuserTwo.getEmail(), newuserTwo.getPassword()); + Boolean doesStickerUnlock = userRepository.unlockSticker(newuser.getName(),1,2); + List<Long> newUserStickerCollection = userRepository.getUserStickersFromPack(newuser.getName(),1); + List<Long> newUserStickerCollectionTwo = userRepository.getUserStickersFromPack(newuserTwo.getName(),1); // compare and see if only new suer that has unlocked a sticker ahs one in their collection for pack 1 + int newUserStickerList = newUserStickerCollection.size(); + int newUserStickerListTwo = newUserStickerCollectionTwo.size(); // should have different sizes + assertNotSame(newUserStickerList,newUserStickerListTwo); + + } + + +} diff --git a/src/test/java/testTwo.java b/src/test/java/testTwo.java new file mode 100644 index 0000000000000000000000000000000000000000..225fb28724e8c0dc26ba5ad295dd166b52498969 --- /dev/null +++ b/src/test/java/testTwo.java @@ -0,0 +1,52 @@ +////package Team5.SmartTowns.data; +// +////import org.junit.platform.commons.util.Preconditions; +//// +//import Team5.SmartTowns.data.Location; +//import Team5.SmartTowns.data.LocationRepository; +//import Team5.SmartTowns.data.LocationRepositoryJDBC; +//import org.junit.jupiter.api.BeforeAll; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.core.RowMapper; +// +//import static org.junit.jupiter.api.Assertions.assertEquals; +// +// +////@SpringBootTest +//public class testTwo { +// +//private JdbcTemplate jdbcTemplate; +//private LocationRepositoryJDBC locationRepositoryJDBC; +// +//private RowMapper<Location> locationMapper; +// +//@Autowired +//private LocationRepository locationRepository; +// +// +//@Autowired +// public void LocationRepositoryJDBC(JdbcTemplate jdbc){ +// this.jdbcTemplate = jdbc; +// locationRepositoryJDBC = new LocationRepositoryJDBC(jdbc); +//} +// +// +//@BeforeAll +//public static void setUp(){ +// locationRepository = new LocationRepositoryJDBC.getAllLocation(); +//// locationRepository = (LocationRepositoryJDBC) locationRepository.getAllLocation(); +//} +// +//@Test +//public void test(){ +// int aa=1; +// assertEquals(1,aa); +// +// } +// +// +// +//} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000000000000000000000000000000000000..83f47c5db5a7390e1ab3dadf4882c3ddf1e3b4ea --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,8 @@ +spring.datasource.url=jdbc:mariadb://localhost:3306/ +spring.datasource.username=root +spring.datasource.password=comsc + +spring.sql.init.mode=always +spring.sql.init.platform=test +spring.sql.init.schema-locations=classpath:schema-test.sql +spring.sql.init.data-locations=classpath:test-data.sql \ No newline at end of file diff --git a/src/test/resources/data.sql b/src/test/resources/data.sql new file mode 100644 index 0000000000000000000000000000000000000000..c2259e46e52a7b84e4dabf968a3c315118ff253a --- /dev/null +++ b/src/test/resources/data.sql @@ -0,0 +1,74 @@ +# delete from users; +# insert into users (email, name) value ('hannah@gmail.com', 'Hannah'); +# insert into users (email, name) value ('nigel@gmail.com', 'Nigel'); +# +# +# insert into trails ( trailID, trailName, trailNumber) value ( 0101,'Caerphilly Castle Trail','0101'); +# insert into trails ( trailID, trailName, trailNumber) value ( 0102,'Caerphilly Pub Trail','0102'); +# insert into trails ( trailID, trailName, trailNumber) value ( 0103,'Caerphilly Heritage Trail','0103'); +# insert into trails ( trailID, trailName, trailNumber) value ( 0201,'Risca Heritage Trail','0201'); +# insert into trails ( trailID, trailName, trailNumber) value ( 0301,'Penarth Esplanade Trail','0301'); +# +# +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Castle','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Medieval Trades','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Queen''s War','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, true); +# +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'JD Wetherspoons-Malcolm Uphill','','Location description here','Caerphilly',0102, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Cwtch','','Location description here','Caerphilly',0102, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, true); +# +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Bus Station','','Location description here','Caerphilly',0103, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Medieval Courthouse','','Location description here','Caerphilly',0103, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Risca Colliery','','Location description here','Risca',0201, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Esplanade','','Location description here','Penarth',0301, true); +# insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301, true); +# +# +# +# insert into packs (name, description) value ('Wales Football Team', 'Pack of Welsh Football Players in the National Team'); +# insert into packs (name, description) value ('Wales Rugby Team', 'Pack of Welsh Rugby Players in the National Team'); +# insert into packs (name, description) value ('Welsh Heritage', 'Pack About Welsh Heritage'); +# +# +# +# insert into stickers (packID, stickerID, name, description, rarity) value (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2'); +# insert into stickers (packID, stickerID, name, description, rarity) value (1, 2, 'neco_williams', 'Wales Football Team Player', '2'); +# insert into stickers (packID, stickerID, name, description, rarity) value (1, 3, 'joe_morrell', 'Wales Football Team Player', '2'); +# insert into stickers (packID, stickerID, name, description, rarity) value (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2'); +# insert into stickers (packID, stickerID, name, description, rarity) value (1, 5, 'connor_roberts', 'Wales Football Team Player', '2'); +# insert into stickers (packID, stickerID, name, description, rarity) value (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (3, 1, 'Welsh Lady', 'Welsh Heritage', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (3, 2, 'Welsh Outline', 'Welsh Heritage', '1'); +# insert into stickers (packID, stickerID, name, description, rarity) value (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1'); +# +# +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (2, 51.57623, -3.21910 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (3, 51.575372, -3.219186); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (4, 51.576363, -3.220712 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (9, 51.57239, -3.21992); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (10, 51.57230, -3.21938 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (13, 51.57168, -3.21861); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (14, 51.57465, -3.22022 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (17, 51.61117, -3.10198 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (18, 51.61655, -3.12371 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (19, 51.43484, -3.16492 ); +# insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (20, 51.43547, -3.16789 ); +# +# +# insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Caerphilly', '51.57903','-3.22075 ','51.60418','51.55093','-3.25222','-3.17696'); +# insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Risca','51.61195','-3.09648','51.63039','51.59175','-3.12129','-3.06438'); +# insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Penarth','51.43893','-3.17354','51.44878','51.41233','-3.20271','-3.16005'); \ No newline at end of file diff --git a/src/test/resources/schema-test.sql b/src/test/resources/schema-test.sql new file mode 100644 index 0000000000000000000000000000000000000000..60304bee1fb5f57502846d60fea88d90713c1735 --- /dev/null +++ b/src/test/resources/schema-test.sql @@ -0,0 +1,121 @@ + + + + +DROP DATABASE IF EXISTS test_towns; +CREATE DATABASE IF NOT EXISTS test_towns; +USE test_towns; +/****************************************************************/ + +/* DROPS ALL TABLES IF THEY EXIST (they wont but just in case) */ + +drop table if exists locationCoordinates; +drop table if exists locations; +drop table if exists trails; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS stickers; +DROP TABLE IF EXISTS packs; +DROP TABLE IF EXISTS stickerProgress; + + + +/****************************************************************/ + +/* CREATES ALL TABLES */ + +create table if not exists trails +( + trailID varchar(128) primary key, + trailName varchar(128), + trailNumber varchar(128) +) engine=InnoDB; + +drop table if exists locationCoordinates; +drop table if exists locations; +create table if not exists locations +( + locationID bigint auto_increment primary key, + locationName varchar(128), + locationEmail varchar(128), + locationDescription longtext, + locationPlace varchar(255), + locationTrailID varchar(128), + locationApproved boolean +) engine=InnoDB; + + +CREATE TABLE IF NOT EXISTS users ( + username varchar(30) primary key NOT NULL, + id bigint auto_increment unique, /*DEPRECATED COLUMN, LEFT IN WHILE SOME OTHER FUNCTIONS STILL USE IT*/ + email varchar(128), + password varchar(30) NOT NULL, + enabled boolean default true +); + +CREATE TABLE IF NOT EXISTS authorities ( + id bigint primary key auto_increment NOT NULL, + username varchar(30) NOT NULL , + authority varchar(45) NOT NULL +); + +CREATE TABLE IF NOT EXISTS packs ( + id bigint auto_increment primary key, + name varchar(20) NOT NULL, + description text +); + +CREATE TABLE IF NOT EXISTS stickers ( + id bigint auto_increment primary key, + packID bigint NOT NULL, + FOREIGN KEY (packID) REFERENCES packs(id) + ON DELETE CASCADE + ON UPDATE RESTRICT, + stickerID bigint NOT NULL, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/ + name varchar(30) NOT NULL, + description text NOT NULL, + rarity tinyint +); +CREATE TABLE IF NOT EXISTS stickerProgress ( + id bigint auto_increment primary key, + username varchar(30) NOT NULL, + FOREIGN KEY (username) REFERENCES users(username) + ON DELETE CASCADE + ON UPDATE RESTRICT, + packID bigint NOT NULL, + FOREIGN KEY (packID) REFERENCES packs(id) + ON DELETE CASCADE + ON UPDATE RESTRICT, + stickerID bigint NOT NULL, + FOREIGN KEY (stickerID) REFERENCES stickers(id) + ON DELETE CASCADE + ON UPDATE RESTRICT +); + +create table if not exists locationCoordinates +( + locationCoordID bigint auto_increment primary key, + locationID bigint, + Foreign Key (locationID) REFERENCES locations(locationID) + ON DELETE CASCADE + ON UPDATE RESTRICT, + locationCoordsLat DECIMAL(8,6), + locationCoordsLong DECIMAL(8,6) + + +)engine=InnoDB; + + +drop table if exists townsWithTrails; +create table if not exists townsWithTrails +( + townID bigint auto_increment primary key, + townName varchar(128), + townCentreCoordsLat varchar(128), + townCentreCoordsLong varchar(128), + townUppermostCoordsLat varchar(128), + townLowermostCoordsLat varchar(128), + townLeftmostCoordsLong varchar(128), + townRightmostCoordsLong varchar(128) + +)engine=InnoDB; + diff --git a/src/test/resources/schema.sql b/src/test/resources/schema.sql new file mode 100644 index 0000000000000000000000000000000000000000..70cf59c3ea7e21770133191348ff79616c78622a --- /dev/null +++ b/src/test/resources/schema.sql @@ -0,0 +1,108 @@ +# DROP DATABASE test_towns; +# CREATE DATABASE test_towns; +# USE test_towns; +# +# +# drop table if exists locationCoordinates; +# drop table if exists locations; +# drop table if exists trails; +# +# create table if not exists trails +# ( +# trailID varchar(128) primary key, +# trailName varchar(128), +# trailNumber varchar(128) +# ) engine=InnoDB; +# +# +# create table if not exists locations +# ( +# locationID bigint auto_increment primary key, +# locationName varchar(128), +# locationEmail varchar(128), +# locationDescription longtext, +# locationPlace varchar(255), +# locationTrailID varchar(128), +# Foreign Key (locationTrailID) REFERENCES trails(trailID) +# ON DELETE CASCADE +# ON UPDATE RESTRICT, +# locationApproved boolean +# ) engine=InnoDB; +# +# +# drop table if exists users; +# drop table if exists stickers; +# drop table if exists packs; +# drop table if exists stickerProgress; +# +# create table if not exists users +# ( +# id bigint auto_increment primary key, +# email varchar(128), +# name varchar(30), +# dragonProgress int, +# dragonsLandmarkIDs longtext +# ) engine=InnoDB; +# +# +# create table if not exists packs +# ( +# id bigint auto_increment primary key, +# name varchar(20), +# description text +# ) engine=InnoDB; +# +# create table if not exists stickers +# ( +# id bigint auto_increment primary key, +# packID bigint, +# FOREIGN KEY (packID) REFERENCES packs(id) +# ON DELETE CASCADE +# ON UPDATE RESTRICT, +# stickerID bigint, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/ +# name varchar(30), +# description text, +# rarity tinyint +# +# ) engine=InnoDB; +# +# create table if not exists stickerProgress +# ( +# id bigint auto_increment primary key, +# userID bigint, +# stickerID bigint +# ) engine=InnoDB; +# +# +# +# +# +# create table if not exists locationCoordinates +# ( +# locationCoordID bigint auto_increment primary key, +# locationID bigint, +# Foreign Key (locationID) REFERENCES locations(locationID) +# ON DELETE CASCADE +# ON UPDATE RESTRICT, +# locationCoordsLat DECIMAL(8,6), +# locationCoordsLong DECIMAL(8,6) +# +# +# )engine=InnoDB; +# +# +# drop table if exists townsWithTrails; +# create table if not exists townsWithTrails +# ( +# townID bigint auto_increment primary key, +# townName varchar(128), +# townCentreCoordsLat varchar(128), +# townCentreCoordsLong varchar(128), +# townUppermostCoordsLat varchar(128), +# townLowermostCoordsLat varchar(128), +# townLeftmostCoordsLong varchar(128), +# townRightmostCoordsLong varchar(128) +# +# )engine=InnoDB; +# +# diff --git a/src/test/resources/test-data.sql b/src/test/resources/test-data.sql new file mode 100644 index 0000000000000000000000000000000000000000..f2e5430167e4ec54f04063fc60dd41c28d216b0a --- /dev/null +++ b/src/test/resources/test-data.sql @@ -0,0 +1,104 @@ +# delete from users; +# insert into users (email, name) value ('hannah@gmail.com', 'Hannah'); +# insert into users (email, name) value ('nigel@gmail.com', 'Nigel'); + +delete from trails; +insert into trails ( trailID, trailName, trailNumber) value ( 0101,'Caerphilly Castle Trail','0101'); +insert into trails ( trailID, trailName, trailNumber) value ( 0102,'Caerphilly Pub Trail','0102'); +insert into trails ( trailID, trailName, trailNumber) value ( 0103,'Caerphilly Heritage Trail','0103'); +insert into trails ( trailID, trailName, trailNumber) value ( 0201,'Risca Heritage Trail','0201'); +insert into trails ( trailID, trailName, trailNumber) value ( 0301,'Penarth Esplanade Trail','0301'); + +delete from locations; +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Castle','','Location description here','Caerphilly',0101, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Medieval Trades','','Location description here','Caerphilly',0101, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Queen''s War','','Location description here','Caerphilly',0101, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, false); + +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'JD Wetherspoons-Malcolm Uphill','','Location description here','Caerphilly',0102, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Cwtch','','Location description here','Caerphilly',0102, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, false); + +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Bus Station','','Location description here','Caerphilly',0103, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Medieval Courthouse','','Location description here','Caerphilly',0103, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, false); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, false); + +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Risca Colliery','','Location description here','Risca',0201, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201, true); + +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Esplanade','','Location description here','Penarth',0301, true); +insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301, true); + +DELETE FROM locationCoordinates; +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (2, 51.57623, -3.21910 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (3, 51.575372, -3.219186); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (4, 51.576363, -3.220712 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (9, 51.57239, -3.21992); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (10, 51.57230, -3.21938 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (13, 51.57168, -3.21861); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (14, 51.57465, -3.22022 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (17, 51.61117, -3.10198 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (18, 51.61655, -3.12371 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (19, 51.43484, -3.16492 ); +insert into locationCoordinates(locationID, locationCoordsLat, locationCoordsLong) value (20, 51.43547, -3.16789 ); + +# delete from badges; +# insert into badges (name, description, difficulty) value ('TownConnoisseur', 'You know the town very well!', '2'); +# insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1'); +# insert into badges (name, description, difficulty) value ('TownMaster', 'You visited the town 7 days in a row!', '1'); +# insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1'); +# insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1'); + + + +delete from packs; +insert into packs (name, description) value ('Wales Football Team', 'Pack of Welsh Football Players in the National Team'); +insert into packs (name, description) value ('Wales Rugby Team', 'Pack of Welsh Rugby Players in the National Team'); +insert into packs (name, description) value ('Welsh Heritage', 'Pack About Welsh Heritage'); + + +DELETE FROM stickers; +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 2, 'neco_williams', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 3, 'joe_morrell', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 5, 'connor_roberts', 'Wales Football Team Player', '2'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 1, 'Welsh Lady', 'Welsh Heritage', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 2, 'Welsh Outline', 'Welsh Heritage', '1'); +INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1'); + +# delete from stickerprogress; +# insert into stickerprogress (userID, stickerID, hasSticker) value ('1', '1', true); +# insert into stickerprogress (userID, stickerID, hasSticker) value ('1', '3', true); +# insert into stickerprogress (userID, stickerID, hasSticker) value ('2', '2', true); + + + + + + +# insert into stickerprogress (userID, packID, stickerID) value (1, 1, 1); +# insert into stickerprogress (userID, packID, stickerID) value (1, 1, 2); +# insert into stickerprogress (userID, packID, stickerID) value (1, 1, 3); +# insert into stickerprogress (userID, packID, stickerID) value (1, 1, 5); +# insert into stickerprogress (userID, packID, stickerID) value (1, 2, 1); +# insert into stickerprogress (userID, packID, stickerID) value (1, 2, 3); + + + +# +delete from townsWithTrails; +insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Caerphilly', '51.57903','-3.22075 ','51.60418','51.55093','-3.25222','-3.17696'); +insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Risca','51.61195','-3.09648','51.63039','51.59175','-3.12129','-3.06438'); +insert into townsWithTrails (townName, townCentreCoordsLat, townCentreCoordsLong, townUppermostCoordsLat, townLowermostCoordsLat, townLeftmostCoordsLong, townRightmostCoordsLong) value ('Penarth','51.43893','-3.17354','51.44878','51.41233','-3.20271','-3.16005'); \ No newline at end of file