Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(CSTM-CPC-976)Add a pet to an Owner #527

Merged
merged 9 commits into from
Oct 9, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

Check warning on line 14 in api-gateway/src/main/java/com/petclinic/bffapigateway/domainclientlayer/CustomersServiceClient.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Unused import

Unused import `import org.springframework.web.bind.annotation.RequestParam;`
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
Expand Down Expand Up @@ -100,7 +100,7 @@
.bodyValue(model)
.retrieve()
.bodyToMono(OwnerResponseDTO.class);
// return webClientBuilder.build()

Check notice on line 103 in api-gateway/src/main/java/com/petclinic/bffapigateway/domainclientlayer/CustomersServiceClient.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (8 lines)
// .post()
// .uri(customersServiceUrl + "/owners")
// .accept(MediaType.APPLICATION_JSON)
Expand Down Expand Up @@ -140,14 +140,14 @@

public Flux<PetResponseDTO> getPetsByOwnerId(final String ownerId) {
return webClientBuilder.build().get()
.uri(customersServiceUrl + "/pet/owner/" + ownerId + "/pets")
.uri(customersServiceUrl + "/pet/owner/" + ownerId)
.retrieve()
.bodyToFlux(PetResponseDTO.class);
}

public Mono<PetResponseDTO> createPet(PetResponseDTO model, final String ownerId) {
return webClientBuilder.build().post()
.uri(customersServiceUrl + "{ownerId}/pets", ownerId)
.uri(customersServiceUrl + "/pet", ownerId)
.body(just(model), PetResponseDTO.class)
.accept(MediaType.APPLICATION_JSON)
.retrieve().bodyToMono(PetResponseDTO.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class PetRequestDTO {
private String name;
private Date birthDate;
private String petTypeId;
private String photoId;
//private String photoId;
private String isActive;

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

/**
* @author Maciej Szarlinski
* Copied from https://github.com/spring-petclinic/spring-petclinic-microservices

Check warning on line 12 in api-gateway/src/main/java/com/petclinic/bffapigateway/dtos/Pets/PetResponseDTO.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Link specified as plain text

Link specified as plain text
*/
@Builder
@AllArgsConstructor
Expand All @@ -22,7 +22,7 @@
private String name;
private Date birthDate;
private String petTypeId;
private String photoId;
//private String photoId;
private String isActive;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
/**
* @author Maciej Szarlinski
* @author Christine Gerard
* Copied from https://github.com/spring-petclinic/spring-petclinic-microservices

Check warning on line 37 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Link specified as plain text

Link specified as plain text
* Modified to remove circuitbreaker
*/

Expand Down Expand Up @@ -147,13 +147,13 @@


@IsUserSpecific(idToMatch = {"customerId"}, bypassRoles = {Roles.ADMIN,Roles.VET})
@PostMapping(value = "owners/{ownerId}/pets" , produces = "application/json", consumes = "application/json")
@PostMapping(value = "/owners/{ownerId}/pets" , produces = "application/json", consumes = "application/json")
public Mono<ResponseEntity<PetResponseDTO>> createPet(@RequestBody PetResponseDTO pet, @PathVariable String ownerId){
return customersServiceClient.createPet(pet, ownerId).map(s -> ResponseEntity.status(HttpStatus.CREATED).body(s))
.defaultIfEmpty(ResponseEntity.badRequest().build());
}

/*@GetMapping(value = "owners/{ownerId}/pets")

Check notice on line 156 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (4 lines)
public Flux<PetResponseDTO> getAllPetsFromOwnerId(@PathVariable String ownerId){
return customersServiceClient.getAllPets(ownerId);
}*/
Expand Down Expand Up @@ -278,7 +278,7 @@
.defaultIfEmpty(ResponseEntity.notFound().build());
}
// @PutMapping(value = "owners/*/pets/{petId}/visits/{visitId}", consumes = "application/json", produces = "application/json")
/*

Check notice on line 281 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (33 lines)
Mono<ResponseEntity<VisitDetails>> updateVisit(@RequestBody VisitDetails visit, @PathVariable String petId, @PathVariable String visitId) {
visit.setPetId(petId);
visit.setVisitId(visitId);
Expand Down Expand Up @@ -321,7 +321,7 @@
.defaultIfEmpty(ResponseEntity.badRequest().build());
}

// @PutMapping(value = "owners/*/pets/{petId}/visits/{visitId}", consumes = "application/json", produces = "application/json")

Check notice on line 324 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (7 lines)
// Mono<ResponseEntity<VisitDetails>> updateVisit(@RequestBody VisitDetails visit, @PathVariable String petId, @PathVariable String visitId) {
// visit.setPetId(petId);
// visit.setVisitId(visitId);
Expand All @@ -330,7 +330,7 @@
// }
/* End of Visit Methods */

/**

Check warning on line 333 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Dangling Javadoc comment

Dangling Javadoc comment
* End of Visit Methods
**/

Expand Down Expand Up @@ -465,7 +465,7 @@

@IsUserSpecific(idToMatch = {"vetId"})
@GetMapping("/vets/vetBillId/{vetId}")
public Mono<ResponseEntity<VetDTO>> getVetByVetBillId(@PathVariable String vetBillId) {

Check notice on line 468 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Mismatch in @PathVariable declarations and usages

Path variable 'vetId' is not consumed

Check warning on line 468 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Mismatch in @PathVariable declarations and usages

Cannot resolve path variable 'vetBillId' in request mapping
return vetsServiceClient.getVetByVetBillId(VetsEntityDtoUtil.verifyId(vetBillId))
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
Expand Down Expand Up @@ -504,10 +504,10 @@
.defaultIfEmpty(ResponseEntity.notFound().build());
}

/**

Check warning on line 507 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Dangling Javadoc comment

Dangling Javadoc comment
* End of Vet Methods
**/
//

Check notice on line 510 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (16 lines)
// @DeleteMapping(value = "users/{userId}")
// public Mono<UserDetails> deleteUser(@RequestHeader(AUTHORIZATION) String auth, final @PathVariable long userId) {
// return authServiceClient.deleteUser(auth, userId);
Expand Down Expand Up @@ -576,7 +576,7 @@
}


// @PostMapping(value = "owners",

Check notice on line 579 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (6 lines)
// consumes = "application/json",
// produces = "application/json")
// public Mono<OwnerResponseDTO> createOwner(@RequestBody OwnerResponseDTO model){
Expand All @@ -590,12 +590,12 @@
.defaultIfEmpty(ResponseEntity.badRequest().build());
}

