source: trunk/grails-app/services/AssetTreeService.groovy @ 783

Last change on this file since 783 was 460, checked in by gav, 15 years ago

Refactor asset tree generation to improve speed by around 4 fold, part 2.

File size: 29.2 KB
RevLine 
[312]1class AssetTreeService {
2
3    boolean transactional = false
4
[322]5    def js = new JsUtilService()
[312]6
7    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
8
[457]9    /** General */
10    def nameDescriptionSeperator = ' -- '
11
[312]12    /** Html class and id settings */
[457]13    def buttonHtmlClass = 'tree_button'
14    def paneHtmlClass = 'overlayPane'
15    def paneHtmlId = 'assetTreePane'
16    def paneCloseHtmlClass = 'pane_close'
17    def tableDivHtmlClass = 'tree'
18    def tableHtmlId = 'assetTreeTable'
19    def tableLoadingImgId = 'assetTreeLoadingImg'
[312]20
[457]21    /** Imgs */
22    def treeRootImg = ''
23    def addImg = ''
24    def copyImg = ''
25    def bulletTreePlusImg = ''
26    def bulletTreeMinusImg = ''
27    def dashImg = ''
28    def closeImg = ''
29
30    /** Urls */
31    def assetTreeActionUrl = ''
32    def saveAssetTreeStatusActionUrl = ''
33
34    /** Links */
35    def siteCreateBaseLink = ''
36    def siteShowBaseLink = ''
37    def siteEditBaseLink = ''
38    def sectionCreateBaseLink = ''
39    def sectionShowBaseLink = ''
40    def sectionEditBaseLink = ''
41    def assetCreateBaseLink = ''
42    def assetShowBaseLink = ''
43    def assetEditBaseLink = ''
44    def assetCopyBaseLink = ''
45    def assetSubItemCreateBaseLink = ''
46    def assetSubItemCreateWithParentBaseLink = ''
47    def assetSubItemShowBaseLink = ''
48    def assetSubItemEditBaseLink = ''
49
50    /**
51    * Initialise some class wide variables.
52    * This has been done to optimise since g.link and g.resource calls are expensive.
53    * This can't be done by class construction since some of the metaclass stuff is not available yet, e.g. 'out' etc.
54    * Initialise can't be called from BootStrap.
55    */
56    def initialise() {
57        log.debug "Initialise asset tree variables."
58
59        // Imgs.
60        treeRootImg = g.resource(dir:'images/skin',file:'chart_organisation.png')
61        addImg = g.resource(dir:'images/skin',file:'database_add.png')
62        copyImg = g.resource(dir:'images/skin',file:'page_copy.png')
63        bulletTreePlusImg = g.resource(dir:'images/skin',file:'bullet_tree_plus.png')
64        bulletTreeMinusImg = g.resource(dir:'images/skin',file:'bullet_tree_minus.png')
65        dashImg = g.resource(dir:'images/skin',file:'hline_short.png')
66        closeImg = g.resource(dir:'images/skin',file:'cross.png')
67
68        // Urls.
69        assetTreeActionUrl = g.createLink(controller: 'assetDetailed', action: 'assetTree')
70        saveAssetTreeStatusActionUrl = g.createLink(controller: 'assetDetailed', action: 'saveAssetTreeStatus')
71
72        // Links
73        siteCreateBaseLink = g.createLink(controller: 'siteDetailed', action: 'create').toString()
74        siteShowBaseLink = g.createLink(controller: 'siteDetailed', action: 'show').toString()
75        siteEditBaseLink = g.createLink(controller: 'siteDetailed', action: 'edit').toString()
76        sectionCreateBaseLink = g.createLink(controller: 'sectionDetailed', action: 'create').toString()
77        sectionShowBaseLink = g.createLink(controller: 'sectionDetailed', action: 'show').toString()
78        sectionEditBaseLink = g.createLink(controller: 'sectionDetailed', action: 'edit').toString()
79        assetCreateBaseLink = g.createLink(controller: 'assetDetailed', action: 'create').toString()
80        assetShowBaseLink = g.createLink(controller: 'assetDetailed', action: 'show').toString()
81        assetEditBaseLink = g.createLink(controller: 'assetDetailed', action: 'edit').toString()
82        assetCopyBaseLink = g.createLink(controller: 'assetDetailed', action: 'copy').toString()
83        assetSubItemCreateBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'create').toString()
84        assetSubItemCreateWithParentBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'create').toString()
85        assetSubItemShowBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'show').toString()
86        assetSubItemEditBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'edit').toString()
87        // Success.
88        return true
[312]89    }
90
[317]91    /** Name and Description Formatting */
92
93    def name(obj) {
94        obj.name.encodeAsHTML()
95    }
96
97    def description(obj) {
98        def s =  obj.description.encodeAsHTML()
[457]99        s = s? (nameDescriptionSeperator + s) : ''
[317]100    }
101
[312]102    /**
[457]103    * Build and return the asset tree button.
104    * Built here instead of directly in the taglib since we may need to initialise.
105    */
106    def buildAssetTreeButton(attrs) {
107
108        // Self initialisation ;-)
109        if(!treeRootImg)
110            initialise()
111
112        def sw = new StringWriter()
113        def mkp = new groovy.xml.MarkupBuilder(sw)
114
115        mkp.div(class: buttonHtmlClass) {
116            a( href: hrefShowPane() ) {
117                img(src: treeRootImg)
118            }
119        } // mkp
120
121        return sw.toString()
122    }
123
124    /**
125    * Build and return the empty asset tree pane, ready for populating by ajax call to buildAssetTree.
126    * Built here instead of directly in the taglib since we may need to initialise.
127    */
128    def buildAssetTreePane(attrs) {
129
130        // Self initialisation ;-)
131        if(!treeRootImg)
132            initialise()
133
134        def sw = new StringWriter()
135        def mkp = new groovy.xml.MarkupBuilder(sw)
136
137        mkp.div(class: paneHtmlClass, id: paneHtmlId, style: 'display:none;') {
138            div(class: paneCloseHtmlClass) {
139                a( href: js.toggle(paneHtmlId) ) {
140                    img(src: closeImg)
141                }
142            }
143
144            div(class: tableDivHtmlClass) {
145                table(id: tableHtmlId) {
146                    tr() {
147                        td(valign: 'top', class: 'value') {
148                            ul() {
149                                img(src: treeRootImg, id: tableLoadingImgId, alt: 'TreeRoot')
150                                li() {
151                                } // li
152                            } // ul
153                        } // td
154                    } // tr
155                } // table
156            } // div
157        } // mkp
158
159        return sw.toString()
160
161    } // buildAssetPane
162
163    /**
[312]164    * Build and return the asset tree table.
[457]165    * To be used in conjunction with AssetTreeTagLib which inserts the wrapper div built by buildAssetTreePane().
[312]166    * This table replaces the contents of the wrapper div.
167    * @returns The asset tree table as a String
168    */
169    def buildAssetTree(params, session) {
170
[457]171        def startedAt = System.currentTimeMillis()
[312]172
[457]173        // Self initialisation ;-)
174        if(!treeRootImg)
175            initialise()
176
177        def sites = Site.withCriteria {
178            eq("isActive", true)
179        }
180
[312]181        def visibleBranches = session.assetTreeVisibleBranches ? session.assetTreeVisibleBranches.tokenize(',') : []
182
183        def branchStyle = { branchId ->
184            if(visibleBranches.contains(branchId))
185                ''
186            else
187                'display:none;'
188        }
189
190        def branchImg = { branchId ->
191            if(visibleBranches.contains(branchId))
[457]192                bulletTreeMinusImg
[312]193            else
[457]194                bulletTreePlusImg
[312]195        }
196
197        def divIdCount = 0
198        def divId = ''
199        def nextDivId = {
200            divIdCount++
201            divId = 'assetTreeBranch'+divIdCount
202        }
203
204        def sw = new StringWriter()
[457]205        def mkp = new groovy.xml.MarkupBuilder(sw)
[312]206
207        // Offer a site create link if no sites are found.
208        if(!sites) {
[457]209            mkp.div(class: tableDivHtmlClass) {
[312]210
[457]211                div(class: paneCloseHtmlClass) {
212                    a( href: js.toggle(paneHtmlId) ) {
213                        img(src: closeImg)
[312]214                    }
215                }
216
[457]217                table(id: tableHtmlId) {
[312]218                    tr() {
219                        td( valign: 'top', class: 'value') {
220                            ul() {
[457]221                                img(src: treeRootImg, alt: 'TreeRoot')
[312]222                                li() {
[460]223                                    a(href: siteCreateBaseLink) {
[457]224                                        img(src: addImg, alt: 'Add', title: 'Add Site')
[312]225                                    }
226                                } // li
227                            } // ul
228                        } // td
229                    } // tr
230                } // table
231
232                div( class: 'buttons') {
233                    span(class: 'button') {
[457]234                        input( type: 'button', value: g.message(code: 'default.close.text'), onclick: js.toggle(paneHtmlId, "onclick") )
[312]235                    }
236                } // button div
237            } // mkp
238            return sw.toString()
239        } // if(!sites)
240
241
242        // The main populated table.
243        /// @todo: use a loop for the subItem levels.
[457]244        mkp.div(class: tableDivHtmlClass) {
[312]245
[457]246            div(class: paneCloseHtmlClass) {
[312]247                a( href: hrefHideAndSavePane() ) {
[457]248                    img(src: closeImg)
[312]249                }
250            }
251
[457]252            table(id: tableHtmlId) {
[312]253                tr() {
254                    td(valign: 'top', class: 'value') {
255                        ul() {
[457]256                            img(src: treeRootImg, alt: 'TreeRoot')
[312]257                            for(site in sites.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
258                                li() {
259                                    if(site.sections) {
[322]260                                        a(href: toggleBranch(nextDivId()) ) {
[312]261                                            img( src: branchImg(divId), id: divId+'img' )
262                                        }
263                                    }
264                                    else
[457]265                                        img(src: dashImg)
[312]266                                    a( href: siteShowLink(site.id), onclick: onclickHideAndSavePane() ) {
[317]267                                        yieldUnescaped( name(site)  )
[312]268                                    }
[317]269                                    yieldUnescaped( description(site)  )
[312]270                                    a(href: sectionCreateLink(site.id), onclick: onclickHideAndSavePane()) {
[457]271                                        img(src: addImg, alt: 'Add', title: 'Add Section')
[312]272                                    }
273                                }
274                                if(site.sections) {
275                                    div( id: divId, style: branchStyle(divId) ) {
276                                        ul() {
277                                            for(section in site.sections.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
278                                                li() {
279                                                    if(section.assets) {
[322]280                                                        a( href: toggleBranch(nextDivId()) ) {
[312]281                                                            img(src: branchImg(divId), id: divId+'img' )
282                                                        }
283                                                    }
284                                                    else
[457]285                                                        img(src: dashImg)
[312]286                                                    a( href: sectionShowLink(section.id), onclick: onclickHideAndSavePane() ) {
[317]287                                                        yieldUnescaped( name(section) )
[312]288                                                    }
[317]289                                                    yieldUnescaped( description(section)  )
[312]290                                                    a(href: assetCreateLink(section.id), onclick: onclickHideAndSavePane()) {
[457]291                                                        img(src: addImg, alt: 'Add', title: 'Add Asset')
[312]292                                                    }
293                                                }
294
295                                                if(section.assets) {
296                                                    div( id: divId, style: branchStyle(divId) ) {
297                                                        ul() {
298                                                            for(asset in section.assets.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
299                                                                li() {
300                                                                    if(asset.assetSubItems) {
[322]301                                                                        a( href: toggleBranch(nextDivId()) ) {
[312]302                                                                            img(src: branchImg(divId), id: divId+'img' )
303                                                                        }
304                                                                    }
305                                                                    else
[457]306                                                                        img(src: dashImg)
[312]307                                                                    a( href: assetShowLink(asset.id), onclick: onclickHideAndSavePane() ) {
[317]308                                                                        yieldUnescaped( name(asset) )
[312]309                                                                    }
[317]310                                                                    yieldUnescaped( description(asset) )
[312]311                                                                    a(href: assetSubItemCreateLink(asset.id), onclick: onclickHideAndSavePane()) {
[457]312                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
[312]313                                                                    }
314                                                                    a(href: assetCopyLink(asset.id), onclick: onclickHideAndSavePane()) {
[457]315                                                                        img(src: copyImg, alt: 'Add', title: 'Copy Asset')
[312]316                                                                    }
317                                                                } // li
318
319                                                                if(asset.assetSubItems) {
320                                                                    div( id: divId, style: branchStyle(divId) ) {
321                                                                        ul() {
322                                                                            for(assetSubItemL1 in asset.assetSubItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
323                                                                                li() {
324                                                                                    if(assetSubItemL1.subItems) {
[322]325                                                                                        a( href: toggleBranch(nextDivId()) ) {
[312]326                                                                                            img(src: branchImg(divId), id: divId+'img' )
327                                                                                        }
328                                                                                    }
329                                                                                    else
[457]330                                                                                        img(src: dashImg)
[312]331                                                                                    a( href: assetSubItemShowLink(assetSubItemL1.id), onclick: onclickHideAndSavePane() ) {
[317]332                                                                                        yieldUnescaped( name(assetSubItemL1) )
[312]333                                                                                    }
[317]334                                                                                    yieldUnescaped( description(assetSubItemL1) )
[312]335                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL1.id), onclick: onclickHideAndSavePane()) {
[457]336                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
[312]337                                                                                    }
338                                                                                } // li
339
340                                                                                if(assetSubItemL1.subItems) {
341                                                                                    div( id: divId, style: branchStyle(divId) ) {
342                                                                                        ul() {
343                                                                                            for(assetSubItemL2 in assetSubItemL1.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
344                                                                                                li() {
345                                                                                                    if(assetSubItemL2.subItems) {
[322]346                                                                                                        a( href: toggleBranch(nextDivId()) ) {
[312]347                                                                                                            img( src: branchImg(divId), id: divId+'img' )
348                                                                                                        }
349                                                                                                    }
350                                                                                                    else
[457]351                                                                                                        img(src: dashImg)
[312]352                                                                                                    a( href: assetSubItemShowLink(assetSubItemL2.id), onclick: onclickHideAndSavePane() ) {
[317]353                                                                                                        yieldUnescaped( name(assetSubItemL2) )
[312]354                                                                                                    }
[317]355                                                                                                    yieldUnescaped( description(assetSubItemL2) )
[312]356                                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL2.id), onclick: onclickHideAndSavePane()) {
[457]357                                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
[312]358                                                                                                    }
359                                                                                                } // li
360
361                                                                                                if(assetSubItemL2.subItems) {
362                                                                                                    div( id: divId, style: branchStyle(divId) ) {
363                                                                                                        ul() {
364                                                                                                            for(assetSubItemL3 in assetSubItemL2.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
365                                                                                                                li() {
366                                                                                                                    if(assetSubItemL3.subItems) {
[322]367                                                                                                                        a( href: toggleBranch(nextDivId()) ) {
[312]368                                                                                                                            img( src: branchImg(divId), id: divId+'img' )
369                                                                                                                        }
370                                                                                                                    }
371                                                                                                                    else
[457]372                                                                                                                        img(src: dashImg)
[312]373                                                                                                                    a( href: assetSubItemShowLink(assetSubItemL3.id), onclick: onclickHideAndSavePane() ) {
[317]374                                                                                                                        yieldUnescaped( name(assetSubItemL3) )
[312]375                                                                                                                    }
[317]376                                                                                                                    yieldUnescaped( description(assetSubItemL3) )
[312]377                                                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL3.id), onclick: onclickHideAndSavePane()) {
[457]378                                                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
[312]379                                                                                                                    }
380                                                                                                                } // li
381
382                                                                                                                if(assetSubItemL3.subItems) {
383                                                                                                                    div( id: divId, style: branchStyle(divId) ) {
384                                                                                                                        ul() {
385                                                                                                                            for(assetSubItemL4 in assetSubItemL3.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
386                                                                                                                                li() {
387            //                                                                                                                         if(assetSubItemL4.subItems) {
[322]388            //                                                                                                                             a( href: toggleBranch(nextDivId()) ) {
[312]389            //                                                                                                                                 img( src: branchImg(divId), id: divId+'img' )
390            //                                                                                                                             }
391            //                                                                                                                         }
392            //                                                                                                                         else
[457]393                                                                                                                                    img(src: dashImg)
[312]394                                                                                                                                    a( href: assetSubItemShowLink(assetSubItemL4.id), onclick: onclickHideAndSavePane() ) {
[317]395                                                                                                                                        yieldUnescaped( name(assetSubItemL4) )
[312]396                                                                                                                                    }
[317]397                                                                                                                                    yieldUnescaped( description(assetSubItemL4) )
[312]398            //                                                                                                                         a(href: assetSubItemCreateWithParentLink(assetSubItemL4.id), onclick: onclickHideAndSavePane()) {
[457]399            //                                                                                                                             img(src: addImg, alt: 'Add', title: 'Add Sub Item')
[312]400            //                                                                                                                         }
401                                                                                                                                } // li
402
403                                                                                                                            } // assetSubItemL4
404                                                                                                                        } // ul
405                                                                                                                    } // div
406                                                                                                                } // if(assetSubItemL3.subItems)
407
408
409                                                                                                            } // assetSubItemL3
410                                                                                                        } // ul
411                                                                                                    } // div
412                                                                                                } // if(assetSubItemL2.subItems)
413
414                                                                                            } // assetSubItemL2
415                                                                                        } // ul
416                                                                                    } // div
417                                                                                } // if(assetSubItemL1.subItems)
418
419                                                                            } // assetSubItemL1
420                                                                        } // ul
421                                                                    } // div
422                                                                } // if(asset.assetSubItems)
423
424                                                            } // assets
425                                                        } // ul
426                                                    } // div
427                                                } // if(section.assets)
428
429                                            } //sections
430                                        } // ul
431                                    } // div
432                                } // if(site.sections)
433                            } // sites
434                        } // ul
435                    } // td
436                } // tr
437            } // table
438
439            div( class: 'buttons') {
440                span(class: 'button') {
441                    input( type: 'button', value: g.message(code: 'default.close.text'), onclick: onclickHideAndSavePane() )
442                }
443            }
444
445        } // mkp
446
[457]447        def totalTime = (System.currentTimeMillis() - startedAt)/1000
448        log.debug "Total time to build asset tree: " + totalTime + "sec."
[312]449        return sw.toString()
450
451    } // buildAssetTree
452
453    /** js calls */
454
455    def hrefShowPane() {
[457]456        'javascript: showAssetTreePane(\"assetTreePane\", \"assetTreeLoadingImg' +'\", \"' + assetTreeActionUrl + '\");'
[312]457    }
458
459    def onclickHideAndSavePane() {
[457]460        'return hideAssetTreePane(\"assetTreePane\", \"assetTreeTable' + '\", \"' + saveAssetTreeStatusActionUrl + '\");'
[312]461    }
462
463    def hrefHideAndSavePane() {
[457]464        'javascript: hideAssetTreePane(\"assetTreePane\", \"assetTreeTable' + '\", \"' + saveAssetTreeStatusActionUrl + '\");'
[312]465    }
466
[322]467    def toggleBranch(divId) {
[457]468        js.toggleWithImg(divId, divId + 'img', bulletTreeMinusImg, bulletTreePlusImg)
[312]469    }
470
471    /** Links */
472
473    def siteShowLink(id) {
[457]474        siteShowBaseLink + '/' + id
[312]475    }
476
477    def siteEditLink(id) {
[457]478        siteEditBaseLink + '/' + id
[312]479    }
480
481    def sectionCreateLink(siteId) {
[457]482        sectionCreateBaseLink + '?site.id=' + siteId
[312]483    }
484
485    def sectionShowLink(id) {
[457]486        sectionShowBaseLink + '/' + id
[312]487    }
488
489    def sectionEditLink(id) {
[457]490        sectionEditBaseLink + '/' + id
[312]491    }
492
493    def assetCreateLink(sectionId) {
[457]494        assetCreateBaseLink + '?section.id=' + sectionId
[312]495    }
496
497    def assetShowLink(id) {
[457]498        assetShowBaseLink + '/' + id
[312]499    }
500
501    def assetEditLink(id) {
[457]502        assetEditBaseLink + '/' + id
[312]503    }
504
505    def assetCopyLink(id) {
[457]506        assetCopyBaseLink + '?assetToCopy.id=' + id
[312]507    }
508
509    def assetSubItemCreateLink(assetId) {
[457]510        assetSubItemCreateBaseLink + '?asset.id=' + assetId
[312]511    }
512
513    def assetSubItemCreateWithParentLink(parentItemId) {
[457]514        assetSubItemCreateWithParentBaseLink + '?parentItem.id=' + parentItemId
[312]515    }
516
517    def assetSubItemShowLink(id) {
[457]518        assetSubItemShowBaseLink + '/' + id
[312]519    }
520
521    def assetSubItemEditLink(id) {
[457]522        assetSubItemEditBaseLink + '/' + id
[312]523    }
524
525} // end class
Note: See TracBrowser for help on using the repository browser.