mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-17 21:15:50 +00:00
redesign owner details page
This commit is contained in:
parent
3510dbfc45
commit
15129c32c3
18 changed files with 162 additions and 499 deletions
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.model;
|
package org.springframework.samples.petclinic.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
@ -42,7 +43,7 @@ public class Visit extends BaseEntity {
|
||||||
*/
|
*/
|
||||||
@Column(name = "visit_date")
|
@Column(name = "visit_date")
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
@DateTimeFormat(pattern = "yyyy/MM/dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private Date date;
|
private Date date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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<String, Object> 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<String, Object> model) {
|
|
||||||
model.put("visits", this.clinicService.findPetById(petId).getVisits());
|
|
||||||
return "visitList";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,13 +12,13 @@
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-resource.min.js"></script>
|
|
||||||
|
|
||||||
<script src="scripts/app/app.js"></script>
|
<script src="scripts/app/app.js"></script>
|
||||||
<script src="scripts/app/owner-list/owner-list.component.js"></script>
|
<script src="scripts/app/owner-list/owner-list.component.js"></script>
|
||||||
<script src="scripts/app/owner-details/owner-details.component.js"></script>
|
<script src="scripts/app/owner-details/owner-details.component.js"></script>
|
||||||
<script src="scripts/app/owner-form/owner-form.component.js"></script>
|
<script src="scripts/app/owner-form/owner-form.component.js"></script>
|
||||||
<script src="scripts/app/pet-form/pet-form.component.js"></script>
|
<script src="scripts/app/pet-form/pet-form.component.js"></script>
|
||||||
|
<script src="scripts/app/visits/visits.component.js"></script>
|
||||||
<script src="scripts/app/vet-list/vet-list.component.js"></script>
|
<script src="scripts/app/vet-list/vet-list.component.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/* App Module */
|
/* App Module */
|
||||||
var petClinicApp = angular.module('petClinicApp', [
|
var petClinicApp = angular.module('petClinicApp', [
|
||||||
'ngRoute', 'layoutNav', 'layoutFooter', 'layoutWelcome',
|
'ngRoute', 'layoutNav', 'layoutFooter', 'layoutWelcome',
|
||||||
'ownerList', 'ownerDetails', 'ownerForm','petForm', 'vetList']);
|
'ownerList', 'ownerDetails', 'ownerForm', 'petForm', 'visits', 'vetList']);
|
||||||
|
|
||||||
petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
|
petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
|
||||||
|
|
||||||
|
@ -22,26 +22,18 @@ petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationP
|
||||||
template: '<pet-form></pet-form>'
|
template: '<pet-form></pet-form>'
|
||||||
}).when('/owners/:ownerId/pets/:petId', {
|
}).when('/owners/:ownerId/pets/:petId', {
|
||||||
template: '<pet-form></pet-form>'
|
template: '<pet-form></pet-form>'
|
||||||
|
}).when('/owners/:ownerId/pets/:petId/visits', {
|
||||||
|
template: '<visits></visits>'
|
||||||
}).when('/vets', {
|
}).when('/vets', {
|
||||||
template: '<vet-list></vet-list>'
|
template: '<vet-list></vet-list>'
|
||||||
}).otherwise('/welcome');
|
}).otherwise('/welcome');
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
angular.module('layoutWelcome', []);
|
['welcome', 'nav', 'footer'].forEach(function(c) {
|
||||||
|
var mod = 'layout' + c.toUpperCase().substring(0, 1) + c.substring(1);
|
||||||
angular.module("layoutWelcome").component("layoutWelcome", {
|
angular.module(mod, []);
|
||||||
templateUrl: "scripts/app/fragments/welcome.html"
|
angular.module(mod).component(mod, {
|
||||||
});
|
templateUrl: "scripts/app/fragments/" + c + ".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"
|
|
||||||
});
|
});
|
|
@ -19,7 +19,7 @@
|
||||||
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Owners <span class="caret"></span></a>
|
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Owners <span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#!/owners">All</a></li>
|
<li><a href="#!/owners">All</a></li>
|
||||||
<li><a href="#!/new-owner">New</a></li>
|
<li><a href="#!/new-owner">Register</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
<p>Welcome to Petclinic </p>
|
<h1>Welcome to Petclinic</h1>
|
||||||
|
|
||||||
|
<img src="resources/images/pets.png" alt="pets logo" />
|
|
@ -29,41 +29,22 @@
|
||||||
|
|
||||||
<h2>Pets and Visits</h2>
|
<h2>Pets and Visits</h2>
|
||||||
|
|
||||||
<table class="table" style="width:600px;">
|
<div ng-repeat="pet in $ctrl.owner.pets">
|
||||||
<tr ng-repeat="pet in $ctrl.owner.pets">
|
<h3>{{pet.name}}</h3>
|
||||||
<td valign="top" style="width: 120px;">
|
<p>
|
||||||
<dl class="dl-horizontal">
|
{{pet.birthDate | date:'yyyy MMM dd'}} - {{pet.type.name}}
|
||||||
<dt>Name</dt>
|
</p>
|
||||||
<dd>{{pet.name}}</dd>
|
<h4>Visits</h4>
|
||||||
<dt>Birth Date</dt>
|
<p style="margin-left: 2em;" ng-repeat="visit in pet.visits">
|
||||||
<dd>{{pet.birthDate | date:'MM/dd/yyyy'}}</dd>
|
<span style="font-style: italic; margin-right: 1em;">{{visit.date | date:'yyyy MMM dd'}}</span>
|
||||||
<dt>Type</dt>
|
{{visit.description}}
|
||||||
<dd>{{pet.type.name}}</dd>
|
</p>
|
||||||
</dl>
|
|
||||||
</td>
|
<p style="margin-left: 2em;" ng-if="pet.visits.length == 0">
|
||||||
<td valign="top">
|
No visit yet
|
||||||
<table class="table-condensed">
|
</p>
|
||||||
<thead>
|
|
||||||
<tr>
|
<hr/>
|
||||||
<th>Visit Date</th>
|
</div>
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr ng-repeat="visit in pet.visits">
|
|
||||||
<td>{{visit.date | date:'MM/dd/yyyy'}}</td>
|
|
||||||
<td>{{visit.description}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a href="#!/owners/{{$ctrl.owner.id}}/pets/{{pet.id}}">Edit Pet</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="...">Add Visit</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<h2>Owner Information</h2>
|
|
||||||
|
|
||||||
<table class="table table-striped" style="width:600px;">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<td><b>{{owner.firstName}} {{owner.lastName}}</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Address</th>
|
|
||||||
<td>{{owner.address}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>City</th>
|
|
||||||
<td>{{owner.city}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Telephone</th>
|
|
||||||
<td>{{owner.telephone}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a class="btn btn-info" ui-sref="app.owneredit({id: owner.id})">Edit Owner</a></td>
|
|
||||||
<td>
|
|
||||||
<a ui-sref="app.petcreate({ownerid: owner.id})" class="btn btn-success">Add New Pet</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2>Pets and Visits</h2>
|
|
||||||
|
|
||||||
<table class="table" style="width:600px;">
|
|
||||||
<tr ng-repeat="pet in owner.pets">
|
|
||||||
<td valign="top" style="width: 120px;">
|
|
||||||
<dl class="dl-horizontal">
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{pet.name}}</dd>
|
|
||||||
<dt>Birth Date</dt>
|
|
||||||
<dd>{{pet.birthDate | date:'MM/dd/yyyy'}}</dd>
|
|
||||||
<dt>Type</dt>
|
|
||||||
<dd>{{pet.type.name}}</dd>
|
|
||||||
</dl>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<table class="table-condensed">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Visit Date</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr ng-repeat="visit in pet.visits">
|
|
||||||
<td>{{visit.date | date:'MM/dd/yyyy'}}</td>
|
|
||||||
<td>{{visit.description}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a ui-sref="app.petedit( {ownerid: owner.id, petid: pet.id})">Edit Pet</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<spring:url value="/owners/{ownerId}/pets/{petId}/visits/new" var="visitUrl">
|
|
||||||
<spring:param name="ownerId" value="${owner.id}"/>
|
|
||||||
<spring:param name="petId" value="${pet.id}"/>
|
|
||||||
</spring:url>
|
|
||||||
<a href="${fn:escapeXml(visitUrl)}">Add Visit</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<div class="container">
|
|
||||||
<h2>Owner</h2>
|
|
||||||
<form class="form-horizontal" name="ownerForm" data-ng-controller="ownerFormController">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">First name</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<input class="form-control" ng-model="owner.firstName" name="firstName" required/>
|
|
||||||
<span ng-show="ownerForm.firstName.$error.required" class="help-inline">First name is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Last name</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<input class="form-control" ng-model="owner.lastName" name="lastName" required/>
|
|
||||||
<span ng-show="ownerForm.lastName.$error.required" class="help-inline">Last name is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Address</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<input class="form-control" ng-model="owner.address" name="address" required/>
|
|
||||||
<span ng-show="ownerForm.address.$error.required" class="help-inline">Address is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">City</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<input class="form-control" ng-model="owner.city" name="city" required/>
|
|
||||||
<span ng-show="ownerForm.city.$error.required" class="help-inline">City is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Telephone</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<input class="form-control" ng-model="owner.telephone" name="telephone" required/>
|
|
||||||
<span ng-show="ownerForm.telephone.$error.required" class="help-inline">Telephone is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-offset-2 col-sm-4">
|
|
||||||
<button class="btn btn-primary" type="submit" ng-click="submitOwnerForm()">Submit</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<h2>Owners</h2>
|
|
||||||
<form class="form-inline" ng-controller="ownerSearchController">
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label">Last name</label>
|
|
||||||
<input class="form-control" type="text" ng-model="ownerSearchForm.lastName" size="30" maxlength="80"/>
|
|
||||||
<button class="btn btn-info" type="submit" ng-click="submitOwnerSearchForm()">Find Owners</button> |
|
|
||||||
<a class="btn btn-info" ui-sref="app.ownercreate">Add New Owner</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -16,9 +16,10 @@ angular.module("petForm").component("petForm", {
|
||||||
|
|
||||||
var petId = $routeParams.petId || 0;
|
var petId = $routeParams.petId || 0;
|
||||||
|
|
||||||
if (petId) {
|
if (petId) { // edit
|
||||||
$http.get("owner/" + ownerId + "/pet/" + petId).then(function(resp) {
|
$http.get("owner/" + ownerId + "/pet/" + petId).then(function(resp) {
|
||||||
self.pet = resp.data;
|
self.pet = resp.data;
|
||||||
|
self.pet.birthDate = new Date(self.pet.birthDate);
|
||||||
self.petTypeId = "" + self.pet.type.id;
|
self.petTypeId = "" + self.pet.type.id;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,6 +27,7 @@ angular.module("petForm").component("petForm", {
|
||||||
self.pet = {
|
self.pet = {
|
||||||
owner: resp.data.firstName + " " + resp.data.lastName
|
owner: resp.data.firstName + " " + resp.data.lastName
|
||||||
};
|
};
|
||||||
|
self.petTypeId = "1";
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -54,6 +56,7 @@ angular.module("petForm").component("petForm", {
|
||||||
$location.url("owners/" + ownerId);
|
$location.url("owners/" + ownerId);
|
||||||
}, function (response) {
|
}, function (response) {
|
||||||
var error = response.data;
|
var error = response.data;
|
||||||
|
error.errors = error.errors || [];
|
||||||
alert(error.error + "\r\n" + error.errors.map(function (e) {
|
alert(error.error + "\r\n" + error.errors.map(function (e) {
|
||||||
return e.field + ": " + e.defaultMessage;
|
return e.field + ": " + e.defaultMessage;
|
||||||
}).join("\r\n"));
|
}).join("\r\n"));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<h2>Pet</h2>
|
<h2>Pet</h2>
|
||||||
|
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal" ng-submit="$ctrl.submit()">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">Owner</label>
|
<label class="col-sm-2 control-label">Owner</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">Birth date</label>
|
<label class="col-sm-2 control-label">Birth date</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<input class="form-control" ng-model="$ctrl.pet.birthDate" value="{{pet.birthDate}}" required type="text"/>
|
<input class="form-control" ng-model="$ctrl.pet.birthDate" required type="date"/>
|
||||||
<span ng-show="petForm.name.$error.required" class="help-inline"> birth date is required.</span>
|
<span ng-show="petForm.name.$error.required" class="help-inline"> birth date is required.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-6 col-sm-offset-2">
|
<div class="col-sm-6 col-sm-offset-2">
|
||||||
<button class="btn btn-primary" type="submit" ng-click="$ctrl.submit()">
|
<button class="btn btn-primary" type="submit">
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<h2>Pet</h2>
|
|
||||||
|
|
||||||
<form class="form-horizontal" name="petForm" data-ng-controller="petFormController">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Owner</label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<p class="form-control-static">{{pet.owner}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Name </label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<input class="form-control col-sm-4" ng-model="pet.name" name="name" required type="text"/>
|
|
||||||
<span ng-show="petForm.name.$error.required" class="help-inline"> Name is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Birth date </label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<input class="form-control" ng-model="pet.birthDate" value="{{pet.birthDate}}" required type="text"/>
|
|
||||||
<span ng-show="petForm.name.$error.required" class="help-inline"> birth date is required.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label">Type </label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<select class="form-control" ng-model="pet.type.id">
|
|
||||||
<option ng-repeat="x in types" value="{{x.id}}">{{x.name}}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
34
src/main/webapp/scripts/app/visits/visits.component.js
Normal file
34
src/main/webapp/scripts/app/visits/visits.component.js
Normal file
|
@ -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() {
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
});
|
27
src/main/webapp/scripts/app/visits/visits.template.html
Normal file
27
src/main/webapp/scripts/app/visits/visits.template.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<h2>Visits</h2>
|
||||||
|
|
||||||
|
<form ng-submit="$ctrl.submit()">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Date</label>
|
||||||
|
<input type="date" class="form-control" ng-model='$ctrl.date'/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Description</label>
|
||||||
|
<textarea class="form-control" ng-model="$ctrl.desc" style="resize:vertical;" required></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-primary" type="submit">Add New Visit</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h3>Previous Visits</h3>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr ng-repeat="v in $ctrl.visits">
|
||||||
|
<td class="col-sm-2">{{v.date}}</td>
|
||||||
|
<td>{{v.description}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
Loading…
Reference in a new issue