diff --git a/KickstartWithBootstrapGrailsPlugin.groovy b/KickstartWithBootstrapGrailsPlugin.groovy index f4f8b4a..ebfed62 100644 --- a/KickstartWithBootstrapGrailsPlugin.groovy +++ b/KickstartWithBootstrapGrailsPlugin.groovy @@ -3,7 +3,7 @@ import kickstart.CustomDateEditorRegistrar class KickstartWithBootstrapGrailsPlugin { def title = "Kickstart with Bootstrap - Good looking websites!" - def version = "1.1.0" + def version = "1.2.0" def license = "APACHE" def description = """\ Kickstart is a plugin for Grails to start your project with a good looking frontend. \ @@ -16,7 +16,7 @@ frontend framework initiated by Twitter.""" ] def developers = [ - [ name: "J�rg Rech", email: "joerg.rech@gmail.com" ] + [ name: "Jörg Rech", email: "joerg.rech@gmail.com" ] ] def documentation = "http://grails.org/plugin/kickstart-with-bootstrap" def scm = [ url: "https://github.com/joergrech/KickstartWithBootstrap" ] diff --git a/application.properties b/application.properties index 9dbf151..0c84835 100644 --- a/application.properties +++ b/application.properties @@ -1,5 +1,5 @@ #Grails Metadata file #Sat Jan 25 08:08:58 CET 2014 -app.grails.version=2.3.5 +app.grails.version=2.4.3 #app.name=kickstart app.name=kickstartWithBootstrap diff --git a/grails-app/conf/BuildConfig.groovy b/grails-app/conf/BuildConfig.groovy index 8ae09dc..ccae125 100644 --- a/grails-app/conf/BuildConfig.groovy +++ b/grails-app/conf/BuildConfig.groovy @@ -21,9 +21,9 @@ grails.project.dependency.resolution = { ":rest-client-builder:1.0.3") { export = false } - compile ":scaffolding:2.0.1" // Needed since Grails 2.3 + compile ":scaffolding:2.1.1" // Needed since Grails 2.3 - runtime ":resources:1.2.1" // Needed for Bootstrap's less files + runtime ":resources:1.2.9" // Needed for Bootstrap's less files compile ":lesscss-resources:1.3.3" // Needed for Bootstrap's less files } } diff --git a/src/templates/artifacts/Controller.groovy b/src/templates/artifacts/Controller.groovy index 45be85f..a36ec0d 100644 --- a/src/templates/artifacts/Controller.groovy +++ b/src/templates/artifacts/Controller.groovy @@ -1,9 +1,4 @@ -@artifact.package@/** - * @artifact.name@ - * A controller class handles incoming web requests and performs actions such as redirects, rendering views and so on. - */ -class @artifact.name@ { +@artifact.package@class @artifact.name@ { - static scaffold = true -// def index = { } + def index() { } } diff --git a/src/templates/artifacts/DomainClass.groovy b/src/templates/artifacts/DomainClass.groovy index bd6e568..5a611dc 100644 --- a/src/templates/artifacts/DomainClass.groovy +++ b/src/templates/artifacts/DomainClass.groovy @@ -1,33 +1,5 @@ -@artifact.package@/** - * @artifact.name@ - * A domain class describes the data object and it's mapping to the database - */ -class @artifact.name@ { +@artifact.package@class @artifact.name@ { - /* Default (injected) attributes of GORM */ -// Long id -// Long version - - /* Automatic timestamping of GORM */ -// Date dateCreated -// Date lastUpdated - -// static belongsTo = [] // tells GORM to cascade commands: e.g., delete this object if the "parent" is deleted. -// static hasOne = [] // tells GORM to associate another domain object as an owner in a 1-1 mapping -// static hasMany = [] // tells GORM to associate other domain objects for a 1-n or n-m mapping -// static mappedBy = [] // specifies which property should be used in a mapping - - static mapping = { + static constraints = { } - - static constraints = { - } - - /* - * Methods of the Domain Class - */ -// @Override // Override toString for a nicer / more descriptive UI -// public String toString() { -// return "${name}"; -// } } diff --git a/src/templates/artifacts/Filters.groovy b/src/templates/artifacts/Filters.groovy index b248cb8..d1af7f9 100644 --- a/src/templates/artifacts/Filters.groovy +++ b/src/templates/artifacts/Filters.groovy @@ -1,8 +1,4 @@ -@artifact.package@/** - * @artifact.name@ - * A filters class is used to execute code before and after a controller action is executed and also after a view is rendered - */ -class @artifact.name@ { +@artifact.package@class @artifact.name@ { def filters = { all(controller:'*', action:'*') { diff --git a/src/templates/artifacts/ScaffoldingController.groovy b/src/templates/artifacts/ScaffoldingController.groovy new file mode 100644 index 0000000..3f95216 --- /dev/null +++ b/src/templates/artifacts/ScaffoldingController.groovy @@ -0,0 +1,3 @@ +@artifact.package@class @artifact.name@ { + static scaffold = true +} diff --git a/src/templates/artifacts/Service.groovy b/src/templates/artifacts/Service.groovy index 175a3e1..0aba638 100644 --- a/src/templates/artifacts/Service.groovy +++ b/src/templates/artifacts/Service.groovy @@ -1,7 +1,5 @@ -@artifact.package@/** - * @artifact.name@ - * A service class encapsulates the core business logic of a Grails application - */ +@artifact.package@import grails.transaction.Transactional + @Transactional class @artifact.name@ { diff --git a/src/templates/artifacts/TagLib.groovy b/src/templates/artifacts/TagLib.groovy index 5754368..77b8270 100644 --- a/src/templates/artifacts/TagLib.groovy +++ b/src/templates/artifacts/TagLib.groovy @@ -1,8 +1,4 @@ -@artifact.package@/** - * @artifact.name@ - * A taglib library provides a set of reusable tags to help rendering the views. - */ -class @artifact.name@ { - static defaultEncodeAs = 'html' - //static encodeAsForTags = [tagName: 'raw'] +@artifact.package@class @artifact.name@ { + static defaultEncodeAs = [taglib:'html'] + //static encodeAsForTags = [tagName: [taglib:'html'], otherTagName: [taglib:'none']] } diff --git a/src/templates/artifacts/Tests.groovy b/src/templates/artifacts/Tests.groovy index 11590d9..37c12e2 100644 --- a/src/templates/artifacts/Tests.groovy +++ b/src/templates/artifacts/Tests.groovy @@ -1,8 +1,4 @@ -@artifact.package@/** - * @artifact.name@ - * A unit test class is used to test individual methods or blocks of code without considering the surrounding infrastructure - */ -@import grails.test.* +@artifact.package@import grails.test.* class @artifact.name@ extends @artifact.superclass@ { protected void setUp() { diff --git a/src/templates/scaffolding/AsyncController.groovy b/src/templates/scaffolding/AsyncController.groovy index 8da30bf..3ab74a0 100644 --- a/src/templates/scaffolding/AsyncController.groovy +++ b/src/templates/scaffolding/AsyncController.groovy @@ -17,7 +17,7 @@ class ${className}Controller { } } - def show(Long id) { + def show(String id) { ${className}.async.get(id).then { ${propertyName} -> respond ${propertyName} } @@ -41,7 +41,7 @@ class ${className}Controller { ${propertyName}.save flush:true request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.created.message', args: [message(code: '${propertyName}.label', default: '${className}'), ${propertyName}.id]) redirect ${propertyName} } @@ -50,13 +50,13 @@ class ${className}Controller { } } - def edit(Long id) { + def edit(String id) { ${className}.async.get(id).then { ${propertyName} -> respond ${propertyName} } } - def update(Long id) { + def update(String id) { ${className}.async.withTransaction { def ${propertyName} = ${className}.get(id) if (${propertyName} == null) { @@ -71,7 +71,7 @@ class ${className}Controller { } request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.updated.message', args: [message(code: '${className}.label', default: '${className}'), ${propertyName}.id]) redirect ${propertyName} } @@ -80,7 +80,7 @@ class ${className}Controller { } } - def delete(Long id) { + def delete(String id) { ${className}.async.withTransaction { def ${propertyName} = ${className}.get(id) if (${propertyName} == null) { @@ -91,7 +91,7 @@ class ${className}Controller { ${propertyName}.delete flush:true request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.deleted.message', args: [message(code: '${className}.label', default: '${className}'), ${propertyName}.id]) redirect action:"index", method:"GET" } @@ -102,7 +102,7 @@ class ${className}Controller { protected void notFound() { request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.not.found.message', args: [message(code: '${propertyName}.label', default: '${className}'), params.id]) redirect action: "index", method: "GET" } diff --git a/src/templates/scaffolding/Controller.groovy b/src/templates/scaffolding/Controller.groovy index 5dbd2c7..b6995fa 100644 --- a/src/templates/scaffolding/Controller.groovy +++ b/src/templates/scaffolding/Controller.groovy @@ -1,22 +1,14 @@ <%=packageName ? "package ${packageName}\n\n" : ''%> + import static org.springframework.http.HttpStatus.* import grails.transaction.Transactional -/** - * ${className}Controller - * A controller class handles incoming web requests and performs actions such as redirects, rendering views and so on. - */ @Transactional(readOnly = true) class ${className}Controller { static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"] - def index(Integer max) { - params.max = Math.min(max ?: 10, 100) - respond ${className}.list(params), model:[${propertyName}Count: ${className}.count()] - } - - def list(Integer max) { + def index(Integer max) { params.max = Math.min(max ?: 10, 100) respond ${className}.list(params), model:[${propertyName}Count: ${className}.count()] } @@ -44,8 +36,8 @@ class ${className}Controller { ${propertyName}.save flush:true request.withFormat { - form { - flash.message = message(code: 'default.created.message', args: [message(code: '${propertyName}.label', default: '${className}'), ${propertyName}.id]) + form multipartForm { + flash.message = message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id]) redirect ${propertyName} } '*' { respond ${propertyName}, [status: CREATED] } @@ -71,7 +63,7 @@ class ${className}Controller { ${propertyName}.save flush:true request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.updated.message', args: [message(code: '${className}.label', default: '${className}'), ${propertyName}.id]) redirect ${propertyName} } @@ -90,7 +82,7 @@ class ${className}Controller { ${propertyName}.delete flush:true request.withFormat { - form { + form multipartForm { flash.message = message(code: 'default.deleted.message', args: [message(code: '${className}.label', default: '${className}'), ${propertyName}.id]) redirect action:"index", method:"GET" } @@ -100,8 +92,8 @@ class ${className}Controller { protected void notFound() { request.withFormat { - form { - flash.message = message(code: 'default.not.found.message', args: [message(code: '${propertyName}.label', default: '${className}'), params.id]) + form multipartForm { + flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id]) redirect action: "index", method: "GET" } '*'{ render status: NOT_FOUND } diff --git a/src/templates/scaffolding/RestfulController.groovy b/src/templates/scaffolding/RestfulController.groovy new file mode 100644 index 0000000..9c311e2 --- /dev/null +++ b/src/templates/scaffolding/RestfulController.groovy @@ -0,0 +1,62 @@ +<%=packageName ? "package ${packageName}\n\n" : ''%> + +import static org.springframework.http.HttpStatus.* +import grails.transaction.Transactional + +@Transactional(readOnly = true) +class ${className}Controller { + + static responseFormats = ['json', 'xml'] + static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"] + + def index(Integer max) { + params.max = Math.min(max ?: 10, 100) + respond ${className}.list(params), [status: OK] + } + + @Transactional + def save(${className} ${propertyName}) { + if (${propertyName} == null) { + render status: NOT_FOUND + return + } + + ${propertyName}.validate() + if (${propertyName}.hasErrors()) { + render status: NOT_ACCEPTABLE + return + } + + ${propertyName}.save flush:true + respond ${propertyName}, [status: CREATED] + } + + @Transactional + def update(${className} ${propertyName}) { + if (${propertyName} == null) { + render status: NOT_FOUND + return + } + + ${propertyName}.validate() + if (${propertyName}.hasErrors()) { + render status: NOT_ACCEPTABLE + return + } + + ${propertyName}.save flush:true + respond ${propertyName}, [status: OK] + } + + @Transactional + def delete(${className} ${propertyName}) { + + if (${propertyName} == null) { + render status: NOT_FOUND + return + } + + ${propertyName}.delete flush:true + render status: NO_CONTENT + } +} diff --git a/src/templates/scaffolding/RestfulSpec.groovy b/src/templates/scaffolding/RestfulSpec.groovy new file mode 100644 index 0000000..d57bb28 --- /dev/null +++ b/src/templates/scaffolding/RestfulSpec.groovy @@ -0,0 +1,99 @@ +<%=packageName ? "package ${packageName}\n\n" : ''%> + +import static org.springframework.http.HttpStatus.* +import grails.converters.JSON +import grails.test.mixin.* +import spock.lang.* + +@TestFor(${className}Controller) +@Mock(${className}) +class ${className}ControllerSpec extends Specification { + + def populateValidParams(params) { + assert params != null + // TODO: Populate valid properties like... + //params['name'] = 'someValidName' + } + + void "Test the index action returns the correct model"() { + + when:"The index action is executed" + controller.index() + + then:"The response is correct" + response.status == OK.value + response.text == ([] as JSON).toString() + } + + void "Test the save action correctly persists an instance"() { + + when:"The save action is executed with an invalid instance" + // Make sure the domain class has at least one non-null property + // or this test will fail. + def ${propertyName} = new ${className}() + controller.save(${propertyName}) + + then:"The response status is NOT_ACCEPTABLE" + response.status == NOT_ACCEPTABLE.value + + when:"The save action is executed with a valid instance" + response.reset() + populateValidParams(params) + ${propertyName} = new ${className}(params) + + controller.save(${propertyName}) + + then:"The response status is CREATED and the instance is returned" + response.status == CREATED.value + response.text == (${propertyName} as JSON).toString() + } + + void "Test the update action performs an update on a valid domain instance"() { + when:"Update is called for a domain instance that doesn't exist" + controller.update(null) + + then:"The response status is NOT_FOUND" + response.status == NOT_FOUND.value + + when:"An invalid domain instance is passed to the update action" + response.reset() + def ${propertyName} = new ${className}() + controller.update(${propertyName}) + + then:"The response status is NOT_ACCEPTABLE" + response.status == NOT_ACCEPTABLE.value + + when:"A valid domain instance is passed to the update action" + response.reset() + populateValidParams(params) + ${propertyName} = new ${className}(params).save(flush: true) + controller.update(${propertyName}) + + then:"The response status is OK and the updated instance is returned" + response.status == OK.value + response.text == (${propertyName} as JSON).toString() + } + + void "Test that the delete action deletes an instance if it exists"() { + when:"The delete action is called for a null instance" + controller.delete(null) + + then:"A NOT_FOUND is returned" + response.status == NOT_FOUND.value + + when:"A domain instance is created" + response.reset() + populateValidParams(params) + def ${propertyName} = new ${className}(params).save(flush: true) + + then:"It exists" + ${className}.count() == 1 + + when:"The domain instance is passed to the delete action" + controller.delete(${propertyName}) + + then:"The instance is deleted" + ${className}.count() == 0 + response.status == NO_CONTENT.value + } +} diff --git a/src/templates/scaffolding/Spec.groovy b/src/templates/scaffolding/Spec.groovy index b58d0e8..579a1eb 100644 --- a/src/templates/scaffolding/Spec.groovy +++ b/src/templates/scaffolding/Spec.groovy @@ -34,6 +34,8 @@ class ${className}ControllerSpec extends Specification { void "Test the save action correctly persists an instance"() { when:"The save action is executed with an invalid instance" + request.contentType = FORM_CONTENT_TYPE + request.method = 'POST' def ${propertyName} = new ${className}() ${propertyName}.validate() controller.save(${propertyName}) @@ -89,6 +91,8 @@ class ${className}ControllerSpec extends Specification { void "Test the update action performs an update on a valid domain instance"() { when:"Update is called for a domain instance that doesn't exist" + request.contentType = FORM_CONTENT_TYPE + request.method = 'PUT' controller.update(null) then:"A 404 error is returned" @@ -119,6 +123,8 @@ class ${className}ControllerSpec extends Specification { void "Test that the delete action deletes an instance if it exists"() { when:"The delete action is called for a null instance" + request.contentType = FORM_CONTENT_TYPE + request.method = 'DELETE' controller.delete(null) then:"A 404 is returned" diff --git a/src/templates/scaffolding/_form.gsp b/src/templates/scaffolding/_form.gsp index 76076a5..19579e4 100644 --- a/src/templates/scaffolding/_form.gsp +++ b/src/templates/scaffolding/_form.gsp @@ -32,13 +32,14 @@ private renderFieldForProperty(p, owningClass, prefix = "") { boolean required = false if (hasHibernate) { cp = owningClass.constrainedProperties[p.name] - required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable && (cp.propertyType != String || !cp.blank) : false) - } %> -
- -
- ${renderEditor(p)} - \${hasErrors(bean: ${propertyName}, field: '${p.name}', 'error')} -
-
-<% } %> + required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable : false) + } + %> +
+ + ${renderEditor(p)} +
+<% } %> diff --git a/src/templates/scaffolding/create.gsp b/src/templates/scaffolding/create.gsp index 4aaf005..5fc16f6 100644 --- a/src/templates/scaffolding/create.gsp +++ b/src/templates/scaffolding/create.gsp @@ -1,34 +1,38 @@ -<%=packageName%> - - - - - <g:message code="default.create.label" args="[entityName]" /> - - - - -
- - -
- + + + + <g:message code="default.create.label" args="[entityName]" /> + + + + - - - > - - -
- - -
-
- -
- - - +
+

