layout.html 11.5 KB
Newer Older
LE GAC Renaud's avatar
LE GAC Renaud committed
1
{{
2 3 4 5 6 7 8

    #--------------------------------------------------------------------------
    # The python controller return:
    #   - collection_logs (list of MsgCollection) one for each collection
    #   - harvester (Storage)
    #   - logs (list of MSg) one for each publication
    #   - selector (Selector)
9 10
    #--------------------------------------------------------------------------
    #
11
    # prepare the data:
12 13
    #    - configure the Ext.data.Array for the statistics
    #    - configure the Ext.data.Array for the logs
14 15 16 17
    #    - the title of the page
    #    - the DIV block
    #    - the HTML page footer
    #    - export python variable to the javascript
18 19 20
    #
    #--------------------------------------------------------------------------
    import json
21
    from datetime import datetime
22

23 24 25 26 27
    #
    # configure the Ext.data.Array for the statistics
    # transform the collection_logs in a series of counters per collection
    #
    cfg = dict(sorters=['collection'])
28

29 30 31 32 33 34 35 36 37 38 39
    cfg['fields'] = [{'name': 'add', 'type': 'int'},
                     {'name': 'error', 'type': 'string'},
                     {'name': 'found', 'type': 'int'},
                     {'name': 'idle', 'type': 'int'},
                     {'name': 'lost', 'type': 'int'},
                     {'name': 'modify', 'type': 'int'},
                     {'name': 'reject', 'type': 'int'},
                     {'name': 'title', 'type': 'string'},
                     {'name': 'url', 'type': 'string'}]

    cfg['data'] = []
40

41
    for collection in collection_logs:
42

43 44
        # count database action for this collection
        count = Storage(idle=0, load=0, modify=0, process=0, reject=0)
45

46 47 48 49 50 51
        for row in logs:
            if row.collection == collection.title:
                count.process += 1
                count[row.action] += 1
            pass
        pass
52

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
        stat = [count.load,
                collection.error,
                collection.found,
                count.idle,
                collection.found - count.process,
                count.modify,
                count.reject,
                collection.title,
                collection.url_hb()]

        cfg['data'].append(stat)
    pass

    cfg_statStore = json.dumps(cfg)

    #
    # configure the Ext.data.Array for the logs
    #
    cfg = dict(groupField='txt',
               sorters=['txt', 'title'])
73

74 75 76 77 78
    cfg['fields'] = [{'name': 'collection', 'type': 'string'},
                     {'name': 'title', 'type': 'string'},
                     {'name': 'txt', 'type': 'string'},
                     {'name': 'url', 'type': 'string'},
                     {'name': 'year', 'type': 'string'}]
79

80 81 82
    cfg['data'] = []
    for row in logs:
        cfg['data'].append([row.collection,
83
                            row.title,
84 85 86 87
                            row.txt,
                            row.url,
                            row.year])
    pass
88

89 90 91
    cfg_logsStore = json.dumps(cfg)

    #
92
    # Write the Title on the HTML page
93
    #
94 95 96
    period = ""
    if selector.year_start and selector.year_end:
        period = T("from %s to %s") % (selector.year_start, selector.year_end)
LE GAC Renaud's avatar
LE GAC Renaud committed
97

98 99
    elif selector.year_start:
        period = str(selector.year_start)
100

101
    pass
102

103 104 105 106
    project = ""
    if selector.id_projects:
        project = db.projects[selector.id_projects].project
    pass
107

108
    title = "%s %s %s" % (harvester.controller.title(), project, period)
109

110 111 112 113 114
    style = ["font-size: 12px;",
             "font-variant: small-caps;",
             "margin-left: 10px;",
             "margin-bottom: 3ex;",
             "margin-top: 2ex;"]
115

116
    response.write(P(title, _style="".join(style)))
117

118 119 120
    #
    # the DIV blocks, one for each  grid
    #
121 122
    divstat = "grid-%s" % id(cfg_statStore)
    divlogs = "grid-%s" % id(cfg_logsStore)
123

124 125
    response.write(DIV(_id=divstat))
    response.write(DIV(_id=divlogs))
126

127 128 129 130 131
    #
    # the footer, processing time of the request
    #
    delta = (datetime.now()-request.now).total_seconds()
    delta = T('Harvester took %s seconds') % round(delta, 2)
132

133 134 135 136
    style = ["font-size: 10px;",
             "margin-left: 10px;",
             "margin-bottom: 3ex;",
             "margin-top: 2ex;"]
137

138 139 140 141 142 143 144
    response.write(P(delta, _style="".join(style)))

    #
    # Export python variables to the javascript
    #
    jsvars = ["cfgStatStore = %s" % cfg_statStore,
              "cfgLogsStore = %s" % cfg_logsStore,
145 146 147 148 149 150
              "divstat = '%s'" % divstat,
              "divlogs = '%s'" % divlogs,
              "gridStat",
              "gridLog",
              "harvester = %s" % json.dumps(harvester.as_dict()),
              "menu",
151 152 153
              "trAction = '%s'" % T('Action'),
              "trAdded = '%s'" % T('Added'),
              "trCollection = '%s'" % T('Collection'),
154
              "trEditAndInsert = '%s'" % T('Edit and insert'),
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
              "trError = '%s'" % T('Error'),
              "trExisting = '%s'" % T('Existing'),
              "trFound = '%s'" % T('Found'),
              "trLost = '%s'" % T('Lost'),
              "trModified = '%s'" % T('Modified'),
              "trRejected = '%s'" % T('Rejected'),
              "trTitle = '%s'" % T('Title'),
              "trStatistics = '%s'" % T('Statistics'),
              "trYear = '%s'" % T('Year')]

    jsvars = "    var %s;" % ',\n'.join(jsvars)
    response.write(SCRIPT(jsvars), escape=False)

}}
<script type="text/javascript">
170 171

    /**
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
     * Launch the Edit and Insert wizard
     */
    function onEditAndInsert() {

        "use strict";

        var host = this.harvester.host,
            li,
            mask,
            record = this.gridLog.getSelectionModel().getSelection()[0],
            record_id;

        // mask the main ViewPort during the data transfer
        //
        // NOTE 141112:
        // the loadMask option of the component should do the job
        // but I never succeed with Ext JS 4.2.1. Therefore it is done by hand
        //
        mask = Ext.create('Ext.LoadMask', {
            msg: 'Loading data from ' + host + '...',
            target: Ext.ComponentQuery.query('xviewport')[0]
        });
        mask.show();

        // extract the record identifier from the publication URL
        // e.g "http://cds.cern.ch/record/1692474"
        li = record.get('url').split("/");
        record_id = li[li.length - 1];

        // launch the EditAndInsert wizard using a loader
        // NOTE 141112: the success function is used to remove the mask
        //
        Ext.create('Ext.Component', {
            loader: {
                url: 'harvest/edit_insert',
                params: {
                    Edit_insert_selectorId_teams: this.harvester.id_teams,
                    Edit_insert_selectorId_projects: this.harvester.id_projects,
                    Edit_insert_selectorHost: host,
                    Edit_insert_selectorRecord_id: record_id,
                    Edit_insert_selectorController: this.harvester.controller,
                    Edit_insert_selectorId_categories: this.harvester.id_categories
                },
                autoLoad: true,
                failure: function () {
                    Ext.Msg.alert('Status', 'Data transfer from '+ host +' failed');
                },
                loadMask: false,
                scripts: true,
                success: function () {
                    mask.hide();
                },
                timeout: 60000
            },
            renderTo: Ext.getBody()
      });
    }

    /**
     * Renderer the publication title as an URL
232 233 234 235
     *
     * @param {Object} value
     * @param {Object} metadata
     * @param {Ext.data.Model} record
236 237 238 239
     * @param {Number} rowIndex
     * @param {Number} colIndex
     * @param {Ext.data.Store} store
     * @param {Ext.view.view} view
240 241
     *
     */
