forked from robfletcher/grails-angular-scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAngularScaffoldingGrailsPlugin.groovy
234 lines (181 loc) · 8.1 KB
/
AngularScaffoldingGrailsPlugin.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import org.codehaus.groovy.grails.commons.GrailsApplication
import org.codehaus.groovy.grails.commons.GrailsControllerClass
import org.codehaus.groovy.grails.commons.GrailsDomainClass
import grails.plugin.angularscaffolding.AngularTemplateGenerator
import org.codehaus.groovy.grails.scaffolding.GrailsTemplateGenerator
import org.springframework.context.ApplicationContext
import grails.util.BuildSettingsHolder
import grails.converters.JSON
import grails.rest.render.json.JsonRenderer
import grails.rest.render.json.JsonCollectionRenderer
import org.codehaus.groovy.grails.web.mime.MimeType
import grails.plugin.angularscaffolding.marshalling.DomainClassMarshaller
import grails.plugin.angularscaffolding.marshalling.AngularObjectMarshallers
import grails.plugin.angularscaffolding.marshalling.AngularDateMarshaller
class AngularScaffoldingGrailsPlugin {
//private Logger log = LoggerFactory.getLogger(getClass())
def version = '1.0-SNAPSHOT'
def grailsVersion = '2.0 > *'
def dependsOn = [:]
def pluginExcludes = []
def loadBefore = ['platformUi']
def loadAfter = ['controllers', 'groovyPages','scaffolding']
def title = 'Angular Scaffolding Plugin'
def author = 'Rob Fletcher'
def authorEmail = '[email protected]'
def description = '''\
A plugin that enables Grails scaffolding to operate as an Angular.js one-page app.
'''
def documentation = 'http://freeside.co/grails-angular-scaffolding'
def license = 'MIT'
def organization = [name: 'Freeside Software', url: 'http://freeside.co/']
def issueManagement = [system: 'GitHub', url: 'https://github.com/robfletcher/grails-angular-scaffolding/issues']
def scm = [url: 'https://github.com/robfletcher/grails-angular-scaffolding']
def observe = ['controllers', 'domainClass']
def doWithConfig = { config ->
log.debug "AngularScaffoldingGrailsPlugin.doWithConfig"
platformUi {
ui.AngularScaffolding.logo.cssClass = 'navbar-brand'
ui.AngularScaffolding.actions.cssClass = ''
ui.AngularScaffolding.button.cssClass = 'btn'
ui.AngularScaffolding.tab.cssClass = 'tab-pane'
ui.AngularScaffolding.tabs.cssClass = 'nav nav-tabs'
ui.AngularScaffolding.field.cssClass = 'input'
ui.AngularScaffolding.input.cssClass = 'input-xlarge'
ui.AngularScaffolding.invalid.cssClass = 'invalid'
ui.AngularScaffolding.table.cssClass = 'table table-striped table-bordered table-hover'
ui.AngularScaffolding.tr.cssClass = ''
ui.AngularScaffolding.trOdd.cssClass = ''
ui.AngularScaffolding.trEven.cssClass = ''
ui.AngularScaffolding.carousel.cssClass = 'carousel slide'
ui.AngularScaffolding.slide.cssClass = 'item'
ui.AngularScaffolding.form.cssClass = 'form-horizontal'
ui.AngularScaffolding.primaryNavigation.cssClass = 'nav'
ui.AngularScaffolding.secondaryNavigation.cssClass = 'nav nav-pills'
ui.AngularScaffolding.navigation.cssClass = 'nav'
themes.AngularScaffolding.ui.set = "AngularScaffolding"
}
application {
if(config.grails.databinding.dateFormats){
grails.databinding.dateFormats = config.grails.databinding.dateFormats + ["yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss.S", "yyyy-MM-dd'T'hh:mm:ss'Z'", "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'"]
} else {
grails.databinding.dateFormats = ["yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss.S", "yyyy-MM-dd'T'hh:mm:ss'Z'", "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'"]
grails.databinding.dateFormats.unique()
}
grails.databinding.dateFormats.unique()
}
}
def doWithSpring = {
log.debug "AngularScaffoldingGrailsPlugin.doWithSpring"
scaffoldingTemplateGenerator(AngularTemplateGenerator, ref("classLoader")) {
grailsApplication = ref("grailsApplication")
}
angularObjectMarshallers( AngularObjectMarshallers ) {
marshallers = [
new AngularDateMarshaller()
]
}
//default excludes class field
def excludesList = ['class']
if(application.config.angularScaffolding.render.excludesList) {
excludesList = application.config.angularScaffolding.render.excludesList
}
// for all domain classes in the application.
for (domainClass in application.domainClasses) {
// Register JSON renderer for domainClass resource with short output.
"json${domainClass.shortName}ShortRenderer"(JsonRenderer, domainClass.clazz) {
// Grails will compare the name of the MimeType
// to determine which renderer to use. So we
// use our own custom name here.
// The second argument, 'short', specifies the
// supported extension. We can now use
// the request parameter format=short to use
// this renderer for the domainClass resource.
mimeTypes = [new MimeType('application/angular-scaffolding.short+json', 'short')]
// Here we specify the named configuration
// that must be used by an instance
// of this renderer.
namedConfiguration = 'short'
}
"json${domainClass.shortName}ShortCollectionRenderer"(JsonCollectionRenderer, domainClass.clazz) {
mimeTypes = [new MimeType('application/angular-scaffolding.short+json', 'short')]
namedConfiguration = 'short'
}
// Default JSON renderer as fallback.
"json${domainClass.shortName}Renderer"(JsonRenderer, domainClass.clazz) {
excludes = excludesList
}
"json${domainClass.shortName}CollectionRenderer"(JsonCollectionRenderer, domainClass.clazz) {
excludes = excludesList
}
}
}
def doWithApplicationContext = { ctx ->
log.debug "AngularScaffoldingGrailsPlugin.doWithApplicationContext"
// Custom marshalling
ctx.getBean( "angularObjectMarshallers" ).register()
JSON.createNamedConfig('short') { nc ->
for (domainClass in application.domainClasses) {
Closure c = DomainClassMarshaller.createIncludeMarshaller(domainClass.clazz, ['id','toString'])
nc.registerObjectMarshaller(domainClass.clazz, c)
}
}
def config = application.config
config.grails.mime.types['short'] = ['application/angular-scaffolding.short+json', 'application/json']
//TODO if config.grails.plugin.angularscaffolding.dynamicScaffolding == true
if (application.warDeployed) {
doScaffolding ctx, application
return
}
try {
log.info "do scaffolding..."
doScaffolding ctx, application
log.info "done scaffolding."
}
catch (e) {
log.error "Error doing scaffolding: $e.message", e
}
}
def onChange = { event ->
log.debug "AngularScaffoldingGrailsPlugin.onChange"
def dynamicScaffold = false //TODO make configurable
if(dynamicScaffold){
if (event.source && application.isControllerClass(event.source)) {
GrailsControllerClass controllerClass = application.getControllerClass(event.source.name)
doScaffoldingController(event.ctx, event.application, controllerClass)
} else {
doScaffolding(event.ctx, event.application)
}
}
}
private void doScaffolding(ApplicationContext ctx, GrailsApplication application) {
for (controllerClass in application.controllerClasses) {
doScaffoldingController(ctx, application, controllerClass)
}
}
private void doScaffoldingController(ApplicationContext ctx, GrailsApplication application, GrailsControllerClass controllerClass) {
def scaffoldProperty = controllerClass.getPropertyValue("scaffold", Object)
if (!scaffoldProperty || !ctx) {
return
}
GrailsDomainClass domainClass = getScaffoldedDomainClass(application, controllerClass, scaffoldProperty)
if (!domainClass) {
log.error "Cannot generate controller logic for scaffolded class {}. It is not a domain class!", scaffoldProperty
return
}
GrailsTemplateGenerator generator = ctx.scaffoldingTemplateGenerator
ClassLoader parentLoader = ctx.classLoader
def basedir = BuildSettingsHolder.settings.baseDir.toString()
generator.generateViews(domainClass, basedir)
}
private GrailsDomainClass getScaffoldedDomainClass(application, GrailsControllerClass controllerClass, scaffoldProperty) {
if (!scaffoldProperty) {
return null
}
if (scaffoldProperty instanceof Class) {
return application.getDomainClass(scaffoldProperty.name)
}
scaffoldProperty = controllerClass.packageName ? "${controllerClass.packageName}.${controllerClass.name}" : controllerClass.name
return application.getDomainClass(scaffoldProperty)
}
}