| [118] | 1 | import org.codehaus.groovy.grails.plugins.springsecurity.Secured | 
|---|
| [271] | 2 | import org.codehaus.groovy.grails.commons.ConfigurationHolder | 
|---|
| [387] | 3 | import org.apache.commons.lang.WordUtils | 
|---|
| [118] | 4 |  | 
|---|
| [298] | 5 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager']) | 
|---|
| [124] | 6 | class AssetDetailedController extends BaseController { | 
|---|
| [156] | 7 |  | 
|---|
| [414] | 8 | def assetCsvService | 
|---|
| [156] | 9 | def filterService | 
|---|
| [271] | 10 | def exportService | 
|---|
| [278] | 11 | def assetService | 
|---|
| [312] | 12 | def assetTreeService | 
|---|
| [156] | 13 |  | 
|---|
| [118] | 14 | // the delete, save and update actions only accept POST requests | 
|---|
| [271] | 15 | static allowedMethods = [delete:'POST', save:'POST', update:'POST', saveCopy:'POST'] | 
|---|
| [118] | 16 |  | 
|---|
| [298] | 17 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [306] | 18 | def index = { redirect(action:search,params:params) } | 
|---|
| [298] | 19 |  | 
|---|
| [325] | 20 | /** | 
|---|
| [326] | 21 | * Set session.assetSearchParamsMax | 
|---|
|  | 22 | */ | 
|---|
|  | 23 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
|  | 24 | def setSearchParamsMax = { | 
|---|
|  | 25 | def max = 1000 | 
|---|
|  | 26 | if(params.newMax.isInteger()) { | 
|---|
|  | 27 | def i = params.newMax.toInteger() | 
|---|
|  | 28 | if(i > 0 && i <= max) | 
|---|
|  | 29 | session.assetSearchParamsMax = params.newMax | 
|---|
|  | 30 | if(i > max) | 
|---|
|  | 31 | session.assetSearchParamsMax = max | 
|---|
|  | 32 | } | 
|---|
|  | 33 | forward(action: 'search', params: params) | 
|---|
|  | 34 | } | 
|---|
|  | 35 |  | 
|---|
|  | 36 | /** | 
|---|
| [325] | 37 | * Build and return the asset tree response for the AJAX request. | 
|---|
|  | 38 | */ | 
|---|
|  | 39 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [312] | 40 | def assetTree = { | 
|---|
|  | 41 | def s = assetTreeService.buildAssetTree(params, session) | 
|---|
|  | 42 | render s | 
|---|
|  | 43 | } | 
|---|
|  | 44 |  | 
|---|
| [318] | 45 | /** | 
|---|
|  | 46 | * Save the asset tree status in the current http session. | 
|---|
|  | 47 | */ | 
|---|
| [325] | 48 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [318] | 49 | def saveAssetTreeStatus = { | 
|---|
|  | 50 | session.assetTreeVisibleBranches = params.assetTreeVisibleBranches | 
|---|
|  | 51 | } | 
|---|
|  | 52 |  | 
|---|
| [325] | 53 | /** | 
|---|
|  | 54 | * Disaply the import view. | 
|---|
|  | 55 | */ | 
|---|
|  | 56 | def importAssetTree = { | 
|---|
|  | 57 | } | 
|---|
|  | 58 |  | 
|---|
|  | 59 | /** | 
|---|
|  | 60 | * Handle the import save. | 
|---|
|  | 61 | */ | 
|---|
| [271] | 62 | def importAssetTreeSave = { | 
|---|
| [414] | 63 | def result = assetCsvService.importAssetTree(request) | 
|---|
| [271] | 64 |  | 
|---|
| [421] | 65 | if(!result.error) { | 
|---|
| [271] | 66 | flash.message = g.message(code: "asset.tree.import.success") | 
|---|
| [421] | 67 | redirect(action:search) | 
|---|
|  | 68 | return | 
|---|
|  | 69 | } | 
|---|
| [271] | 70 |  | 
|---|
| [421] | 71 | flash.errorMessage = g.message(code: result.error.code, args: result.error.args) | 
|---|
| [271] | 72 | redirect(action: importAssetTree) | 
|---|
|  | 73 | } | 
|---|
|  | 74 |  | 
|---|
|  | 75 | /** | 
|---|
|  | 76 | * Export a csv template. | 
|---|
|  | 77 | * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time! | 
|---|
|  | 78 | * This does not appear to be a problem once deployed to Tomcat. | 
|---|
|  | 79 | */ | 
|---|
| [298] | 80 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [271] | 81 | def exportAssetTreeTemplate = { | 
|---|
|  | 82 | response.contentType = ConfigurationHolder.config.grails.mime.types["csv"] | 
|---|
|  | 83 | response.setHeader("Content-disposition", "attachment; filename=AssetTreeTemplate.csv") | 
|---|
| [414] | 84 | def s = assetCsvService.buildAssetTreeTemplate() | 
|---|
| [271] | 85 | render s | 
|---|
|  | 86 | } | 
|---|
|  | 87 |  | 
|---|
| [325] | 88 | /** | 
|---|
|  | 89 | * Export a csv test file. | 
|---|
|  | 90 | */ | 
|---|
| [302] | 91 | def exportAssetTreeTest = { | 
|---|
|  | 92 | response.contentType = ConfigurationHolder.config.grails.mime.types["csv"] | 
|---|
|  | 93 | response.setHeader("Content-disposition", "attachment; filename=AssetTreeTestFile.csv") | 
|---|
| [414] | 94 | def s = assetCsvService.buildAssetTreeTest() | 
|---|
| [302] | 95 | render s | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
| [298] | 98 | /** | 
|---|
| [325] | 99 | * Export the entire asset tree as a csv file. | 
|---|
| [298] | 100 | */ | 
|---|
|  | 101 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [271] | 102 | def exportAssetTree = { | 
|---|
|  | 103 |  | 
|---|
|  | 104 | def assetList = Asset.list() | 
|---|
|  | 105 |  | 
|---|
|  | 106 | response.contentType = ConfigurationHolder.config.grails.mime.types["csv"] | 
|---|
|  | 107 | response.setHeader("Content-disposition", "attachment; filename=AssetTree.csv") | 
|---|
| [414] | 108 | def s = assetCsvService.buildAssetTree(assetList) | 
|---|
| [271] | 109 | render s | 
|---|
|  | 110 | } | 
|---|
|  | 111 |  | 
|---|
| [298] | 112 | /** | 
|---|
|  | 113 | * Search action. | 
|---|
|  | 114 | */ | 
|---|
|  | 115 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [139] | 116 | def search = { | 
|---|
| [156] | 117 |  | 
|---|
| [325] | 118 | if(session.assetSearchParamsMax) | 
|---|
|  | 119 | params.max = session.assetSearchParamsMax | 
|---|
| [271] | 120 |  | 
|---|
|  | 121 | params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000) | 
|---|
|  | 122 |  | 
|---|
|  | 123 | def assetInstanceList = [] | 
|---|
|  | 124 | def assetInstanceTotal | 
|---|
|  | 125 | def filterParams = [:] | 
|---|
|  | 126 |  | 
|---|
| [156] | 127 | // Quick Search: | 
|---|
|  | 128 | if(!params.filter) { | 
|---|
| [271] | 129 | assetInstanceList = Asset.list( params ) | 
|---|
|  | 130 | assetInstanceTotal = Asset.count() | 
|---|
|  | 131 | filterParams.quickSearch = params.quickSearch | 
|---|
| [156] | 132 | } | 
|---|
| [271] | 133 | else { | 
|---|
| [156] | 134 | // filterPane: | 
|---|
| [271] | 135 | assetInstanceList = filterService.filter( params, Asset ) | 
|---|
|  | 136 | assetInstanceTotal = filterService.count( params, Asset ) | 
|---|
|  | 137 | filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params) | 
|---|
|  | 138 | } | 
|---|
| [139] | 139 |  | 
|---|
| [271] | 140 | // export plugin: | 
|---|
|  | 141 | if(params?.format && params.format != "html") { | 
|---|
|  | 142 |  | 
|---|
|  | 143 | def dateFmt = { date -> | 
|---|
|  | 144 | formatDate(format: "EEE, dd-MMM-yyyy", date: date) | 
|---|
|  | 145 | } | 
|---|
|  | 146 |  | 
|---|
|  | 147 | //             def fmtAsset = { m -> | 
|---|
|  | 148 | //                     def r = '' | 
|---|
|  | 149 | //                     def assetInstance = Asset.findByName(m) | 
|---|
|  | 150 | // | 
|---|
|  | 151 | //                     r +=  assetInstance | 
|---|
|  | 152 | //                     r += ", " | 
|---|
|  | 153 | // | 
|---|
|  | 154 | //                     def  lastSubAsset = assetInstance.subAssets.size() - 1 | 
|---|
|  | 155 | //                     assetInstance.subAssets.eachWithIndex() { obj, i -> | 
|---|
|  | 156 | //                         r += "\"" + obj + "\"" | 
|---|
|  | 157 | //                         if( i < lastSubAsset ) | 
|---|
|  | 158 | //                             r += ", " | 
|---|
|  | 159 | //                     } | 
|---|
|  | 160 | //                     return r | 
|---|
|  | 161 | //             } | 
|---|
|  | 162 |  | 
|---|
|  | 163 | //             def fmtSubAsset = { m -> | 
|---|
|  | 164 | //                     def r = '' | 
|---|
|  | 165 | //                     m.each() { | 
|---|
|  | 166 | //                         def machine = Machine.findByName(it) | 
|---|
|  | 167 | //                         def assemblies = machine.assemblies | 
|---|
|  | 168 | //                         r += machine.name | 
|---|
|  | 169 | //                         r += " " | 
|---|
|  | 170 | //                         r += assemblies | 
|---|
|  | 171 | //                         r += " " | 
|---|
|  | 172 | //                     } | 
|---|
|  | 173 | //                     return r | 
|---|
|  | 174 | //             } | 
|---|
|  | 175 |  | 
|---|
|  | 176 | String title = "Asset List." | 
|---|
|  | 177 |  | 
|---|
|  | 178 | response.contentType = ConfigurationHolder.config.grails.mime.types[params.format] | 
|---|
| [390] | 179 | response.setHeader("Content-disposition", "attachment; filename=Assets.${params.extension}") | 
|---|
| [271] | 180 | List fields = ["section.site", | 
|---|
|  | 181 | "section", | 
|---|
|  | 182 | "name", | 
|---|
|  | 183 | "description"] | 
|---|
|  | 184 | Map labels = ["section.site": "Site", | 
|---|
|  | 185 | "section": "Section", | 
|---|
|  | 186 | "name": "Asset", | 
|---|
|  | 187 | "description": "Description"] | 
|---|
|  | 188 | //             Map labels | 
|---|
|  | 189 | //             Map formatters = ["subAsset.name": fmtSubAsset] | 
|---|
|  | 190 | Map formatters = [:] | 
|---|
|  | 191 | Map parameters = [title: title, separator: ","] | 
|---|
|  | 192 |  | 
|---|
|  | 193 | exportService.export(params.format, | 
|---|
|  | 194 | response.outputStream, | 
|---|
|  | 195 | assetInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }, | 
|---|
|  | 196 | fields, | 
|---|
|  | 197 | labels, | 
|---|
|  | 198 | formatters, | 
|---|
|  | 199 | parameters) | 
|---|
|  | 200 | } | 
|---|
|  | 201 |  | 
|---|
|  | 202 | // Add some basic params to filterParams. | 
|---|
|  | 203 | filterParams.max = params.max | 
|---|
|  | 204 | filterParams.offset = params.offset?.toInteger() ?: 0 | 
|---|
|  | 205 | filterParams.sort = params.sort ?: "id" | 
|---|
|  | 206 | filterParams.order = params.order ?: "desc" | 
|---|
|  | 207 |  | 
|---|
|  | 208 | return[ assetInstanceList: assetInstanceList, | 
|---|
|  | 209 | assetInstanceTotal: assetInstanceTotal, | 
|---|
|  | 210 | filterParams: filterParams ] | 
|---|
|  | 211 |  | 
|---|
|  | 212 | } // end search() | 
|---|
|  | 213 |  | 
|---|
| [298] | 214 | /** | 
|---|
|  | 215 | * Show action. | 
|---|
|  | 216 | */ | 
|---|
|  | 217 | @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser']) | 
|---|
| [118] | 218 | def show = { | 
|---|
| [283] | 219 |  | 
|---|
| [139] | 220 | // In the case of an actionSubmit button, rewrite action name from 'index'. | 
|---|
|  | 221 | if(params._action_Show) | 
|---|
| [375] | 222 | params.action='show' | 
|---|
| [283] | 223 |  | 
|---|
| [118] | 224 | def assetInstance = Asset.get( params.id ) | 
|---|
|  | 225 |  | 
|---|
|  | 226 | if(!assetInstance) { | 
|---|
|  | 227 | flash.message = "Asset not found with id ${params.id}" | 
|---|
| [139] | 228 | redirect(action:search) | 
|---|
| [118] | 229 | } | 
|---|
|  | 230 | else { return [ assetInstance : assetInstance ] } | 
|---|
|  | 231 | } | 
|---|
|  | 232 |  | 
|---|
| [298] | 233 | /** | 
|---|
|  | 234 | * Delete action. | 
|---|
|  | 235 | */ | 
|---|
| [118] | 236 | def delete = { | 
|---|
| [350] | 237 | def result = assetService.delete(params) | 
|---|
|  | 238 |  | 
|---|
|  | 239 | if(!result.error) { | 
|---|
|  | 240 | flash.message = g.message(code: "default.delete.success", args: ["Asset", params.id]) | 
|---|
|  | 241 | redirect(action:search) | 
|---|
|  | 242 | return | 
|---|
| [118] | 243 | } | 
|---|
| [350] | 244 |  | 
|---|
|  | 245 | flash.errorMessage = g.message(code: result.error.code, args: result.error.args) | 
|---|
|  | 246 |  | 
|---|
|  | 247 | if(result.error.code == "default.not.found") { | 
|---|
| [139] | 248 | redirect(action:search) | 
|---|
| [350] | 249 | return | 
|---|
| [118] | 250 | } | 
|---|
| [350] | 251 |  | 
|---|
|  | 252 | redirect(action:show, id: params.id) | 
|---|
| [118] | 253 | } | 
|---|
|  | 254 |  | 
|---|
| [298] | 255 | /** | 
|---|
|  | 256 | * Edit action. | 
|---|
|  | 257 | */ | 
|---|
| [118] | 258 | def edit = { | 
|---|
| [283] | 259 |  | 
|---|
| [139] | 260 | // In the case of an actionSubmit button, rewrite action name from 'index'. | 
|---|
|  | 261 | if(params._action_Edit) | 
|---|
| [375] | 262 | params.action='edit' | 
|---|
| [283] | 263 |  | 
|---|
| [118] | 264 | def assetInstance = Asset.get( params.id ) | 
|---|
|  | 265 |  | 
|---|
|  | 266 | if(!assetInstance) { | 
|---|
|  | 267 | flash.message = "Asset not found with id ${params.id}" | 
|---|
| [139] | 268 | redirect(action:search) | 
|---|
| [118] | 269 | } | 
|---|
|  | 270 | else { | 
|---|
| [305] | 271 | return [ assetInstance : assetInstance, possibleAssetSubItems: assetService.possibleAssetSubItems() ] | 
|---|
| [118] | 272 | } | 
|---|
|  | 273 | } | 
|---|
|  | 274 |  | 
|---|
| [298] | 275 | /** | 
|---|
|  | 276 | * Update action. | 
|---|
|  | 277 | */ | 
|---|
| [118] | 278 | def update = { | 
|---|
|  | 279 | def assetInstance = Asset.get( params.id ) | 
|---|
|  | 280 | if(assetInstance) { | 
|---|
|  | 281 | if(params.version) { | 
|---|
|  | 282 | def version = params.version.toLong() | 
|---|
|  | 283 | if(assetInstance.version > version) { | 
|---|
| [283] | 284 |  | 
|---|
| [403] | 285 | assetInstance.errors.rejectValue("version", "default.optimistic.locking.failure") | 
|---|
| [305] | 286 | render(view:'edit',model:[assetInstance:assetInstance, possibleAssetSubItems: assetService.possibleAssetSubItems()]) | 
|---|
| [118] | 287 | return | 
|---|
|  | 288 | } | 
|---|
|  | 289 | } | 
|---|
| [286] | 290 |  | 
|---|
| [118] | 291 | assetInstance.properties = params | 
|---|
| [286] | 292 |  | 
|---|
| [387] | 293 | use(WordUtils) { | 
|---|
|  | 294 | assetInstance.name = assetInstance.name.capitalize() | 
|---|
|  | 295 | assetInstance.description = assetInstance.description.capitalize() | 
|---|
|  | 296 | } | 
|---|
|  | 297 |  | 
|---|
| [286] | 298 | assetInstance.setAssetSubItemsFromCheckBoxList(params.assetSubItems) | 
|---|
|  | 299 |  | 
|---|
| [178] | 300 | if(!assetInstance.hasErrors() && assetInstance.save(flush: true)) { | 
|---|
| [387] | 301 | flash.message = "Asset '${assetInstance.name}' updated" | 
|---|
| [118] | 302 | redirect(action:show,id:assetInstance.id) | 
|---|
|  | 303 | } | 
|---|
|  | 304 | else { | 
|---|
| [305] | 305 | render(view:'edit',model:[assetInstance:assetInstance, possibleAssetSubItems: assetService.possibleAssetSubItems()]) | 
|---|
| [118] | 306 | } | 
|---|
|  | 307 | } | 
|---|
|  | 308 | else { | 
|---|
|  | 309 | flash.message = "Asset not found with id ${params.id}" | 
|---|
| [334] | 310 | redirect(action:search) | 
|---|
| [118] | 311 | } | 
|---|
|  | 312 | } | 
|---|
|  | 313 |  | 
|---|
| [298] | 314 | /** | 
|---|
|  | 315 | * Create action. | 
|---|
|  | 316 | */ | 
|---|
| [118] | 317 | def create = { | 
|---|
| [284] | 318 | def result = assetService.create(params) | 
|---|
|  | 319 |  | 
|---|
|  | 320 | if(!result.error) | 
|---|
|  | 321 | return [assetInstance: result.assetInstance] | 
|---|
|  | 322 |  | 
|---|
|  | 323 | flash.errorMessage = g.message(code: result.error.code, args: result.error.args) | 
|---|
|  | 324 | redirect(action: search) | 
|---|
| [118] | 325 | } | 
|---|
|  | 326 |  | 
|---|
| [298] | 327 | /** | 
|---|
|  | 328 | * Copy action. | 
|---|
|  | 329 | */ | 
|---|
| [271] | 330 | def copy = { | 
|---|
| [284] | 331 | def result = assetService.copy(params) | 
|---|
| [271] | 332 |  | 
|---|
| [284] | 333 | if(!result.error) | 
|---|
|  | 334 | return [assetInstance: result.assetInstance, assetToCopy: result.assetToCopy] | 
|---|
| [271] | 335 |  | 
|---|
| [284] | 336 | flash.errorMessage = g.message(code: result.error.code, args: result.error.args) | 
|---|
|  | 337 | redirect(action: search) | 
|---|
| [271] | 338 | } | 
|---|
|  | 339 |  | 
|---|
| [298] | 340 | /** | 
|---|
|  | 341 | * Save action. | 
|---|
|  | 342 | */ | 
|---|
| [118] | 343 | def save = { | 
|---|
| [284] | 344 | def result = assetService.save(params) | 
|---|
|  | 345 |  | 
|---|
|  | 346 | if(!result.error) { | 
|---|
| [387] | 347 | flash.message = g.message(code: "default.create.success", args: ["Asset",  "'${result.assetInstance.name}'"]) | 
|---|
| [284] | 348 | redirect(action:show, id: result.assetInstance.id) | 
|---|
|  | 349 | return | 
|---|
| [118] | 350 | } | 
|---|
| [284] | 351 |  | 
|---|
|  | 352 | render(view:'create', model:[assetInstance: result.assetInstance]) | 
|---|
| [118] | 353 | } | 
|---|
| [271] | 354 |  | 
|---|
| [298] | 355 | /** | 
|---|
|  | 356 | * Copy save action. | 
|---|
|  | 357 | */ | 
|---|
| [271] | 358 | def saveCopy = { | 
|---|
| [278] | 359 | def result = assetService.saveCopy(params) | 
|---|
| [271] | 360 |  | 
|---|
|  | 361 | if(!result.error) { | 
|---|
|  | 362 | flash.message = g.message(code: "default.create.success", args: ["Asset", result.assetInstance.id]) | 
|---|
|  | 363 | redirect(action:show, id: result.assetInstance.id) | 
|---|
|  | 364 | return | 
|---|
|  | 365 | } | 
|---|
|  | 366 |  | 
|---|
|  | 367 | if(result.error.code == "default.not.found") { | 
|---|
|  | 368 | flash.message = g.message(code: result.error.code, args: ["Asset", params.assetToCopy?.id]) | 
|---|
| [334] | 369 | redirect(action: search) | 
|---|
| [271] | 370 | return | 
|---|
|  | 371 | } | 
|---|
|  | 372 |  | 
|---|
| [429] | 373 | flash.errorMessage = g.message(code: result.error.code, args: ["Asset"]) | 
|---|
| [278] | 374 |  | 
|---|
| [271] | 375 | render(view:'copy', model:[assetInstance: result.assetInstance, assetToCopy: result.assetToCopy]) | 
|---|
|  | 376 | } | 
|---|
|  | 377 |  | 
|---|
|  | 378 | } // end class | 
|---|