+ +
\${flash.message}
+
+ + + + > +
+ +
+
+ +
+
+
+ diff --git a/src/templates/scaffolding/edit.gsp b/src/templates/scaffolding/edit.gsp index 50e0e9a..882dc9b 100644 --- a/src/templates/scaffolding/edit.gsp +++ b/src/templates/scaffolding/edit.gsp @@ -1,38 +1,41 @@ <%=packageName%> - - - - - <g:message code="default.edit.label" args="[entityName]" /> - - - - -
- - -
- + + + + <g:message code="default.edit.label" args="[entityName]" /> + + + + - - - > - - - - - - -
- - -
-
- -
- - - +
+

+ +
\${flash.message}
+
+ + + + > + +
+ +
+
+ +
+
+
+ diff --git a/src/templates/scaffolding/index.gsp b/src/templates/scaffolding/index.gsp index f9d1afc..d252bcd 100644 --- a/src/templates/scaffolding/index.gsp +++ b/src/templates/scaffolding/index.gsp @@ -2,56 +2,61 @@ <%=packageName%> - - - - - <g:message code="default.index.label" args="[entityName]" /> - - - - -
- - - - - <% excludedProps = Event.allEvents.toList() << 'id' << 'version' - allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated' - props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && !Collection.isAssignableFrom(it.type) && (domainClass.constrainedProperties[it.name] ? domainClass.constrainedProperties[it.name].display : true) } - Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[])) - props.eachWithIndex { p, i -> - if (i < 6) { - if (p.isAssociation()) { %> - - <% } else { %> - - <% } } } %> - - - - - - <% props.eachWithIndex { p, i -> - if (i == 0) { %> - - <% } else if (i < 6) { - if (p.type == Boolean || p.type == boolean) { %> - - <% } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %> - - <% } else { %> - - <% } } } %> - - - -
\${fieldValue(bean: ${propertyName}, field: "${p.name}")}\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
-
- -
-
- - - + + + + <g:message code="default.list.label" args="[entityName]" /> + + + + +
+

