Created
February 7, 2013 19:40
-
-
Save cdeszaq/4733549 to your computer and use it in GitHub Desktop.
Example of how to have multiple child elements created from a single view. Of note, the `RequestedPeersCommand` object is the part that lets n People be selected to request peer evaluations from.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ page import="edu.wisc.radiology.performanceevaluations.Score" %> | |
<p>Please enter the people you would like to request a Peer Evaluation from for <strong>${performanceReview.employee}</strong>:</p> | |
<g:each in="${0..2}"> | |
<div class="control-group"> | |
<label class="control-label" for="people[${it}].id">Peer</label> | |
<div class="controls"> | |
%{--TODO: Use Select2 (http://ivaynberg.github.com/select2/index.html)--}% | |
<g:select name="people[$it].id" from="${possiblePeers}" optionKey="id" noSelection="['':'Please select']" /> | |
</div> | |
</div> | |
</g:each> | |
<p> | |
In order for this to be a complete review, <em>please think carefully about peer evaluations</em>. Individuals who work closely with | |
this person would be the best selection. <strong>Please request at least 3 peer evaluators</strong>. | |
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(document).ready(function(){ | |
// *** Request Peer Evaluations *** | |
// Remove the modal dialogue when it closes so that content re-loads | |
// See: http://stackoverflow.com/a/12287169/20770 | |
$('#requestPeerEvaluationsModal').on('hidden', function () { | |
$(this).removeData('modal'); | |
}); | |
// Attach the peer request submission handler | |
$("#requestPeerEvaluationsModal form").submit(function(e) { | |
e.preventDefault(); | |
var method = this.method; | |
var action = this.action; | |
var data = $(this).serialize(); | |
$.ajax({ | |
type: method, | |
url: action, | |
data: data, | |
success: function(data) { | |
// Replace the table | |
$("#evaluationList").replaceWith(data); | |
// Trigger timed fade | |
initiateTimedFade(2000) | |
// Close the modal | |
$("#requestPeerEvaluationsModal").modal('hide'); | |
}, | |
error: function(data) { | |
alert("Failed to request peer evaluations."); | |
} | |
}); | |
}); | |
// Attach the add more peers handler | |
// TODO: Use this | |
$("#requestPeerEvaluationsModal .addMore").click(function(e) { | |
e.preventDefault(); | |
var peerList = $("#requestPeerEvaluationsModal .modal-body"); | |
var kids = peerList.children("div"); | |
var nextId = "people[" + kids.size() + "].id"; | |
var clone = kids.last().clone(); | |
// Update the id in the clone | |
$(clone).find("label") | |
.attr("for", nextId); | |
$(clone).find("select") | |
.attr("name", nextId) | |
.attr("id", nextId); | |
// Put it before the comment at the bottom | |
kids.last().after(clone); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package edu.wisc.radiology.performanceevaluations | |
import grails.converters.JSON | |
import grails.converters.XML | |
import grails.plugins.springsecurity.Secured | |
import grails.validation.Validateable | |
@Secured("hasRole('ROLE_USER')") | |
class RequestPeerEvaluationController { | |
def springSecurityService | |
def requestPeerEvaluationService | |
def performanceReviewStatusGateService | |
// Dangerous actions are limited to dangerous methods that make sense for that action | |
static allowedMethods = [ | |
save: ["POST"] | |
] | |
// Return a page for requesting new peer evaluations | |
def create() { | |
withPerformanceReview { PerformanceReview performanceReviewInstance -> | |
// TODO: Gate Me | |
def possiblePeers = requestPeerEvaluationService.getPossiblePeers(performanceReviewInstance) | |
def model = [ | |
performanceReview: performanceReviewInstance, | |
possiblePeers: possiblePeers | |
] | |
render(template:"requestPeerEvaluationsTemplate", model: model) | |
} | |
} | |
// Create a new peer evaluation requests from the request data | |
def save(RequestedPeersCommand requestedPeers) { | |
withPerformanceReview { PerformanceReview performanceReviewInstance -> | |
// TODO: Gate Me | |
requestedPeers.people.each { | |
requestPeerEvaluationService.requestPeerEvaluation(it, performanceReviewInstance) | |
} | |
def message = 'Peer evaluations requested' | |
def messageType = "success" | |
// Respond successfully | |
withFormat { | |
html { | |
render(template:"/performanceReview/evaluationListTemplate", model: [message: message, messageType: messageType, performanceReview: performanceReviewInstance]) | |
} | |
} | |
} | |
} | |
// Must be public so that controller-specific actions can reach it. It can't do anything nefarious though, so it's OK. | |
// Methods can't have default parameters but closures can... | |
private withPerformanceReview = { id = "id", Closure c -> | |
def performanceReviewInstance = PerformanceReview.get(params[id]) | |
if (!performanceReviewInstance) { | |
flash.message = message(code: 'default.not.found.message', args: [message(code: 'performanceReview.label', default: 'PerformanceReview'), params.id]) | |
response.status = 404 | |
withFormat { | |
// Browsers get helpful 404 content (the list), the others just get the error message | |
html { forward(action: "list") } | |
json { render flash as JSON } | |
xml { render flash as XML } | |
} | |
} else { | |
c.call performanceReviewInstance | |
} | |
} | |
} | |
@Validateable | |
class RequestedPeersCommand { | |
Collection<Person> people = [].withDefault { new Person() } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package edu.wisc.radiology.performanceevaluations | |
import org.joda.time.LocalDate | |
class RequestPeerEvaluationService { | |
def mailService | |
def springSecurityService | |
boolean requestPeerEvaluation(Person peer, PerformanceReview performanceReview) { | |
// TODO: Gate me properly | |
if (!peer.id || PerformanceReviewPeer.countByPerformanceReviewAndPerson(performanceReview,peer) > 0) { | |
return false | |
} | |
// Update the performance review's status | |
performanceReview.performanceReviewStatus = PerformanceReviewStatus.findByName("Open") | |
if (!performanceReview.save(flush: true)) { | |
return false | |
} | |
PerformanceReviewPeer prp = createPerformanceReviewPeer(peer, performanceReview) | |
sendPeerEmail(prp) | |
true | |
} | |
private static def createPerformanceReviewPeer(Person peer, PerformanceReview review) { | |
// TODO: Gate me | |
PerformanceReviewPeer prp = new PerformanceReviewPeer(person: peer, performanceReview: review) | |
prp.save(flush: true) | |
prp | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment