Skip to content

Commit

Permalink
Merge pull request #364 from gpc/incorporate-scaffolding-old-with-his…
Browse files Browse the repository at this point in the history
…tory

Incorporate https://github.com/grails/scaffolding-old code and docs into fields plugin
  • Loading branch information
jamesfredley authored Sep 24, 2024
2 parents 6a5bfc0 + 99c1dd9 commit 8180260
Show file tree
Hide file tree
Showing 75 changed files with 4,893 additions and 1 deletion.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ dependencies {
compileOnly "org.springframework.boot:spring-boot-starter-tomcat"
compileOnly "org.grails:grails-dependencies"
compileOnly "org.grails.plugins:gsp:${grailsVersion}"
implementation "org.grails:scaffolding-core:$grailsScaffoldingVersion"

testImplementation "org.grails:grails-web-testing-support"
testImplementation "org.grails:grails-gorm-testing-support"
Expand All @@ -45,6 +44,8 @@ dependencies {
}

testRuntimeOnly "net.bytebuddy:byte-buddy:$byteBuddyVersion"

testImplementation "org.grails:grails-datastore-gorm-hibernate5:$gormHibernate5Version"
}

tasks.withType(Test).configureEach {
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ grailsVersion=7.0.0-SNAPSHOT
grailsGradlePluginVersion=7.0.0-SNAPSHOT
grailsScaffoldingVersion=2.1.0
groovyVersion=4.0.23
gormHibernate5Version=9.0.0-SNAPSHOT
joddWotVersion=3.3.8
byteBuddyVersion=1.14.12
asciidoc=true
Expand Down
103 changes: 103 additions & 0 deletions src/docs/asciidoc/scaffolding/definitions/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
== Definitions

The scaffolding classes provided by this module use words that have special meaning in the context of rendering HTML.

=== Input

Input is defined as a means for a user to input data. Typically this will come in the form of HTML elements like select or textarea. The definition is not limited to input elements because all facets of rendering inputs can be changed to include whatever makes sense for your plugin.

=== Output

Output is defined as a means for a user to view data. How this is represented is entirely based on whatever template rendering technology you are using. For Groovy pages it may look like `${domain.property}`. For Angular templates it may look like `{{domain.property}}`.

=== Context

Context is defined as the markup that surrounds or is rendered alongside domain properties. There are several different contexts this module defines. All contexts are rendered by the link:api/org/grails/scaffolding/markup/ContextMarkupRenderer.html[ContextMarkupRenderer].

==== List Output Context

The markup surrounding the display of a list of domain classes. Examples are a table or a grid.

==== Output Context (Domain)

The markup surrounding the display of a domain class. An example is a container or ordered list.

==== Output Context (Property)

The markup surrounding the display of an individual domain class property. An example is a row in a grid or a list item.

==== Input Context (Domain)

The markup surrounding where a domain class will be created or modified. An example is a form.

==== Input Context (Property)

The markup surrounding the input of a domain class property. An example is a cell in a grid.

==== Embedded Output Context

The markup surrounding the input of the properties of an embedded domain class property. An example is a header.

==== Embedded Input Context

The markup surrounding the display of the properties of an embedded domain class property. An example is a fieldset.

=== Examples

[source,xml,indent=1]
----
<form class="form-inline"> <1>
<div class="form-group"> <2>
<label for="exampleName2">Name</label>
<input type="text" class="form-control" id="exampleName2"> <3>
</div>
<div class="form-group"> <2>
<label for="exampleEmail2">Email</label>
<input type="email" class="form-control" id="exampleEmail2"> <3>
</div>
<fieldset> <4>
<legend>Address</legend>
<div class="form-group"> <2>
<label for="city">City</label>
<input type="text" class="form-control" id="city"> <3>
</div>
</fieldset>
<button type="submit" class="btn btn-default">Send invitation</button>
</form>
----
<1> Input Context (Domain)
<2> Input Context (Property)
<3> Rendered Domain Property
<4> Embedded Input Context


[source,xml,indent=1]
----
<div class="container"> <1>
<div class="row">
<div class="col-sm-2">Name</div> <2>
<div class="col-sm-10">
${user.name} <3>
</div>
<div class="col-sm-2">Age</div>
<div class="col-sm-10">
${user.age} <3>
</div>
<div class="col-sm-2">Address</div> <4>
<div class="col-sm-10">
<div class="row-fluid">
<div class="col-sm-2">City</div> <2>
<div class="col-sm-10">
${user.address.city} <3>
</div>
</div>
</div>
</div>
</div>
----
<1> Output Context (Domain)
<2> Output Context (Property)
<3> Rendered Domain Property
<4> Embedded Output Context
59 changes: 59 additions & 0 deletions src/docs/asciidoc/scaffolding/extending/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
== Extending

All aspects of the way markup is created can be changed.

=== Which properties are rendered

The link:api/org/grails/scaffolding/model/DomainModelService.html[DomainModelService] is responsible for returning which properties should be rendered for any given view. To override the default behavior, register a bean with the name "domainModelService" that implements the link:api/org/grails/scaffolding/model/DomainModelService.html[DomainModelService] interface. You can extend the default implementation link:api/org/grails/scaffolding/model/DomainModelServiceImpl.html[DomainModelServiceImpl] if you wish.

=== How the different contexts are rendered

The link:api/org/grails/scaffolding/markup/ContextMarkupRenderer.html[ContextMarkupRenderer] is responsible for rendering all of the contexts. To override the default behavior, register a bean with the name "contextMarkupRenderer" that implements the link:api/org/grails/scaffolding/markup/ContextMarkupRenderer.html[ContextMarkupRenderer] interface. You can extend the default implementation link:api/org/grails/scaffolding/markup/ContextMarkupRendererImpl.html[ContextMarkupRendererImpl] if you wish.

=== How properties are rendered

The link:api/org/grails/scaffolding/markup/PropertyMarkupRenderer.html[PropertyMarkupRenderer] is responsible for rendering all of domain properties. To override the default behavior, register a bean with the name "propertyMarkupRenderer" that implements the link:api/org/grails/scaffolding/markup/PropertyMarkupRenderer.html[PropertyMarkupRenderer] interface. You can extend the default implementation link:api/org/grails/scaffolding/markup/PropertyMarkupRendererImpl.html[PropertyMarkupRendererImpl] if you wish.

The default implementation simply defers to a domain output or input registry. The most convenient way to control how a specific type of property will be rendered is to register an input or ouput renderer to the registry.

NOTE: All of the default renderers in the registry have a priority of < 0, so registering a custom one with a priority of > 0 will ensure it is used over the default

==== Input Rendering

Input renders must implement the link:api/org/grails/scaffolding/registry/DomainInputRenderer.html[DomainInputRenderer] interface. Implementations must define 2 methods.

* `Boolean supports(DomainProperty domainProperty)`
Return true if your renderer supports the given property. See the link:api/org/grails/scaffolding/model/property/DomainProperty.html[DomainProperty] and link:http://gorm.grails.org/latest/api/org/grails/datastore/mapping/model/PersistentProperty.html[PersistentProperty] interfaces to see what data is available on the domain property instance.
* `Closure renderInput(Map defaultAttributes, DomainProperty property)`
Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property

NOTE: The default attributes passed to `renderInput` are created by the link:api/org/grails/scaffolding/markup/PropertyMarkupRenderer.html#getStandardAttributes(org.grails.scaffolding.model.property.DomainProperty)[PropertyMarkupRenderer#getStandardAttributes] method.

To register your renderer, inject the "domainInputRendererRegistry" bean and execute `registerDomainRenderer`, passing along your renderer and its priority.

[source,groovy,indent=1]
----
DomainInputRendererRegistry domainInputRendererRegistry
domainInputRendererRegistry.registerDomainRenderer(new MyCustomDomainInputRenderer(), 1)
----

==== Output Rendering

Output renders must implement the link:api/org/grails/scaffolding/registry/DomainOutputRenderer.html[DomainOutputRenderer] interface. Implementations must define 3 methods.

* `Boolean supports(DomainProperty domainProperty)`
Return true if your renderer supports the given property. See the link:api/org/grails/scaffolding/model/property/DomainProperty.html[DomainProperty] and link:http://gorm.grails.org/latest/api/org/grails/datastore/mapping/model/PersistentProperty.html[PersistentProperty] interfaces to see what data is available on the domain property instance.
* `Closure renderListOutput(DomainProperty property)`
Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a list of domain class instances
* `Closure renderOutput(DomainProperty property)`
Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a single domain class instance

To register your renderer, inject the "domainOutputRendererRegistry" bean and execute `registerDomainRenderer`, passing along your renderer and its priority.

[source,groovy,indent=1]
----
DomainOutputRendererRegistry domainOutputRendererRegistry
domainOutputRendererRegistry.registerDomainRenderer(new MyCustomDomainOutputRenderer(), 1)
----
17 changes: 17 additions & 0 deletions src/docs/asciidoc/scaffolding/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
= Grails Scaffolding
:author: James Kleeh
:email: [email protected]
:source-highlighter: coderay
:numbered:

== Introduction

include::introduction.adoc[]

include::definitions/index.adoc[]

include::installation/index.adoc[]

include::usage/index.adoc[]

include::extending/index.adoc[]
10 changes: 10 additions & 0 deletions src/docs/asciidoc/scaffolding/installation/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
== Installation

To start using this library, there are only a couple simple steps:

. Import the library in your `build.gradle`
[source,groovy,subs="attributes",indent=1]
compile "org.grails:scaffolding-core:{version}"
. Register the scaffolding core bean configuration link:api/org/grails/scaffolding/ScaffoldingBeanConfiguration.html[ScaffoldingBeanConfiguration]
[source,groovy,indent=1]
scaffoldingBeanConfiguration(ScaffoldingBeanConfiguration)
6 changes: 6 additions & 0 deletions src/docs/asciidoc/scaffolding/introduction.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The Grails scaffolding core module was created to render 3 separate views: list, show, and create/edit. By default the views are rendered in a similar way to the link:https://grails-fields-plugin.github.io/grails-fields/[fields] plugin. All of the applicable rules of the link:https://grails-fields-plugin.github.io/grails-fields/[fields] plugin also apply to this module.

Scaffolding core is designed to render markup intended to be processed by a template engine. The classes provided by this library will always render markup based on the definition of a domain class, instead of an individual instance or instances of a domain class that contain real data.

This user guide will cover how this library works along with how developers can extend it to completely customize the results.

23 changes: 23 additions & 0 deletions src/docs/asciidoc/scaffolding/usage/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
== Usage

To render markup, inject the link:api/org/grails/scaffolding/markup/DomainMarkupRenderer.html[DomainMarkupRenderer].

[source,groovy,indent=1]
DomainMarkupRenderer domainMarkupRenderer

Then execute one of the methods provided:

* `renderOutput` (Show page)
* `renderInput` (Edit/Create page)
* `renderListOutput` (List page)
A string containing all of the markup will be returned.

Each of the methods requires a link:http://gorm.grails.org/latest/api/org/grails/datastore/mapping/model/PersistentEntity.html[PersistentEntity] that represents the given domain class. To retrieve the link:http://gorm.grails.org/latest/api/org/grails/datastore/mapping/model/PersistentEntity.html[PersistentEntity], inject the mapping context and pass in the fully qualified domain class name.

[source,groovy,indent=1]
----
MappingContext grailsDomainClassMappingContext
grailsDomainClassMappingContext.getPersistentEntity("test.foo.Bar")
----
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.grails.scaffolding

import org.grails.scaffolding.markup.*
import org.grails.scaffolding.model.DomainModelService
import org.grails.scaffolding.model.DomainModelServiceImpl
import org.grails.scaffolding.model.property.DomainPropertyFactory
import org.grails.scaffolding.model.property.DomainPropertyFactoryImpl
import org.grails.scaffolding.registry.DomainInputRendererRegistry
import org.grails.scaffolding.registry.DomainOutputRendererRegistry
import org.grails.scaffolding.registry.DomainRendererRegisterer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class ScaffoldingBeanConfiguration {

@Bean
ContextMarkupRenderer contextMarkupRenderer() {
new ContextMarkupRendererImpl()
}

@Bean
DomainMarkupRenderer domainMarkupRenderer() {
new DomainMarkupRendererImpl()
}

@Bean
PropertyMarkupRenderer propertyMarkupRenderer() {
new PropertyMarkupRendererImpl()
}

@Bean
DomainPropertyFactory domainPropertyFactory() {
new DomainPropertyFactoryImpl()
}

@Bean
DomainModelService domainModelService() {
new DomainModelServiceImpl()
}

@Bean
DomainInputRendererRegistry domainInputRendererRegistry() {
new DomainInputRendererRegistry()
}

@Bean
DomainOutputRendererRegistry domainOutputRendererRegistry() {
new DomainOutputRendererRegistry()
}

@Bean
DomainRendererRegisterer domainRendererRegisterer() {
new DomainRendererRegisterer()
}

}
Loading

0 comments on commit 8180260

Please sign in to comment.