diff --git a/src/main/java/org/springframework/samples/petclinic/model/Visit.java b/src/main/java/org/springframework/samples/petclinic/model/Visit.java index a418c17a7..004c836d7 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/Visit.java +++ b/src/main/java/org/springframework/samples/petclinic/model/Visit.java @@ -15,6 +15,7 @@ */ package org.springframework.samples.petclinic.model; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.format.annotation.DateTimeFormat; @@ -42,7 +43,7 @@ public class Visit extends BaseEntity { */ @Column(name = "visit_date") @Temporal(TemporalType.TIMESTAMP) - @DateTimeFormat(pattern = "yyyy/MM/dd") + @JsonFormat(pattern = "yyyy-MM-dd") private Date date; /** diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java deleted file mode 100644 index 705ed2b5c..000000000 --- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.samples.petclinic.web; - -import java.util.Map; - -import javax.validation.Valid; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.samples.petclinic.model.Pet; -import org.springframework.samples.petclinic.model.Visit; -import org.springframework.samples.petclinic.service.ClinicService; -import org.springframework.stereotype.Controller; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.InitBinder; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -/** - * @author Juergen Hoeller - * @author Ken Krebs - * @author Arjen Poutsma - * @author Michael Isvy - */ -@Controller -public class VisitController { - - private final ClinicService clinicService; - - - @Autowired - public VisitController(ClinicService clinicService) { - this.clinicService = clinicService; - } - - @InitBinder - public void setAllowedFields(WebDataBinder dataBinder) { - dataBinder.setDisallowedFields("id"); - } - - /** - * Called before each and every @RequestMapping annotated method. - * 2 goals: - * - Make sure we always have fresh data - * - Since we do not use the session scope, make sure that Pet object always has an id - * (Even though id is not part of the form fields) - * @param petId - * @return Pet - */ - @ModelAttribute("visit") - public Visit loadPetWithVisit(@PathVariable("petId") int petId) { - Pet pet = this.clinicService.findPetById(petId); - Visit visit = new Visit(); - pet.addVisit(visit); - return visit; - } - - // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called - @GetMapping("/owners/*/pets/{petId}/visits/new") - public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { - return "pets/createOrUpdateVisitForm"; - } - - // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called - @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new") - public String processNewVisitForm(@Valid Visit visit, BindingResult result) { - if (result.hasErrors()) { - return "pets/createOrUpdateVisitForm"; - } else { - this.clinicService.saveVisit(visit); - return "redirect:/owners/{ownerId}"; - } - } - - @GetMapping("/owners/*/pets/{petId}/visits") - public String showVisits(@PathVariable int petId, Map model) { - model.put("visits", this.clinicService.findPetById(petId).getVisits()); - return "visitList"; - } - -} diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java b/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java new file mode 100644 index 000000000..68798f79b --- /dev/null +++ b/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.samples.petclinic.web; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * @author Juergen Hoeller + * @author Ken Krebs + * @author Arjen Poutsma + * @author Michael Isvy + */ +@RestController +public class VisitResource { + + private final ClinicService clinicService; + + @Autowired + public VisitResource(ClinicService clinicService) { + this.clinicService = clinicService; + } + + @PostMapping("/owners/{ownerId}/pets/{petId}/visits") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void create( + @Valid @RequestBody Visit visit, + @PathVariable("petId") int petId) { + + clinicService.findPetById(petId).addVisit(visit); + clinicService.saveVisit(visit); + } + + @GetMapping("/owners/{ownerId}/pets/{petId}/visits") + public Object visits(@PathVariable("petId") int petId) { + return clinicService.findPetById(petId).getVisits(); + } +} diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 63775e3c4..874e05b49 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -12,13 +12,13 @@ - + diff --git a/src/main/webapp/scripts/app/app.js b/src/main/webapp/scripts/app/app.js index b92458025..660076158 100644 --- a/src/main/webapp/scripts/app/app.js +++ b/src/main/webapp/scripts/app/app.js @@ -2,7 +2,7 @@ /* App Module */ var petClinicApp = angular.module('petClinicApp', [ 'ngRoute', 'layoutNav', 'layoutFooter', 'layoutWelcome', - 'ownerList', 'ownerDetails', 'ownerForm','petForm', 'vetList']); + 'ownerList', 'ownerDetails', 'ownerForm', 'petForm', 'visits', 'vetList']); petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) { @@ -22,26 +22,18 @@ petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationP template: '' }).when('/owners/:ownerId/pets/:petId', { template: '' + }).when('/owners/:ownerId/pets/:petId/visits', { + template: '' }).when('/vets', { template: '' }).otherwise('/welcome'); }]); -angular.module('layoutWelcome', []); - -angular.module("layoutWelcome").component("layoutWelcome", { - templateUrl: "scripts/app/fragments/welcome.html" -}); - -angular.module('layoutNav', []); - -angular.module("layoutNav").component("layoutNav", { - templateUrl: "scripts/app/fragments/nav.html" -}); - -angular.module('layoutFooter', []); - -angular.module("layoutFooter").component("layoutFooter", { - templateUrl: "scripts/app/fragments/footer.html" +['welcome', 'nav', 'footer'].forEach(function(c) { + var mod = 'layout' + c.toUpperCase().substring(0, 1) + c.substring(1); + angular.module(mod, []); + angular.module(mod).component(mod, { + templateUrl: "scripts/app/fragments/" + c + ".html" + }); }); \ No newline at end of file diff --git a/src/main/webapp/scripts/app/fragments/nav.html b/src/main/webapp/scripts/app/fragments/nav.html index f6722423a..7dd8cded7 100644 --- a/src/main/webapp/scripts/app/fragments/nav.html +++ b/src/main/webapp/scripts/app/fragments/nav.html @@ -19,7 +19,7 @@ diff --git a/src/main/webapp/scripts/app/fragments/welcome.html b/src/main/webapp/scripts/app/fragments/welcome.html index a91aa92e9..8ff4bbe0b 100644 --- a/src/main/webapp/scripts/app/fragments/welcome.html +++ b/src/main/webapp/scripts/app/fragments/welcome.html @@ -1 +1,3 @@ -

Welcome to Petclinic

+

Welcome to Petclinic

+ + pets logo \ No newline at end of file diff --git a/src/main/webapp/scripts/app/owner-details/owner-details.template.html b/src/main/webapp/scripts/app/owner-details/owner-details.template.html index 293ce831f..78220f5db 100644 --- a/src/main/webapp/scripts/app/owner-details/owner-details.template.html +++ b/src/main/webapp/scripts/app/owner-details/owner-details.template.html @@ -29,41 +29,22 @@

Pets and Visits

- - - - - -
-
-
Name
-
{{pet.name}}
-
Birth Date
-
{{pet.birthDate | date:'MM/dd/yyyy'}}
-
Type
-
{{pet.type.name}}
-
-
- - - - - - - - - - - - - - - -
Visit DateDescription
{{visit.date | date:'MM/dd/yyyy'}}{{visit.description}}
- Edit Pet - - Add Visit -
-
+
+

{{pet.name}}

+

+ {{pet.birthDate | date:'yyyy MMM dd'}} - {{pet.type.name}} +

+

Visits

+

+ {{visit.date | date:'yyyy MMM dd'}} + {{visit.description}} +

+ +

+ No visit yet +

+ +
+
diff --git a/src/main/webapp/scripts/app/owner-list/OwnerController.js b/src/main/webapp/scripts/app/owner-list/OwnerController.js deleted file mode 100644 index 6f2cddc0c..000000000 --- a/src/main/webapp/scripts/app/owner-list/OwnerController.js +++ /dev/null @@ -1,110 +0,0 @@ -'use strict'; - -function loadOwner($scope, $resource, $stateParams) { - var ownerResource = $resource('/petclinic/owner/' + $stateParams.id); - $scope.owner = ownerResource.get(); -} - -/* - * Owner Search - */ -angular.module('controllers').controller('ownerSearchController', ['$scope', '$state', - function($scope, $state) { - - $scope.ownerSearchForm = {}; - // form always needs to be initialised - // otherwise we can't read $scope.ownerSearchForm.lastName - - $scope.submitOwnerSearchForm = function() { - var lastNameValue; - $state.go('app.ownerlist', {lastName: $scope.ownerSearchForm.lastName}); -}}]); - -/* - * Owners List - */ -angular.module('controllers').controller('ownerListController', ['$scope', '$resource', '$stateParams', - function($scope, $resource, $stateParams) { - - var destUrl = '/petclinic/owner/list?lastName='; - if(angular.isDefined($stateParams.lastName)) { - destUrl += $stateParams.lastName; - } - var ownerResource = $resource(destUrl); - $scope.ownerList = ownerResource.query(); -}]); - -/* - * Owners detail (used for both Editable and non-editable pages) - */ -angular.module('controllers').controller('ownerDetailController', ['$scope', '$resource', '$stateParams', - loadOwner -]); - - - -/* - * Form used to create and edit owners - */ -angular.module('controllers').controller('ownerFormController', ['$scope', '$http', '$resource', '$stateParams', '$state', -function($scope, $http, $resource, $stateParams, $state) { - - $scope.submitOwnerForm = {}; - - $scope.submitOwnerForm = function() { - var form = $scope.owner; - - // Creating a Javascript object - var data = { - firstName: form.firstName, - lastName: form.lastName, - address: form.address, - city: form.city, - telephone: form.telephone - }; - - var request; - - if ($state.current.name == 'app.owneredit') { - var restUrl = "/petclinic/owner/" + $stateParams.id; - request = $http.put(restUrl, data); - } else { // in case of owner creation - var restUrl = "/petclinic/owner"; - request = $http.post(restUrl, data); - } - - request.then(function () { - $state.go('app.ownerlist'); - }, function (response) { - var error = response.data; - alert(error.error + "\r\n" + error.errors.map(function (e) { - return e.field + ": " + e.defaultMessage; - }).join("\r\n")); - }); - - } - - if ($state.current.name == 'app.owneredit') { - loadOwner($scope, $resource, $stateParams); - } - -}]); - - - - - - - - - - - - - - - - - - - diff --git a/src/main/webapp/scripts/app/owner-list/ownerDetail.html b/src/main/webapp/scripts/app/owner-list/ownerDetail.html deleted file mode 100644 index 45a7b9fdd..000000000 --- a/src/main/webapp/scripts/app/owner-list/ownerDetail.html +++ /dev/null @@ -1,75 +0,0 @@ -
- -

Owner Information

- - - - - - - - - - - - - - - - - - - - - - -
Name{{owner.firstName}} {{owner.lastName}}
Address{{owner.address}}
City{{owner.city}}
Telephone{{owner.telephone}}
- Edit Owner - Add New Pet -
- -

Pets and Visits

- - - - - - -
-
-
Name
-
{{pet.name}}
-
Birth Date
-
{{pet.birthDate | date:'MM/dd/yyyy'}}
-
Type
-
{{pet.type.name}}
-
-
- - - - - - - - - - - - - - - -
Visit DateDescription
{{visit.date | date:'MM/dd/yyyy'}}{{visit.description}}
- Edit Pet - - - - - - Add Visit -
-
- - -
diff --git a/src/main/webapp/scripts/app/owner-list/ownerForm.html b/src/main/webapp/scripts/app/owner-list/ownerForm.html deleted file mode 100644 index 38177f549..000000000 --- a/src/main/webapp/scripts/app/owner-list/ownerForm.html +++ /dev/null @@ -1,45 +0,0 @@ -
-

Owner

-
-
- -
- - First name is required. -
-
-
- -
- - Last name is required. -
-
-
- -
- - Address is required. -
-
-
- -
- - City is required. -
-
-
- -
- - Telephone is required. -
-
-
-
- -
-
-
-
diff --git a/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html b/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html deleted file mode 100644 index 4cd2fac2d..000000000 --- a/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html +++ /dev/null @@ -1,9 +0,0 @@ -

Owners

-
-
- - - | - Add New Owner -
-
\ No newline at end of file diff --git a/src/main/webapp/scripts/app/pet-form/pet-form.component.js b/src/main/webapp/scripts/app/pet-form/pet-form.component.js index 36b766ba8..3de2b735a 100644 --- a/src/main/webapp/scripts/app/pet-form/pet-form.component.js +++ b/src/main/webapp/scripts/app/pet-form/pet-form.component.js @@ -16,9 +16,10 @@ angular.module("petForm").component("petForm", { var petId = $routeParams.petId || 0; - if (petId) { + if (petId) { // edit $http.get("owner/" + ownerId + "/pet/" + petId).then(function(resp) { self.pet = resp.data; + self.pet.birthDate = new Date(self.pet.birthDate); self.petTypeId = "" + self.pet.type.id; }); } else { @@ -26,6 +27,7 @@ angular.module("petForm").component("petForm", { self.pet = { owner: resp.data.firstName + " " + resp.data.lastName }; + self.petTypeId = "1"; }) } @@ -54,6 +56,7 @@ angular.module("petForm").component("petForm", { $location.url("owners/" + ownerId); }, function (response) { var error = response.data; + error.errors = error.errors || []; alert(error.error + "\r\n" + error.errors.map(function (e) { return e.field + ": " + e.defaultMessage; }).join("\r\n")); diff --git a/src/main/webapp/scripts/app/pet-form/pet-form.template.html b/src/main/webapp/scripts/app/pet-form/pet-form.template.html index 8811960a3..a502b8ebe 100644 --- a/src/main/webapp/scripts/app/pet-form/pet-form.template.html +++ b/src/main/webapp/scripts/app/pet-form/pet-form.template.html @@ -1,6 +1,6 @@

Pet

-
+
@@ -19,7 +19,7 @@
- + birth date is required.
@@ -35,7 +35,7 @@
-
diff --git a/src/main/webapp/scripts/app/pet/PetController.js b/src/main/webapp/scripts/app/pet/PetController.js deleted file mode 100644 index a454a4448..000000000 --- a/src/main/webapp/scripts/app/pet/PetController.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -function loadPet($scope, $resource, $stateParams) { - var petResource = $resource('/petclinic/owner/' + $stateParams.ownerid +"/pet/" + $stateParams.petid); - $scope.pet = petResource.get(); - $scope.types = $resource("/petclinic/petTypes").query(); -} - -/* - * Form used to create and edit pets - */ -angular.module('controllers').controller('petFormController', ['$scope', '$http', '$resource', '$stateParams', '$state', -function($scope, $http, $resource, $stateParams, $state) { - - $scope.submitPetForm = {}; - - $scope.submitPetForm = function() { - var form = $scope.pet; - - // Creating a Javascript object - var data = { - name: form.name, - birthDate: form.birthDate, - type: form.type - }; - - if ($state.current.name == 'app.petedit') { - var restUrl = "/petclinic/owner/" + $stateParams.ownerid +"/pet/" +$stateParams.petid; - $http.put(restUrl, data); - $state.go('app.ownerdetail'); - } - else { // in case of pet creation - var restUrl = "/petclinic/owner/" + $stateParams.ownerid +"/pet"; - $http.post(restUrl, data); - $state.go('app.ownerdetail'); - } - } - - if ($state.current.name == 'app.petedit') { - loadPet($scope, $resource, $stateParams); - } - -}]); - - - - - - - - - - - - - - - - - - - diff --git a/src/main/webapp/scripts/app/pet/petForm.html b/src/main/webapp/scripts/app/pet/petForm.html deleted file mode 100644 index a1a090738..000000000 --- a/src/main/webapp/scripts/app/pet/petForm.html +++ /dev/null @@ -1,38 +0,0 @@ -
- -

Pet

- - -
- -
-

{{pet.owner}}

-
-
- -
- -
- - Name is required. -
-
- -
- -
- - birth date is required. -
-
- -
- -
- -
-
- -
diff --git a/src/main/webapp/scripts/app/visits/visits.component.js b/src/main/webapp/scripts/app/visits/visits.component.js new file mode 100644 index 000000000..706b4823c --- /dev/null +++ b/src/main/webapp/scripts/app/visits/visits.component.js @@ -0,0 +1,34 @@ +'use strict'; + +angular.module('visits', [ + 'ngRoute' +]); + +angular.module("visits").component("visits", { + templateUrl: "/petclinic/scripts/app/visits/visits.template.html", + controller: ["$http", '$routeParams', '$location', '$filter', function ($http, $routeParams, $location, $filter) { + var self = this; + var petId = $routeParams.petId || 0; + var url = "owners/" + ($routeParams.ownerId || 0) + "/pets/" + petId + "/visits"; + self.date = new Date(); + self.desc = ""; + + $http.get(url).then(function(resp) { + self.visits = resp.data; + }); + + self.submit = function() { + + var data = { + date : $filter('date')(self.date, "yyyy-MM-dd"), + description : self.desc + }; + console.log(data); + $http.post(url, data).then(function() { + $location.url("owners/" + $routeParams.ownerId); + }, function() { + + }); + }; + }] +}); \ No newline at end of file diff --git a/src/main/webapp/scripts/app/visits/visits.template.html b/src/main/webapp/scripts/app/visits/visits.template.html new file mode 100644 index 000000000..fa27dad28 --- /dev/null +++ b/src/main/webapp/scripts/app/visits/visits.template.html @@ -0,0 +1,27 @@ +

Visits

+ +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +

Previous Visits

+ + + + + +
{{v.date}}{{v.description}}
\ No newline at end of file