/*@GetMapping(value = "owners/photo/{ownerId}")

Check notice on line 593 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (4 lines)
public Mono<PhotoDetails> getOwnerPhoto(@PathVariable int ownerId) {
return customersServiceClient.getOwnerPhoto(ownerId);
}*/

// @PostMapping(value = "owners/{ownerId}/pet/photo/{petId}")

Check notice on line 598 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (19 lines)
// public Mono<String> setPetPhoto(@PathVariable String ownerId, @RequestBody PhotoDetails photoDetails, @PathVariable String petId) {
// return customersServiceClient.setPetPhoto(ownerId, photoDetails, petId);
// }
Expand All @@ -619,7 +619,7 @@



/*

Check notice on line 622 in api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/BFFApiGatewayController.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Commented out code

Commented out code (9 lines)

// Endpoint to update an owner
@PutMapping("owners/{ownerId}")
Expand Down
4 changes: 4 additions & 0 deletions api-gateway/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@
<script src="scripts/auth/reset-pwd-form/reset-pwd-form.controller.js"></script>
<script src="scripts/auth/reset-pwd-form/reset-pwd-form.component.js"></script>

<script src="scripts/pet-register/pet-register.js"></script>
<script src="scripts/pet-register/pet-register.controller.js"></script>
<script src="scripts/pet-register/pet-register.component.js"></script>

<script src="scripts/inventory-list/inventory-service.js"></script>


Expand Down
2 changes: 1 addition & 1 deletion api-gateway/src/main/resources/static/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const whiteList = new Set([

/* App Module */
const petClinicApp = angular.module('petClinicApp', [
'ui.router', 'layoutNav', 'layoutFooter', 'layoutWelcome', 'ownerList', 'ownerDetails', 'ownerForm', 'ownerRegister', 'petForm'
'ui.router', 'layoutNav', 'layoutFooter', 'layoutWelcome', 'ownerList', 'ownerDetails', 'ownerForm', 'ownerRegister', 'petRegister', 'petForm'
, 'visits', 'vetList','vetForm','vetDetails', 'visitList', 'billForm', 'billUpdateForm', 'loginForm', 'rolesDetails', 'signupForm',
'billDetails', 'billsByOwnerId', 'billHistory','billsByVetId','inventoryList', 'inventoryForm', 'productForm','inventoryProductList', 'inventoryUpdateForm', 'productUpdateForm'
, 'verification' , 'adminPanel','resetPwdForm','forgotPwdForm','petTypeList']);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,81 +1,101 @@
angular.module('ownerDetails')
.controller('OwnerDetailsController', ['$http', '$state', '$stateParams', '$scope', '$timeout', '$q', function ($http, $state, $stateParams, $scope, $timeout, $q) {
var self = this;
self.owner = {};
self.pet = {};
.controller('OwnerDetailsController', OwnerDetailsController);

$http.get('api/gateway/owners/' + $stateParams.ownerId).then(function (resp) {
self.owner = resp.data;
console.log(self.owner);
OwnerDetailsController.$inject = ['$http', '$state', '$stateParams', '$scope', '$timeout', '$q'];

var petPromises = self.owner.pets.map(function (pet) {
return $http.get('api/gateway/pets/' + pet.petid, { cache: false });
});
function OwnerDetailsController($http, $state, $stateParams, $scope, $timeout, $q) {
var vm = this; // Use 'vm' (short for ViewModel) instead of 'self'

// Initialize properties
vm.owner = {};
vm.pet = {};
vm.pets = [];

$q.all(petPromises).then(function (responses) {
self.owner.pets = responses.map(function (response) {
return response.data;
});
});
// Fetch owner data
$http.get('api/gateway/owners/' + $stateParams.ownerId)
.then(function (resp) {
vm.owner = resp.data;
console.log(vm.owner);
})
.catch(function (error) {
console.error('Error fetching owner data:', error);
});

self.deletePet = function (petId) {
var config = {
headers: {
'Content-Type': 'application/json'
}
};
$http.delete('api/gateway/pets/' + petId, config)
.then(function (resp) {
console.log("Pet deleted successfully");
// Fetch associated pets and their details
$http.get(`api/gateway/owners/${$stateParams.ownerId}/pets`)
.then(function (response) {
// Split the response by newline characters to get individual pet objects
var petResponses = response.data.split('\n');

/* $http.get('api/gateway/owners/' + $stateParams.ownerId).then(function (resp) {
self.owner = resp.data;
});
*/
// Parse each pet response as JSON, remove the "data:" prefix, and trim any leading/trailing whitespace
var petObjects = petResponses.map(function (petResponse) {
// Remove the "data:" prefix and trim any leading/trailing whitespace
var trimmedResponse = petResponse.replace(/^data:/, '').trim();
console.log("Trimmed results: ", trimmedResponse)

self.owner.pets = self.owner.pets.filter(function(pet) {
return pet.petId !== petId;
});
// Check if the trimmed response is empty
if (!trimmedResponse) {
return null; // Skip empty responses
}

$scope.$applyAsync();
// Handle the success appropriately
}).catch(function (error) {
console.error("Error deleting pet:", error);
// Handle the error appropriately
try {
return JSON.parse(trimmedResponse);
} catch (error) {
console.error('Error parsing pet response:', error);
return null;
}
});
};


// Filter out any parsing errors (null values)
petObjects = petObjects.filter(function (pet) {
return pet !== null;
});


// Assuming that each pet has a 'petId' property, you can create an array of promises to fetch detailed pet data
var petPromises = petObjects.map(function (pet) {
return $http.get(`api/gateway/pets/${pet.petId}`);
});

return $q.all(petPromises);
})
.then(function (responses) {
vm.pets = responses.map(function (response) {
return response.data;
});
console.log("Pet Array:", vm.pets);
})
.catch(function (error) {
console.error('Error fetching pet data:', error);
});

self.toggleActiveStatus = function (petId) {
$http.get('api/gateway/pets/' + petId + '?_=' + new Date().getTime(), { headers: { 'Cache-Control': 'no-cache' } }).then(function (resp) {
// Toggle pet's active status
vm.toggleActiveStatus = function (petId) {
$http.get('api/gateway/pets/' + petId + '?_=' + new Date().getTime(), { headers: { 'Cache-Control': 'no-cache' } })
.then(function (resp) {
console.log("Pet id is " + petId);
console.log(resp.data);
self.pet = resp.data;
console.log("Pet id is " + self.pet.petId);
console.log(self.pet);
vm.pet = resp.data;
console.log("Pet id is " + vm.pet.petId);
console.log(vm.pet);
console.log("=====================================");
console.log(resp.data);
console.log("Active status before is:" + self.pet.isActive);
self.pet.isActive = self.pet.isActive === "true" ? "false" : "true";
console.log("Active status after is:" + self.pet.isActive);
console.log("Active status before is:" + vm.pet.isActive);
vm.pet.isActive = vm.pet.isActive === "true" ? "false" : "true";
console.log("Active status after is:" + vm.pet.isActive);

$http.patch('api/gateway/pet/' + petId, {
isActive: self.pet.isActive
}, { headers: { 'Cache-Control': 'no-cache' } }).then(function (resp) {
console.log("Pet active status updated successfully");
self.pet = resp.data;
$scope.$applyAsync()
$timeout(); // Manually trigger the $digest cycle to update the UI
}).catch(function (error) {
console.error("Error updating pet active status:", error);
// Handle the error appropriately
});
return $http.patch('api/gateway/pet/' + petId, {
isActive: vm.pet.isActive
}, { headers: { 'Cache-Control': 'no-cache' } });
})
.then(function (resp) {
console.log("Pet active status updated successfully");
vm.pet = resp.data;
$timeout(); // Manually trigger the $digest cycle to update the UI
})
.catch(function (error) {
console.error("Error updating pet active status:", error);
// Handle the error appropriately
});
};
}]);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,34 +73,30 @@ <h3 class="">Owner Details</h3>
<div class="d-flex justify-content-between gap-5">
<h3 class="">Pet Details</h3>

<div class="border-5 rounded">
<a style="color: rgba(0,0,0,0.5);" class="btn btn-light" ui-sref="ownerEdit({ownerId: $ctrl.owner.ownerId, method: 'edit'})">Add Pet</a>
<div class="border-5 rounded">
<a style="color: rgba(0,0,0,0.5);" class="btn btn-light" ui-sref="petRegister({ownerId: $ctrl.owner.ownerId})">Add Pet</a>
</div>
</div>
</div>

<div>
<!-- Use ng-repeat to iterate through the owner's pets -->
<div ng-repeat="pet in $ctrl.owner.pets" ng-show="$ctrl.owner.pets.length > 0" class="d-flex justify-content-between">
<div class="mt-3">
<a style="color: rgba(0,0,0,0.5);" class="btn btn-light" ui-sref="editPet({ownerId: $ctrl.owner.ownerId, petId: pet.petId, method: 'edit'})">Edit Pet</a>
<p>Name: {{ pet.name }}</p>
<p>Pet Id: {{pet.petId}}</p>
<!-- Add more pet details as needed -->
</div>
<div class="border-5 rounded">
<input type="checkbox" ng-model="$ctrl.pet.isActive" ng-change="$ctrl.toggleActiveStatus(pet.petId)">
<label ng-if="$ctrl.pet.isActive === 'true'" style="color: rgba(0,0,0,0.5);">Deactivate Pet</label>
<label ng-if="$ctrl.pet.isActive !== 'true'" style="color: rgba(0,0,0,0.5);">Activate Pet</label>
</div>
<div class="border-5 rounded">
<a style="color: rgba(0,0,0,0.5);" class="btn btn-light" ng-click="$ctrl.deletePet(pet.petId)">Delete Pet</a>
</div>
<div>
<!-- Use ng-repeat to iterate through the owner's pets -->
<div ng-repeat="pet in $ctrl.pets" class="d-flex justify-content-between">
<div class="mt-3">
<a style="color: rgba(0,0,0,0.5);" class="btn btn-light" ui-sref="editPet({ownerId: $ctrl.owner.ownerId, petId: pet.petId, method: 'edit'})">Edit Pet</a>
<p>Name: {{ pet.name }}</p>
<!-- Add more pet details as needed -->
</div>
<div class="border-5 rounded">
<input type="checkbox" ng-model="$ctrl.pet.isActive" ng-change="$ctrl.toggleActiveStatus(pet.petId)">
<label ng-if="$ctrl.pet.isActive === 'true'" style="color: rgba(0,0,0,0.5);">Deactivate Pet</label>
<label ng-if="$ctrl.pet.isActive !== 'true'" style="color: rgba(0,0,0,0.5);">Activate Pet</label>
</div>

</div>
</div>
</div>



</div>

</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

angular.module('petRegister')
.component('petRegister', {
templateUrl: 'scripts/pet-register/pet-register.template.html',
controller: 'PetRegisterController'
});

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict';

angular.module('petRegister')
.controller('PetRegisterController', ["$http", '$state', '$stateParams', function ($http, $state, $stateParams) {
var self = this;
var ownerId = $stateParams.ownerId || 0;
console.log("properly running on load")

$http.get('api/gateway/owners/petTypes').then(function (resp) {
self.types = resp.data;
});


// Function to submit the form
self.submitPetForm = function () {
console.log("function calls")
var petType = {
id: self.pet.type.id,
name: self.pet.type.name
}

var data = {
ownerId: ownerId,
petId: randomUUID,
name: self.pet.name,
birthDate: self.pet.birthDate,
type: petType.id,
isActive : "true"
}


$http.post("api/gateway/" + "owners/" + ownerId + "/pets", data).then(function (){
console.log("before if")
$state.go('ownerDetails', {ownerId: 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"));
});
};

function generateUUID() {
// Generate a random hexadecimal string of length 12
var randomHex = 'xxxxxxxxxxxx'.replace(/x/g, function () {
return (Math.random() * 16 | 0).toString(16);
});

// Format the UUID
var uuid = [
randomHex.substr(0, 8),
randomHex.substr(8, 4),
'4' + randomHex.substr(13, 3), // Set the version to 4 (random)
'89ab'[Math.floor(Math.random() * 4)] + randomHex.substr(17, 3), // Set the variant
randomHex.substr(20, 12)
].join('-');

return uuid;
}

// Example usage:
var randomUUID = generateUUID();
console.log(randomUUID);


}]);

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

angular.module('petRegister', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('petRegister', {
parent: 'app',
url: '/owners/{ownerId}/pets/register',
param: {ownerId: null},
template: '<pet-register></pet-register>'
})

}]);

Loading
Loading