242
    function rTitle(value, metadata, record) {
LE GAC Renaud's avatar
LE GAC Renaud committed
243 244 245 246 247 248 249 250 251 252 253 254 255

        var pattern = '<a href="{0}" target="_blank">{1}</a>',
            rep,
            title = record.get('title'),
            url = record.get('url');

        if (url.length > 0) {
            rep = Ext.String.format(pattern, url, title);
        } else {
            rep = title;
        }

        return rep;
256 257
    }

258 259 260 261 262 263 264 265 266 267 268 269
    /**
     * Renderer the total label
     *
     * @param {Object} value
     * @param {Object} metadata
     * @param {Ext.data.Model} record
     * @param {Number} rowIndex
     * @param {Number} colIndex
     * @param {Ext.data.Store} store
     * @param {Ext.view.view} view
     *
     */
270 271 272 273 274
    function rTotal() {
        return 'Total';
    }

    //
275
    // instantiate the grid for the STAT
276
    //
277
    gridStat = Ext.create('Ext.grid.Panel', {
278 279 280 281 282 283 284 285
        title: trStatistics,
        store: Ext.create('Ext.data.ArrayStore', cfgStatStore),
        columns: [
            {xtype: 'rownumberer'},
            {
                text: trCollection,
                dataIndex: 'title',
                flex: 4,
LE GAC Renaud's avatar
LE GAC Renaud committed
286
                renderer: rTitle,
287 288 289 290 291 292 293 294 295 296
                summaryRenderer: rTotal
            },
            {text: trFound, dataIndex: 'found', flex: 1, summaryType: 'sum'},
            {text: trExisting, dataIndex: 'idle', flex: 1, summaryType: 'sum'},
            {text: trAdded, dataIndex: 'add', flex: 1, summaryType: 'sum'},
            {text: trModified, dataIndex: 'modify', flex: 1, summaryType: 'sum'},
            {text: trRejected, dataIndex: 'reject', flex: 1, summaryType: 'sum'},
            {text: trLost, dataIndex: 'lost', flex: 1, summaryType: 'sum'},
            {text: trError, dataIndex: 'error', flex: 1}
        ],
LE GAC Renaud's avatar
LE GAC Renaud committed
297
        collapsible: true,
298 299
        features: [{ftype:'summary'}],
        forceFit: true,
300
        padding: "0 40 20 30",
301
        renderTo: divstat
302 303
    });