+ +
\${flash.message}
+
+ + + + <% excludedProps = Event.allEvents.toList() << 'id' << 'version' + allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated' + props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && it.type != null && !Collection.isAssignableFrom(it.type) && (domainClass.constrainedProperties[it.name] ? domainClass.constrainedProperties[it.name].display : true) } + Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[])) + props.eachWithIndex { p, i -> + if (i < 6) { + if (p.isAssociation()) { %> + + <% } else { %> + + <% } } } %> + + + + + + <% props.eachWithIndex { p, i -> + if (i == 0) { %> + + <% } else if (i < 6) { + if (p.type == Boolean || p.type == boolean) { %> + + <% } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %> + + <% } else { %> + + <% } } } %> + + + +
\${fieldValue(bean: ${propertyName}, field: "${p.name}")}\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
+ +
+ diff --git a/src/templates/scaffolding/list.gsp b/src/templates/scaffolding/list.gsp deleted file mode 100644 index f4d84f9..0000000 --- a/src/templates/scaffolding/list.gsp +++ /dev/null @@ -1,57 +0,0 @@ -<% import grails.persistence.Event %> -<%=packageName%> - - - - - - - <g:message code="default.list.label" args="[entityName]" /> - - - - -
- - - - - <% excludedProps = Event.allEvents.toList() << 'id' << 'version' - allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated' - props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && !Collection.isAssignableFrom(it.type) && (domainClass.constrainedProperties[it.name] ? domainClass.constrainedProperties[it.name].display : true) } - Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[])) - props.eachWithIndex { p, i -> - if (i < 6) { - if (p.isAssociation()) { %> - - <% } else { %> - - <% } } } %> - - - - - - <% props.eachWithIndex { p, i -> - if (i == 0) { %> - - <% } else if (i < 6) { - if (p.type == Boolean || p.type == boolean) { %> - - <% } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %> - - <% } else { %> - - <% } } } %> - - - -
\${fieldValue(bean: ${propertyName}, field: "${p.name}")}\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
-
- -
-
- - - - diff --git a/src/templates/scaffolding/renderEditor.template b/src/templates/scaffolding/renderEditor.template index cc52aca..7c2ea74 100644 --- a/src/templates/scaffolding/renderEditor.template +++ b/src/templates/scaffolding/renderEditor.template @@ -24,7 +24,7 @@ out << renderManyToOne(domainClass, property) else if ((property.oneToMany && !property.bidirectional) || (property.manyToMany && property.isOwningSide())) { def str = renderManyToMany(domainClass, property) - if(str != null) { + if (str != null) { out << str } } @@ -33,11 +33,14 @@ private renderEnumEditor(domainClass, property) { def sb = new StringBuilder("") - sb << ' + sb << "${k}=\"${v}\" " + } sb << renderNoSelection(property) sb << '/>' sb as String @@ -45,18 +48,18 @@ private renderStringEditor(domainClass, property) { if (!cp) { - return "" + return "" } else { def sb = new StringBuilder("") if ("textarea" == cp.widget || (cp.maxSize > 250 && !cp.password && !cp.inList)) { - sb << '' } else if (cp.inList) { - sb << '' } else { if (cp.password) { - sb << '" + return "" } else { - return "" + return "" } } else { def sb = new StringBuilder() if (cp.range) { - sb << '' } else if (cp.inList) { - sb << '' } else { - sb << '" + return "" } else { - def sb = new StringBuilder(" sb << "${k}=\"${v}\" " @@ -207,12 +210,12 @@ private renderDateEditor(domainClass, property) { def precision = (property.type == Date || property.type == java.sql.Date || property.type == Calendar) ? "day" : "minute"; if (!cp) { - return "" + return "" } else { if (!cp.editable) { return "\${${domainInstance}?.${property.name}?.toString()}" } else { - def sb = new StringBuilder(" @@ -230,9 +233,9 @@ private renderSelectTypeEditor(type, domainClass,property) { if (!cp) { - return "" + return "" } else { - def sb = new StringBuilder(" sb << "${k}=\"${v}\" " @@ -260,11 +263,11 @@ } private boolean isOptional() { - if(!cp) { + if (!cp) { return false } else { - cp.nullable || (cp.propertyType == String && cp.blank) || cp.propertyType in [boolean, Boolean] + cp.nullable || cp.propertyType in [boolean, Boolean] } } -%> \ No newline at end of file +%> diff --git a/src/templates/scaffolding/show.gsp b/src/templates/scaffolding/show.gsp index a73df58..5cebc04 100644 --- a/src/templates/scaffolding/show.gsp +++ b/src/templates/scaffolding/show.gsp @@ -2,51 +2,59 @@ <%=packageName%> - - - - - <g:message code="default.show.label" args="[entityName]" /> - - - - -
- - - - <% excludedProps = Event.allEvents.toList() << 'id' << 'version' - allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated' - props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && (domainClass.constrainedProperties[it.name] ? domainClass.constrainedProperties[it.name].display : true) } - Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[])) - props.each { p -> %> - - - <% if (p.isEnum()) { %> - - <% } else if (p.oneToMany || p.manyToMany) { %> - - <% } else if (p.manyToOne || p.oneToOne) { %> - - <% } else if (p.type == Boolean || p.type == boolean) { %> - - <% } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %> - - <% } else if(!p.type.isArray()) { %> - - <% } %> - - <% } %> - -
\${${propertyName}?.${p.name}?.encodeAsHTML()} -
    - -
  • \${${p.name[0]}?.encodeAsHTML()}
  • -
    -
-
\${${propertyName}?.${p.name}?.encodeAsHTML()}\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
-
- - - + + + + <g:message code="default.show.label" args="[entityName]" /> + + + + +
+

+ +
\${flash.message}
+
+
    + <% excludedProps = Event.allEvents.toList() << 'id' << 'version' + allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated' + props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && (domainClass.constrainedProperties[it.name] ? domainClass.constrainedProperties[it.name].display : true) } + Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[])) + props.each { p -> %> + +
  1. + + <% if (p.isEnum()) { %> + + <% } else if (p.oneToMany || p.manyToMany) { %> + + \${${p.name[0]}?.encodeAsHTML()} + + <% } else if (p.manyToOne || p.oneToOne) { %> + \${${propertyName}?.${p.name}?.encodeAsHTML()} + <% } else if (p.type == Boolean || p.type == boolean) { %> + + <% } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %> + + <% } else if (!p.type.isArray()) { %> + + <% } %> +
  2. +
    + <% } %> +
+ +
+ + +
+
+
+ diff --git a/src/templates/war/web.xml b/src/templates/war/web.xml index 29fb595..a187232 100644 --- a/src/templates/war/web.xml +++ b/src/templates/war/web.xml @@ -17,11 +17,6 @@ @grails.project.key@ - - sitemesh - org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter - - charEncodingFilter org.springframework.web.filter.DelegatingFilterProxy @@ -40,13 +35,6 @@ /* - - sitemesh - /* - REQUEST - ERROR - - org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener diff --git a/web-app/WEB-INF/applicationContext.xml b/web-app/WEB-INF/applicationContext.xml index a48dec0..d271243 100644 --- a/web-app/WEB-INF/applicationContext.xml +++ b/web-app/WEB-INF/applicationContext.xml @@ -6,7 +6,6 @@ Grails application factory bean - @@ -21,9 +20,7 @@ - - - + utf-8