Changeset 271


Ignore:
Timestamp:
Jan 15, 2010, 11:37:52 AM (10 years ago)
Author:
gav
Message:

Regenerate asset views and detail views to suite.
Add CsvService, import and copy functions with appropriate messages and gsp's.

Location:
trunk/grails-app
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/AssetDetailedController.groovy

    r178 r271  
    11import org.codehaus.groovy.grails.plugins.springsecurity.Secured
     2import org.codehaus.groovy.grails.commons.ConfigurationHolder
    23
    34class AssetDetailedController extends BaseController {
    45
     6    def csvService
    57    def filterService
     8    def exportService
    69
    710    def index = { redirect(action:search,params:params) }
    811
    912    // the delete, save and update actions only accept POST requests
    10     static allowedMethods = [delete:'POST', save:'POST', update:'POST']
     13    static allowedMethods = [delete:'POST', save:'POST', update:'POST', saveCopy:'POST']
     14
     15    def importAssetTree = {
     16    }
     17
     18    def importAssetTreeSave = {
     19        def result = csvService.importAssetTree(request)
     20
     21        if(!result.error)
     22            flash.message = g.message(code: "asset.tree.import.success")
     23        else
     24            flash.warning = g.message(code: result.error.code, args: result.error.args)
     25
     26        redirect(action: importAssetTree)
     27    }
     28
     29    /**
     30    * Export a csv template.
     31    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
     32    * This does not appear to be a problem once deployed to Tomcat.
     33    */
     34    def exportAssetTreeTemplate = {
     35        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
     36        response.setHeader("Content-disposition", "attachment; filename=AssetTreeTemplate.csv")
     37        def s = csvService.buildAssetTreeTemplate()
     38        render s
     39    }
     40
     41    def exportAssetTree = {
     42
     43        def assetList = Asset.list()
     44
     45        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
     46        response.setHeader("Content-disposition", "attachment; filename=AssetTree.csv")
     47        def s = csvService.buildAssetTree(assetList)
     48        render s
     49    }
    1150
    1251    def list = {
     
    1655
    1756    def search = {
    18         params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
     57
     58        if(session.taskSearchParamsMax)
     59            params.max = session.taskSearchParamsMax
     60
     61        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000)
     62
     63        def assetInstanceList = []
     64        def assetInstanceTotal
     65        def filterParams = [:]
    1966
    2067        // Quick Search:
    2168        if(!params.filter) {
    22            return [ assetInstanceList: Asset.list( params ), assetInstanceTotal: Asset.count() ]
    23         }
     69            assetInstanceList = Asset.list( params )
     70            assetInstanceTotal = Asset.count()
     71            filterParams.quickSearch = params.quickSearch
     72        }
     73        else {
    2474        // filterPane:
    25         return[ assetInstanceList: filterService.filter( params, Asset ),
    26                 assetInstanceTotal: filterService.count( params, Asset ),
    27                 filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
    28                 params:params ]
    29     }
     75            assetInstanceList = filterService.filter( params, Asset )
     76            assetInstanceTotal = filterService.count( params, Asset )
     77            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
     78        }
     79
     80        // export plugin:
     81        if(params?.format && params.format != "html") {
     82
     83            def dateFmt = { date ->
     84                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
     85            }
     86
     87//             def fmtAsset = { m ->
     88//                     def r = ''
     89//                     def assetInstance = Asset.findByName(m)
     90//
     91//                     r +=  assetInstance
     92//                     r += ", "
     93//
     94//                     def  lastSubAsset = assetInstance.subAssets.size() - 1
     95//                     assetInstance.subAssets.eachWithIndex() { obj, i ->
     96//                         r += "\"" + obj + "\""
     97//                         if( i < lastSubAsset )
     98//                             r += ", "
     99//                     }
     100//                     return r
     101//             }
     102
     103//             def fmtSubAsset = { m ->
     104//                     def r = ''
     105//                     m.each() {
     106//                         def machine = Machine.findByName(it)
     107//                         def assemblies = machine.assemblies
     108//                         r += machine.name
     109//                         r += " "
     110//                         r += assemblies
     111//                         r += " "
     112//                     }
     113//                     return r
     114//             }
     115
     116            String title = "Asset List."
     117
     118            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
     119            response.setHeader("Content-disposition", "attachment; filename=tasks.${params.extension}")
     120            List fields = ["section.site",
     121                                "section",
     122                                "name",
     123                                "description"]
     124            Map labels = ["section.site": "Site",
     125                                "section": "Section",
     126                                "name": "Asset",
     127                                "description": "Description"]
     128//             Map labels
     129//             Map formatters = ["subAsset.name": fmtSubAsset]
     130            Map formatters = [:]
     131            Map parameters = [title: title, separator: ","]
     132
     133            exportService.export(params.format,
     134                                                response.outputStream,
     135                                                assetInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
     136                                                fields,
     137                                                labels,
     138                                                formatters,
     139                                                parameters)
     140        }
     141
     142        // Add some basic params to filterParams.
     143        filterParams.max = params.max
     144        filterParams.offset = params.offset?.toInteger() ?: 0
     145        filterParams.sort = params.sort ?: "id"
     146        filterParams.order = params.order ?: "desc"
     147
     148        return[ assetInstanceList: assetInstanceList,
     149                assetInstanceTotal: assetInstanceTotal,
     150                filterParams: filterParams ]
     151
     152    } // end search()
    30153
    31154    def show = {
     
    113236    }
    114237
     238    def copy = {
     239        def assetToCopy = Asset.get(params.asset.id)
     240
     241        if(!assetToCopy) {
     242            flash.message = "Please select an asset to copy."
     243            redirect(action: list)
     244            return
     245        }
     246
     247        def assetInstance = new Asset(name: assetToCopy.name, section: assetToCopy.section)
     248        assetInstance.properties = params
     249        return ['assetInstance':assetInstance, assetToCopy: assetToCopy]
     250    }
     251
    115252    def save = {
    116253        def assetInstance = new Asset(params)
     
    123260        }
    124261    }
    125 }
     262
     263    def saveCopy = {
     264        def result = saveCopySrvce(params)
     265
     266        if(!result.error) {
     267            flash.message = g.message(code: "default.create.success", args: ["Asset", result.assetInstance.id])
     268            redirect(action:show, id: result.assetInstance.id)
     269            return
     270        }
     271
     272        if(result.error.code == "default.not.found") {
     273            flash.message = g.message(code: result.error.code, args: ["Asset", params.assetToCopy?.id])
     274            redirect(action: list)
     275            return
     276        }
     277
     278        render(view:'copy', model:[assetInstance: result.assetInstance, assetToCopy: result.assetToCopy])
     279    }
     280
     281    def saveCopySrvce(params) {
     282        Asset.withTransaction { status ->
     283            def result = [:]
     284
     285            def fail = { Map m ->
     286                status.setRollbackOnly()
     287                if(result.assetInstance && m.field)
     288                    result.assetInstance.errors.rejectValue(m.field, m.code)
     289                result.error = [ code: m.code, args: ["Asset", params.id] ]
     290                return result
     291            }
     292
     293            result.assetToCopy = Asset.get(params.assetToCopy?.id)
     294            if(!result.assetToCopy)
     295                return fail(code:"default.not.found")
     296
     297            result.assetInstance =  new Asset(params)
     298
     299            if(result.assetInstance.hasErrors() || !result.assetInstance.save())
     300                return fail(code:"default.create.failure")
     301
     302            def assetSubItemInstance1
     303
     304            // Copy subItems from level 2 and bellow.
     305            def copyAssetSubItem = { assetSubItemToCopy, parentItem ->
     306                def assetSubItemInstance = new AssetSubItem(name: assetSubItemToCopy.name,
     307                                                                                            description: assetSubItemToCopy.description,
     308                                                                                            parentItem: parentItem)
     309
     310                if(assetSubItemInstance.hasErrors() || !assetSubItemInstance.save())
     311                    return fail(field:"subItems", code:"default.create.failure")
     312
     313                def i = 0
     314                for(assetSubItem in assetSubItemToCopy.subItems) {
     315                    call(assetSubItem, assetSubItemInstance)
     316                    // Protect against endless recurrsion.
     317                    i++
     318                    if(i > 100)
     319                        fail(code:"default.create.failure")
     320                    // Stop if an error is flagged.
     321                    if(result.error)
     322                        break
     323                }
     324            } //copyAssetSubItem
     325
     326            // Copy the 1st level of subItems.
     327            def copyAssetSubItem1 = { assetSubItemToCopy ->
     328                assetSubItemInstance1 = new AssetSubItem(name: assetSubItemToCopy.name,
     329                                                                                        description: assetSubItemToCopy.description,
     330                                                                                        asset: result.assetInstance)
     331
     332                if(assetSubItemInstance1.hasErrors() || !assetSubItemInstance1.save())
     333                    return fail(field:"assetSubItems", code:"default.create.failure")
     334
     335                def i = 0
     336                for(assetSubItem in assetSubItemToCopy.subItems) {
     337                    copyAssetSubItem(assetSubItem, assetSubItemInstance1)
     338                    // Protect against endless recurrsion.
     339                    i++
     340                    if(i > 100)
     341                        fail(code:"default.create.failure")
     342                    // Stop if an error is flagged.
     343                    if(result.error)
     344                        break
     345                }
     346            } //copyAssetSubItem1
     347
     348            def i = 0
     349            for(assetSubItem in result.assetToCopy.assetSubItems) {
     350                copyAssetSubItem1(assetSubItem)
     351                // Protect against endless recurrsion.
     352                i++
     353                if(i > 100)
     354                    fail(code:"default.create.failure")
     355                // Stop if an error is flagged.
     356                if(result.error)
     357                    break
     358            }
     359
     360            // Success or not.
     361            return result
     362
     363        } //end withTransaction
     364    } // end saveCopySrvce
     365
     366} // end class
  • trunk/grails-app/i18n/messages.properties

    r263 r271  
     1asset.tree.import.success=Asset tree imported.
     2asset.tree.import.failure=Could not create asset tree from supplied file.
     3asset.tree.import.file.over.max.size=Supplied file is over max size.
     4asset.tree.import.file.not.supplied=No file supplied.
     5asset.tree.import.no.header=The supplied file does not have the correct headers, please see the template file.
     6
    17sub.task.create.confirm=Immediately create and save a new sub task?
    28
  • trunk/grails-app/views/asset/edit.gsp

    r268 r271  
    8383                            <tr class="prop">
    8484                                <td valign="top" class="name">
    85                                     <label for="assetSubItem">Asset Sub Item:</label>
     85                                    <label for="assetSubItems">Asset Sub Items:</label>
    8686                                </td>
    87                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetSubItem','errors')}">
     87                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetSubItems','errors')}">
    8888                                   
    8989<ul>
    90 <g:each var="a" in="${assetInstance?.assetSubItem?}">
     90<g:each var="a" in="${assetInstance?.assetSubItems?}">
    9191    <li><g:link controller="assetSubItem" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
    9292</g:each>
  • trunk/grails-app/views/asset/show.gsp

    r268 r271  
    7171                   
    7272                        <tr class="prop">
    73                             <td valign="top" class="name">Asset Sub Item:</td>
     73                            <td valign="top" class="name">Asset Sub Items:</td>
    7474                           
    7575                            <td  valign="top" style="text-align:left;" class="value">
    7676                                <ul>
    77                                 <g:each var="a" in="${assetInstance.assetSubItem}">
     77                                <g:each var="a" in="${assetInstance.assetSubItems}">
    7878                                    <li><g:link controller="assetSubItem" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
    7979                                </g:each>
  • trunk/grails-app/views/assetDetailed/create.gsp

    r161 r271  
    55        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    66        <meta name="layout" content="main" />
    7         <title>Create Asset</title>   
     7        <title>Create Asset</title>
    88        <nav:resources override="true"/>
    99    </head>
     
    3131                                </td>
    3232                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'name','errors')}">
    33                                     <input type="text" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
     33                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
    3434                                </td>
    35                             </tr>
     35                            </tr> 
    3636                       
    3737                            <tr class="prop">
     
    4040                                </td>
    4141                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'description','errors')}">
    42                                     <input type="text" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
    43                                 </td>
    44                             </tr>
    45                        
    46                             <tr class="prop">
    47                                 <td valign="top" class="name">
    48                                     <label for="costCode">Cost Code:</label>
    49                                 </td>
    50                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'costCode','errors')}">
    51                                     <input type="text" id="costCode" name="costCode" value="${fieldValue(bean:assetInstance,field:'costCode')}"/>
    52                                 </td>
    53                             </tr>
    54                        
    55                             <tr class="prop">
    56                                 <td valign="top" class="name">
    57                                     <label for="assetType">Asset Type:</label>
    58                                 </td>
    59                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetType','errors')}">
    60                                     <g:select optionKey="id" from="${AssetType.list()}" name="assetType.id" value="${assetInstance?.assetType?.id}" ></g:select>
     42                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
    6143                                </td>
    6244                            </tr>
    63 
    64                             <tr class="prop">
    65                                 <td valign="top" class="name">
    66                                     <label for="systemSection">System Section:</label>
    67                                 </td>
    68                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'systemSection','errors')}">
    69                                     <g:select optionKey="id" from="${SystemSection.list()}" name="systemSection.id" value="${assetInstance?.systemSection?.id}" ></g:select>
    70                                 </td>
    71                             </tr>
    72 
     45                       
    7346                            <tr class="prop">
    7447                                <td valign="top" class="name">
     
    7952                                </td>
    8053                            </tr>
    81 
     54                       
     55                            <tr class="prop">
     56                                <td valign="top" class="name">
     57                                    <label for="section">Section:</label>
     58                                </td>
     59                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'section','errors')}">
     60                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${assetInstance?.section?.id}" ></g:select>
     61                                </td>
     62                            </tr>
     63                       
    8264                        </tbody>
    8365                    </table>
  • trunk/grails-app/views/assetDetailed/edit.gsp

    r161 r271  
    3333                                </td>
    3434                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'name','errors')}">
    35                                     <input type="text" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
     35                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
    3636                                </td>
    3737                            </tr>
     
    4242                                </td>
    4343                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'description','errors')}">
    44                                     <input type="text" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
     44                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
    4545                                </td>
    46                             </tr>
     46                            </tr> 
    4747                       
    4848                            <tr class="prop">
    4949                                <td valign="top" class="name">
    50                                     <label for="costCode">Cost Code:</label>
     50                                    <label for="isActive">Is Active:</label>
    5151                                </td>
    52                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'costCode','errors')}">
    53                                     <input type="text" id="costCode" name="costCode" value="${fieldValue(bean:assetInstance,field:'costCode')}"/>
     52                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'isActive','errors')}">
     53                                    <g:checkBox name="isActive" value="${assetInstance?.isActive}" ></g:checkBox>
    5454                                </td>
    55                             </tr>
     55                            </tr> 
    5656                       
    5757                            <tr class="prop">
    5858                                <td valign="top" class="name">
    59                                     <label for="assetType">Asset Type:</label>
     59                                    <label for="section">Section:</label>
    6060                                </td>
    61                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetType','errors')}">
    62                                     <g:select optionKey="id" from="${AssetType.list()}" name="assetType.id" value="${assetInstance?.assetType?.id}" ></g:select>
     61                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'section','errors')}">
     62                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${assetInstance?.section?.id}" ></g:select>
    6363                                </td>
    64                             </tr>
     64                            </tr> 
    6565                       
    66                             <tr class="prop">
    67                                 <td valign="top" class="name">
    68                                     <label for="systemSection">System Section:</label>
    69                                 </td>
    70                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'systemSection','errors')}">
    71                                     <g:select optionKey="id" from="${SystemSection.list()}" name="systemSection.id" value="${assetInstance?.systemSection?.id}" ></g:select>
    72                                 </td>
    73                             </tr>
    74                          
    7566                            <tr class="prop">
    7667                                <td valign="top" class="name">
     
    9182                            <tr class="prop">
    9283                                <td valign="top" class="name">
    93                                     <label for="isActive">Is Active:</label>
     84                                    <label for="assetSubItems">Asset Sub Items:</label>
    9485                                </td>
    95                                 <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'isActive','errors')}">
    96                                     <g:checkBox name="isActive" value="${assetInstance?.isActive}" ></g:checkBox>
     86                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetSubItems','errors')}">
     87                                   
     88<ul>
     89<g:each var="a" in="${assetInstance?.assetSubItems?}">
     90    <li><g:link controller="assetSubItemDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
     91</g:each>
     92</ul>
     93<g:link controller="assetSubItemDetailed" params="['asset.id':assetInstance?.id]" action="create">Add AssetSubItem</g:link>
     94
    9795                                </td>
    9896                            </tr>
  • trunk/grails-app/views/assetDetailed/list.gsp

    r182 r271  
    2222                       
    2323                                <g:sortableColumn property="id" title="Id" />
    24 
    25                              <g:sortableColumn property="name" title="Name" />
    26 
    27                              <g:sortableColumn property="assetType" title="Asset Type" />
    2824                       
    29                                 <g:sortableColumn property="systemSection" title="System Section" />
    30 
    31                             <g:sortableColumn property="isActive" title="Is Active" />
    32 
    33                             <th></th>
     25                                <g:sortableColumn property="name" title="Name" />
     26                       
     27                                <g:sortableColumn property="description" title="Description" />
     28                       
     29                                <g:sortableColumn property="isActive" title="Is Active" />
     30                       
     31                                <th>Section</th>
    3432                           
    3533                        </tr>
     
    4038                       
    4139                            <td>${fieldValue(bean:assetInstance, field:'id')}</td>
    42 
    43                             <td>${fieldValue(bean:assetInstance, field:'name')}</td>                       
    44 
    45                             <td>${fieldValue(bean:assetInstance, field:'assetType')}</td>
    46 
    47                             <td>${fieldValue(bean:assetInstance, field:'systemSection')}</td>
    48 
     40                       
     41                            <td>${fieldValue(bean:assetInstance, field:'name')}</td>
     42                       
     43                            <td>${fieldValue(bean:assetInstance, field:'description')}</td>
     44                       
    4945                            <td>${fieldValue(bean:assetInstance, field:'isActive')}</td>
     46                       
     47                            <td>${fieldValue(bean:assetInstance, field:'section')}</td>
    5048
    5149                            <td>
  • trunk/grails-app/views/assetDetailed/search.gsp

    r221 r271  
    88        <nav:resources override="true"/>
    99        <filterpane:includes />
     10        <export:resource />
    1011    </head>
    1112    <body>
     
    3940
    4041                             <g:sortableColumn property="name" title="Name" params="${filterParams}" />
    41 
    42                              <g:sortableColumn property="assetType" title="Asset Type" params="${filterParams}" />
    4342                       
    44                                 <g:sortableColumn property="systemSection" title="System Section" params="${filterParams}" />
     43                            <g:sortableColumn property="description" title="Description" params="${filterParams}" />
    4544
    4645                            <g:sortableColumn property="isActive" title="Is Active" params="${filterParams}" />
     46                       
     47                            <g:sortableColumn property="section" title="Section" params="${filterParams}" />
    4748
    4849                            <th></th>
     
    5859                            <td>${fieldValue(bean:assetInstance, field:'name')}</td>                       
    5960
    60                             <td>${fieldValue(bean:assetInstance, field:'assetType')}</td>
    61 
    62                             <td>${fieldValue(bean:assetInstance, field:'systemSection')}</td>
     61                            <td>${fieldValue(bean:assetInstance, field:'description')}</td>
    6362
    6463                            <td>${fieldValue(bean:assetInstance, field:'isActive')}</td>
     64
     65                            <td>${fieldValue(bean:assetInstance, field:'section')}</td>
    6566
    6667                            <td>
     
    7879                <g:paginate total="${assetInstanceTotal}" params="${filterParams}" />
    7980            </div>
     81            <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
     82            <br />
     83            Asset Tree:
     84            <g:link action="exportAssetTree">
     85                Export
     86            </g:link>
     87            /
     88            <g:link action="exportAssetTreeTemplate">
     89                Template
     90            </g:link>
     91            /
     92            <g:link action="importAssetTree">
     93                Import
     94            </g:link>
    8095
    8196            <filterpane:filterPane domainBean="Asset"
     
    8499                                    class="overlayPane"
    85100                                    excludeProperties=""
    86                                     associatedProperties="systemSection.name, assetType.name"
    87                                     filterPropertyValues="${['systemSection.name':[values:SystemSection.list()],
    88                                                                         'assetType.name':[values:AssetType.list()] ]}" />
     101                                    associatedProperties="section.name"
     102                                    filterPropertyValues="${['section.name':[values:Section.list()] ]}" />
    89103        </div> <!-- end body div -->
    90104    </body>
  • trunk/grails-app/views/assetDetailed/show.gsp

    r161 r271  
    1919                <table>
    2020                    <tbody>
    21 
    2221                   
    2322                        <tr class="prop">
     
    2928                   
    3029                        <tr class="prop">
    31                             <td valign="top" class="name">Name:</td>
    32                            
    33                             <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'name')}</td>
    34                            
     30                            <td valign="top" class="name">Asset:</td>
     31
     32                            <td  valign="top" style="text-align:left;" class="value">
     33                                ${assetInstance.encodeAsHTML()}
     34                                <g:link controller="assetSubItemDetailed" params="['asset.id':assetInstance?.id]" action="create">
     35                                    <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item"/>
     36                                </g:link>
     37                                <g:link params="['asset.id':assetInstance?.id]" action="copy">
     38                                    <img src="${resource(dir:'images/skin',file:'page_copy.png')}" alt="Copy" title="Copy Asset"/>
     39                                </g:link>
     40                                <br />
     41                                <br />
     42                                <ul>
     43                                <g:each var="assetSubItem1" in="${assetInstance.assetSubItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
     44                                    <li>
     45                                        <g:link controller="assetSubItemDetailed" action="edit" id="${assetSubItem1.id}">${assetSubItem1?.encodeAsHTML()}</g:link>
     46                                    <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem1?.id]" action="create">
     47                                        <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
     48                                    </g:link>
     49                                    </li>
     50                                    <ul>
     51                                    <g:each var="assetSubItem2" in="${assetSubItem1.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
     52                                        <li>
     53                                            <g:link controller="assetSubItemDetailed" action="edit" id="${assetSubItem2.id}">${assetSubItem2?.encodeAsHTML()}</g:link>
     54                                        <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem2?.id]" action="create">
     55                                            <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
     56                                        </g:link>
     57                                        </li>
     58                                        <ul>
     59                                        <g:each var="assetSubItem3" in="${assetSubItem2.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
     60                                            <li>
     61                                                <g:link controller="assetSubItemDetailed" action="edit" id="${assetSubItem3.id}">${assetSubItem3?.encodeAsHTML()}</g:link>
     62                                            <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem3?.id]" action="create">
     63                                                <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
     64                                            </g:link>
     65                                            </li>
     66                                            <ul>
     67                                            <g:each var="assetSubItem4" in="${assetSubItem3.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
     68                                                <li><g:link controller="assetSubItemDetailed" action="edit" id="${assetSubItem4.id}">${assetSubItem4?.encodeAsHTML()}</g:link></li>
     69                                            </g:each> <!--assetSubItem4-->
     70                                            </ul>
     71                                        </g:each> <!--assetSubItem3-->
     72                                        </ul>
     73                                    </g:each> <!--assetSubItem2-->
     74                                    </ul>
     75                                    <br />
     76                                    <br />
     77                                </g:each> <!--assetSubItem1-->
     78                                </ul>
     79                            </td>
     80
    3581                        </tr>
    3682                   
     
    3985                           
    4086                            <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'description')}</td>
    41                            
    42                         </tr>
    43                    
    44                         <tr class="prop">
    45                             <td valign="top" class="name">Cost Code:</td>
    46                            
    47                             <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'costCode')}</td>
    48                            
    49                         </tr>
    50                    
    51                         <tr class="prop">
    52                             <td valign="top" class="name">Asset Type:</td>
    53                            
    54                             <td valign="top" class="value">
    55                                 ${assetInstance?.assetType?.encodeAsHTML()}
    56                                 <ul>
    57                                 <g:each var="a" in="${assetInstance.assetType.assemblies}">
    58                                     <li>
    59                                         ${a?.encodeAsHTML()}
    60                                         <ul>
    61                                         <g:each var="s" in="${a.subAssemblies}">
    62                                             <li>${s?.encodeAsHTML()}</li>
    63                                         </g:each>
    64                                         </ul>
    65                                     </li>
    66                                 </g:each>
    67                                 </ul>
    68                             </td>
    69                            
    70                         </tr>
    71 
    72                         <tr class="prop">
    73                             <td valign="top" class="name">System Section:</td>
    74                            
    75                             <td valign="top" class="value"><g:link controller="systemSectionDetailed" action="show" id="${assetInstance?.systemSection?.id}">${assetInstance?.systemSection?.encodeAsHTML()}</g:link></td>
    76                            
    77                         </tr>
    78                    
    79                         <tr class="prop">
    80                             <td valign="top" class="name">Asset Extended Attributes:</td>
    81                            
    82                             <td  valign="top" style="text-align:left;" class="value">
    83                                 <ul>
    84                                 <g:each var="a" in="${assetInstance.assetExtendedAttributes}">
    85                                     <li><g:link controller="assetExtendedAttributeDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
    86                                 </g:each>
    87                                 </ul>
    88                             </td>
    8987                           
    9088                        </tr>
     
    9896                   
    9997                        <tr class="prop">
     98                            <td valign="top" class="name">Section:</td>
     99                           
     100                            <td valign="top" class="value"><g:link controller="sectionDetailed" action="show" id="${assetInstance?.section?.id}">${assetInstance?.section?.encodeAsHTML()}</g:link></td>
     101                           
     102                        </tr>
     103                   
     104                        <tr class="prop">
     105                            <td valign="top" class="name">Asset Extended Attributes:</td>
     106                           
     107                            <td  valign="top" style="text-align:left;" class="value">
     108                                <ul>
     109                                <g:each var="a" in="${assetInstance.assetExtendedAttributes}">
     110                                    <li><g:link controller="assetExtendedAttributeDetailed" action="edit" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
     111                                </g:each>
     112                                </ul>
     113                            </td>
     114                           
     115                        </tr>
     116                   
     117                        <tr class="prop">
    100118                            <td valign="top" class="name">Maintenance Actions:</td>
    101119                           
     
    103121                                <ul>
    104122                                <g:each var="m" in="${assetInstance.maintenanceActions}">
    105                                     <li><g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
     123                                    <li><g:link controller="maintenanceActionDetailed" action="edit" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
    106124                                </g:each>
    107125                                </ul>
Note: See TracChangeset for help on using the changeset viewer.