304
    //
305
    // instantiate the grid for the LOGs
306 307 308
    // The row are group per database action and sorted by title.
    // Each title is rendered as an URL pointing to the publication
    // in the harvester repository
309
    //
310
    gridLog = Ext.create('Ext.grid.Panel', {
311 312 313
        store: Ext.create('Ext.data.ArrayStore', cfgLogsStore),
        columns: [
            {xtype: 'rownumberer'},
314
            {text: trTitle, dataIndex: 'title', flex: 3, renderer: rTitle},
315 316 317 318 319 320 321 322
            {text: trAction, dataIndex: 'txt', flex: 1, hidden: true},
            {text: trCollection, dataIndex: 'collection', flex: 1, hidden: true},
            {text: trYear, dataIndex: 'year', flex: 1, hidden: true}
        ],
        features: [
            {ftype:'grouping', groupHeaderTpl: '{name}', startCollapsed: true}
        ],
        forceFit: true,
323
        padding: "10 40 20 30",
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
        renderTo: divlogs
    });

    //
    // instantiate the context menu to launch the "Edit and Insert" wizard
    //
    menu = Ext.create('Ext.menu.Menu', {
        items : [{
            text: trEditAndInsert,
            iconCls: 'xaction-create',
            handler: onEditAndInsert,
            scope: this
        }]
    });

    gridLog.on('itemcontextmenu', function(view, record, item, index, event) {
        event.stopEvent();
341 342 343 344 345 346 347

        // FIX EXT JS 4.2.1
        // In that version the selection of the row is wrong when the grouping
        // feature is activated. It has been corrected in 4.2.2.
        // The next line fixes this bug.
        // (from www.sencha.com/forum/showthread.php?264961-Grid-Grouping-Bug)
        view.getSelectionModel().select(view.dataSource.data.get(item.getAttribute('data-recordid')));
348 349 350 351 352 353 354 355 356 357 358
        menu.showAt(event.getXY());
    });

    // inhibit context menu on the grid header
    gridLog.on("headercontextmenu", function(ct, column, event){
        event.stopEvent();
    });

    // inhibit context menu on the rest of the panel
    gridLog.body.up('.x-panel-body').on('contextmenu', function(event) {
        event.stopEvent();
359 360
    });

361
</script>