<commit_before>define(['marionette',
    'views/form',
    'models/container',
    'models/protein',
    'collections/proteins',
    'models/sample',
    'collections/samples',
    'modules/shipment/views/puck',
    'modules/shipment/views/sampletable',

    'modules/shipment/models/cache',
    'modules/shipment/views/pastefrom',
    'modules/shipment/collections/distinctproteins',

    'modules/shipment/collections/platetypes',
    'modules/shipment/views/plate',
    'modules/shipment/views/singlesample',

    'modules/imaging/collections/schedules',
    'modules/imaging/views/scheduleview',

    'modules/imaging/collections/screens',
    'modules/imaging/collections/screencomponentgroups',
    'modules/imaging/collections/screencomponents',
    'modules/imaging/views/screencomponentgroup',

    'collections/users',

    'tpl!templates/shipment/containeradd.html',
    'tpl!templates/shipment/sampletablenew.html',
    'tpl!templates/shipment/sampletablerownew.html'], function(Marionette,

    FormView,
    Container,
    Protein,
    Proteins,
    Sample,
    Samples,
    PuckView,
    SampleTableView,
    Cache,
    PastFromView,
    DistinctProteins,
    PlateTypes,
    PlateView,
    SingleSample,

    Schedules,
    ScheduleView,

    Screens,
    ScreenComponentGroups,
    ScreenComponents,
    ScreenGroupView,

    Users,

    template, table, row){

    // Use Location as idAttribute for this table
    var LocationSample = Sample.extend({
        idAttribute: 'LOCATION',
    })

    //return Marionette.LayoutView.extend({
    return FormView.extend({
        setupOnConstruct: false,
        className: 'content',
        template: template,
        regions: {
            table: '.table',
            puck: '.puck',
            single: '.singlesamp',
            grp: '.group',
        },

        templateHelpers: function() {
            return {
                SHIPPINGID: this.dewar.get('SHIPPINGID'),
                SHIPMENT: this.dewar.get('SHIPPINGNAME'),
                DEWAR: this.dewar.get('CODE'),
            }
        },

        ui: {
            name: 'input[name=NAME]',
            type: 'select[name=CONTAINERTYPE]',
            pc: '.puck_controls',
            ext: '.extrainfo',
            schedule: 'select[name=SCHEDULEID]',
            screen: 'select[name=SCREENID]',
            pid: 'select[name=PERSONID]',
        },

        events: {
            'click .pf': 'pasteFrom',

            'change .samples input': 'cacheContainer',
            'keyup .samples input': 'cacheContainer',
            'blur .samples input': 'cacheContainer',
            'change .samples select': 'cacheContainer',
            'keyup .samples select': 'cacheContainer',
            'blur .samples select': 'cacheContainer',

            'click a.clonepuck': 'clonePuck',
            'click a.clearpuck': 'clearPuck',
            'click a.autofill': 'autoFill',

            'change @ui.type': 'setType',

            'click @ui.ext': 'toggleExtra',

            'keypress .ui-combobox input': 'excelNavigate',
            'keypress input.sname': 'excelNavigate',
            'keypress select.sg': 'excelNavigate',
            'keypress input.barcode': 'excelNavigate',
            'keypress input.comments': 'excelNavigate',

            'click a.view_sch': 'viewSchedule',
            'click a.edit_user': 'editUser',
            'change @ui.screen': 'selectScreen',
            'change @ui.pid': 'checkPerson',
        },

        checkPerson: function() {
            var u = this.users.findWhere({ PERSONID: this.ui.pid.val() })
            console.log('check p', u)
            if (u) {
                if (!u.get('EMAILADDRESS')) {
                    this.ui.pid.addClass('invalid')
                    this.ui.pid.after('Please update your email address by clicking view')

                } else {
                    this.ui.pid.removeClass('invalid')
                    this.ui.pid.siblings('span.emsg').remove()
                }
            }
        },

        editUser: function(e) {
            e.preventDefault()
            app.trigger('user:show', this.ui.pid.val())
        },

        getScreen: function() {
            return this.ui.screen.val()
        },

        selectScreen: function(e) {
            this.screencomponents.fetch()
            this.screencomponentgroups.fetch().done(this.assignScreen.bind(this))
        },

        assignScreen: function(e) {
            this.samples.each(function(s) {
                var w = this.type.getWell(s.get('LOCATION'))
                var g = this.screencomponentgroups.findWhere({ POSITION: (w+1).toString() })
                if (g) s.set({ SCREENCOMPONENTGROUPID: g.get('SCREENCOMPONENTGROUPID') }, { silent: true })
                    else s.set({ SCREENCOMPONENTGROUPID: null }, { silent: true })
            }, this)
        },

        viewSchedule: function(e) {
            e.preventDefault()
            var m = this.schedules.findWhere({ SCHEDULEID: this.ui.schedule.val() })
            if (m) app.dialog.show(new DialogView({ title: 'View Schedule', className: 'content', view: new ScheduleView({ dialog: true, model: m }), autoSize: true }))
        },

        excelNavigate: function(e) {
            var cl = '.'+e.target.className.replace(' fvalid', '').replace(' ferror', '').replace(/\s/g, '.')
            var group = $(cl)
            var cur = e.target
            var idx = group.index(cur)
            console.log(typeof(cl), cl, group,cur,idx)
            if(e.which == 13) {
                var dir = e.shiftKey ? -1 : 1
                if (idx < group.length) group.eq(idx+dir).focus()

                e.preventDefault()
            }
        },

        toggleExtra: function (e) {
            e.preventDefault()
            //this.$el.find('.extra').toggleClass('show')
            this.table.currentView.toggleExtra()
        },

        setType: function(e) {
            this.type = this.ctypes.findWhere({ name: this.ui.type.val() })
            this.type.set({ isSelected: true })
            this.model.set({
                CAPACITY: this.type.get('capacity'),
                CONTAINERTYPE: this.type.get('name'),
            })

            if (this.type.get('name') == 'Puck') {
                this.buildCollection()
                this.puck.$el.css('width', '25%')
                this.puck.show(new PuckView({ collection: this.samples }))
                this.stable = new SampleTableView({ proteins: this.proteins, gproteins: this.gproteins, collection: this.samples, childTemplate: row, template: table })
                this.table.show(this.stable)
                this.single.empty()
                this.grp.empty()
                this.ui.pc.show()
                this.$el.find('li.plate').hide()

            } else {
                if (!app.mobile()) this.puck.$el.css('width', '50%')
                this.puck.show(new PlateView({ collection: this.samples, type: this.type, showValid: true }))
                this.table.empty()
                this.stable.destroy()
                this.singlesample = new SingleSample({ proteins: this.proteins, gproteins: this.gproteins, platetypes: this.ctypes, samples: this.samples })
                this.single.show(this.singlesample)
                this.group = new ScreenGroupView({ components: this.screencomponents, editable: false })
                this.grp.show(this.group)
                this.ui.pc.hide()
                this.buildCollection()
                this.$el.find('li.plate').show()
            }
            console.log('samples', this.samples)
        },

        autoFill: function(e) {
            e.preventDefault()

            var acronym = this.getOption('visit')+'-p1'

            var p = this.proteins.findWhere({ ACRONYM: acronym })

            if (!p) {
                var p = new Protein({ ACRONYM: acronym })
                p.save({}, {
                    success: function() {
                        self.proteins.add(p)
                        self.$el.find('table.samples select[name=PROTEINID]').eq(0).combobox('value', p.get('PROTEINID')).trigger('change')
                        self.$el.find('table.samples input[name=NAME]').eq(0).val('x1').trigger('change')
                        self.clonePuck()
                    }
                })
            } else {
                this.$el.find('table.samples select[name=PROTEINID]').eq(0).combobox('value', p.get('PROTEINID')).trigger('change')
                this.$el.find('table.samples input[name=NAME]').eq(0).val('x1').trigger('change')
                this.clonePuck()
            }
        },

        clearPuck: function(e) {
            if (e) e.preventDefault()
            this.ui.name.val('')
            this.$el.find('.clear').each(function(i,c) { $(c).trigger('click') })
        },

        clonePuck: function(e) {
            if (e) e.preventDefault()
            if (this.stable) this.stable.cloneAll()
        },

        // Paste from old spreadsheet
        pasteFrom: function(e) {
            e.preventDefault()
            var pf = new PastFromView({ proteins: this.proteins })
            this.listenTo(pf, 'content:parsed', this.insertContent, this)
            app.dialog.show(pf)
        },

        insertContent: function(data) {
            this.samples.set(data.samples, { remove: false })
            this.table.currentView.render()
            this.ui.name.val(data.title)
        },

        // Cache container as user types
        cacheContainer: function() {
            console.log('caching')
            var hasData = false
            this.samples.each(function(s) {
                if (s.get('PROTEINID') > -1) hasData = true
                return
            })

            console.log('caching', hasData)
            if (!hasData) return

            var populated_samples = new Samples(this.samples.filter(function(s) { return s.get('PROTEINID') > -1 }))

            var data = {
                samples: populated_samples.toJSON(),
                title: this.ui.name.val(),
                time: new Date(),
            }

            this.cache.set({ data: data })
            this.cache.save({}, {
                success: function() {
                    app.alert({ message: 'Container contents last saved: '+new Date(), persist: 'saved', className: 'message notify', scrollTo: false })
                }
            })
        },

        loadContainerCache: function() {
            if (!this.cache.get('data')) return

            _.each(this.cache.get('data').samples, function(s) {
                var samp = this.samples.findWhere({ LOCATION: s.LOCATION })
                samp.get('components').reset(s.components)
                delete s.components
                samp.set(s)
            }, this)

            this.table.currentView.render()

            this.ui.name.val(this.cache.get('data').title)

            app.alert({ message: 'Container contents last saved: '+this.cache.get('data').time, persist: 'saved', className: 'message notify', scrollTo: false })
            console.log('loaded cache', this.cache)
        },

        // Callbacks for ajax requests
        success: function() {
            var self = this

            this.samples.each(function(s) {
                s.set({ CONTAINERID: this.model.get('CONTAINERID') }, { silent: true })
            }, this)

            var samples = new Samples(this.samples.filter(function(m) { return m.get('PROTEINID') > - 1 }))
            if (samples.length) {
                samples.save({
                    success: function() {
                        self.finished()
                    }
                })
            } else this.finished()
        },

        finished: function() {
            app.alert({ message: 'New container "'+this.model.get('NAME')+'" created, Click here to view it', persist: 'cadd'+this.model.get('CONTAINERID'), className: 'message notify' })
            this.clearPuck()
            this.model.set({ CONTAINERID: null })
        },

        error: function() {
            app.alert({ message: 'Something went wrong registering this container, please try again' })
        },

        createModel: function() {
            this.model = new Container({ DEWARID: this.dewar.get('DEWARID') })
        },

        selectSample: function() {
            if (this.type.get('name') != 'Puck') {
                var s = this.samples.findWhere({ isSelected: true })
                if (s) {
                    this.singlesample.setModel(s)
                    console.log('select sample', s)

                    var w = this.type.getWell(s.get('LOCATION'))
                    var g = this.screencomponentgroups.findWhere({ POSITION: (w+1).toString() })
                    if (g) this.group.setModel(g)
                        else this.group.setModel(null)
                }
            }
        },

        initialize: function(options) {
            this.ready = []

            this.dewar = options.dewar
            this.samples = new Samples(null, { model: LocationSample })
            this.listenTo(this.samples, 'selected:change', this.selectSample)
            //this.buildCollection()
            this.setupValidation()

            this.users = new Users()
            this.users.queryParams.all = 1
            this.users.queryParams.pid = app.proposal.get('PROPOSALID')
            this.ready.push(this.users.fetch())

            this.proteins = new DistinctProteins()
            this.ready.push(this.proteins.fetch())

            this.gproteins = new DistinctProteins()

            this.cache = new Cache({ name: 'container' })
            this.ready2 = this.cache.fetch()
            this.ctypes = PlateTypes

            this.cacheContainer = _.debounce(this.cacheContainer, 3000)

            var self = this
            this.schedules = new Schedules()
            this.schedules.fetch().done(function() {
                self.ui.schedule.html('<option value=""> - </option>'+self.schedules.opts())
            })

            this.screens = new Screens()
            this.screens.fetch().done(function() {
                self.ui.screen.html('<option value=""> - </option>'+self.screens.opts())
            })

            this.screencomponentgroups = new ScreenComponentGroups()
            this.screencomponentgroups.queryParams.scid = this.getScreen.bind(this)

            this.screencomponents = new ScreenComponents()
            this.screencomponents.queryParams.scid = this.getScreen.bind(this)

        },

        buildCollection: function() {
            var samples = []
            _.each(_.range(1,this.type.get('capacity')+1), function(i) {
                samples.push(new LocationSample({ LOCATION: i.toString(), PROTEINID: -1, new: true }))
            }, this)
            this.samples.reset(samples)
            this.samples.at(0).set('isSelected', true)
        },

        onShow: function() {
            this.getOption('visit') ? this.$el.find('a.autofill').show() : this.$el.find('a.autofill').hide()
            $.when.apply($, this.ready).then(this.doOnShow.bind(this))
        },

        doOnShow: function() {
            console.log('show new puck')
            //this.puck.show(new PuckView({ collection: this.samples }))
            //this.table.show(new SampleTableView({ proteins: this.proteins, collection: this.samples, childTemplate: row, template: table }))
            this.ui.type.html(this.ctypes.opts())
            this.setType()

            this.ready2.done(this.loadContainerCache.bind(this))

            this.ui.pid.html(this.users.opts()).val(app.personid)
            this.checkPerson()
        }
    })

})<commit_msg>MXSW-743<commit_after>define(['marionette',
    'views/form',
    'models/container',
    'models/protein',
    'collections/proteins',
    'models/sample',
    'collections/samples',
    'modules/shipment/views/puck',
    'modules/shipment/views/sampletable',

    'modules/shipment/models/cache',
    'modules/shipment/views/pastefrom',
    'modules/shipment/collections/distinctproteins',

    'modules/shipment/collections/platetypes',
    'modules/shipment/views/plate',
    'modules/shipment/views/singlesample',

    'modules/imaging/collections/schedules',
    'modules/imaging/views/scheduleview',

    'modules/imaging/collections/screens',
    'modules/imaging/collections/screencomponentgroups',
    'modules/imaging/collections/screencomponents',
    'modules/imaging/views/screencomponentgroup',

    'collections/users',

    'tpl!templates/shipment/containeradd.html',
    'tpl!templates/shipment/sampletablenew.html',
    'tpl!templates/shipment/sampletablerownew.html'], function(Marionette,

    FormView,
    Container,
    Protein,
    Proteins,
    Sample,
    Samples,
    PuckView,
    SampleTableView,
    Cache,
    PastFromView,
    DistinctProteins,
    PlateTypes,
    PlateView,
    SingleSample,

    Schedules,
    ScheduleView,

    Screens,
    ScreenComponentGroups,
    ScreenComponents,
    ScreenGroupView,

    Users,

    template, table, row){

    // Use Location as idAttribute for this table
    var LocationSample = Sample.extend({
        idAttribute: 'LOCATION',
    })

    //return Marionette.LayoutView.extend({
    return FormView.extend({
        setupOnConstruct: false,
        className: 'content',
        template: template,
        regions: {
            table: '.table',
            puck: '.puck',
            single: '.singlesamp',
            grp: '.group',
        },

        templateHelpers: function() {
            return {
                SHIPPINGID: this.dewar.get('SHIPPINGID'),
                SHIPMENT: this.dewar.get('SHIPPINGNAME'),
                DEWAR: this.dewar.get('CODE'),
            }
        },

        ui: {
            name: 'input[name=NAME]',
            type: 'select[name=CONTAINERTYPE]',
            pc: '.puck_controls',
            ext: '.extrainfo',
            schedule: 'select[name=SCHEDULEID]',
            screen: 'select[name=SCREENID]',
            pid: 'select[name=PERSONID]',
        },

        events: {
            'click .pf': 'pasteFrom',

            'change .samples input': 'cacheContainer',
            'keyup .samples input': 'cacheContainer',
            'blur .samples input': 'cacheContainer',
            'change .samples select': 'cacheContainer',
            'keyup .samples select': 'cacheContainer',
            'blur .samples select': 'cacheContainer',

            'click a.clonepuck': 'clonePuck',
            'click a.clearpuck': 'clearPuck',
            'click a.autofill': 'autoFill',

            'change @ui.type': 'setType',

            'click @ui.ext': 'toggleExtra',

            'keypress .ui-combobox input': 'excelNavigate',
            'keypress input.sname': 'excelNavigate',
            'keypress select.sg': 'excelNavigate',
            'keypress input.barcode': 'excelNavigate',
            'keypress input.comments': 'excelNavigate',

            'click a.view_sch': 'viewSchedule',
            'click a.edit_user': 'editUser',
            'change @ui.screen': 'selectScreen',
            'change @ui.pid': 'checkPerson',
        },

        checkPerson: function() {
            var u = this.users.findWhere({ PERSONID: this.ui.pid.val() })
            console.log('check p', u)
            if (u) {
                if (!u.get('EMAILADDRESS')) {
                    this.ui.pid.addClass('invalid')
                    this.ui.pid.after('Please update your email address by clicking view')

                } else {
                    this.ui.pid.removeClass('invalid')
                    this.ui.pid.siblings('span.emsg').remove()
                }
            }
        },

        editUser: function(e) {
            e.preventDefault()
            app.trigger('user:show', this.ui.pid.val())
        },

        getScreen: function() {
            return this.ui.screen.val()
        },

        selectScreen: function(e) {
            this.screencomponents.fetch()
            this.screencomponentgroups.fetch().done(this.assignScreen.bind(this))
        },

        assignScreen: function(e) {
            this.samples.each(function(s) {
                var w = this.type.getWell(s.get('LOCATION'))
                var g = this.screencomponentgroups.findWhere({ POSITION: (w+1).toString() })
                if (g) s.set({ SCREENCOMPONENTGROUPID: g.get('SCREENCOMPONENTGROUPID') }, { silent: true })
                    else s.set({ SCREENCOMPONENTGROUPID: null }, { silent: true })
            }, this)
        },

        viewSchedule: function(e) {
            e.preventDefault()
            var m = this.schedules.findWhere({ SCHEDULEID: this.ui.schedule.val() })
            if (m) app.dialog.show(new DialogView({ title: 'View Schedule', className: 'content', view: new ScheduleView({ dialog: true, model: m }), autoSize: true }))
        },

        excelNavigate: function(e) {
            var cl = '.'+e.target.className.replace(' fvalid', '').replace(' ferror', '').replace(/\s/g, '.')
            var group = $(cl)
            var cur = e.target
            var idx = group.index(cur)
            console.log(typeof(cl), cl, group,cur,idx)
            if(e.which == 13) {
                var dir = e.shiftKey ? -1 : 1
                if (idx < group.length) group.eq(idx+dir).focus()

                e.preventDefault()
            }
        },

        toggleExtra: function (e) {
            e.preventDefault()
            //this.$el.find('.extra').toggleClass('show')
            this.table.currentView.toggleExtra()
        },

        setType: function(e) {
            this.type = this.ctypes.findWhere({ name: this.ui.type.val() })
            this.type.set({ isSelected: true })
            this.model.set({
                CAPACITY: this.type.get('capacity'),
                CONTAINERTYPE: this.type.get('name'),
            })

            if (this.type.get('name') == 'Puck') {
                this.buildCollection()
                this.puck.$el.css('width', '25%')
                this.puck.show(new PuckView({ collection: this.samples }))
                this.stable = new SampleTableView({ proteins: this.proteins, gproteins: this.gproteins, collection: this.samples, childTemplate: row, template: table })
                this.table.show(this.stable)
                this.single.empty()
                this.grp.empty()
                this.ui.pc.show()
                this.$el.find('li.plate').hide()

            } else {
                if (!app.mobile()) this.puck.$el.css('width', '50%')
                this.puck.show(new PlateView({ collection: this.samples, type: this.type, showValid: true }))
                this.table.empty()
                this.stable.destroy()
                this.singlesample = new SingleSample({ proteins: this.proteins, gproteins: this.gproteins, platetypes: this.ctypes, samples: this.samples })
                this.single.show(this.singlesample)
                this.group = new ScreenGroupView({ components: this.screencomponents, editable: false })
                this.grp.show(this.group)
                this.ui.pc.hide()
                this.buildCollection()
                this.$el.find('li.plate').show()
            }
            console.log('samples', this.samples)
        },

        autoFill: function(e) {
            e.preventDefault()

            var acronym = this.getOption('visit')+'-p1'

            var p = this.proteins.findWhere({ ACRONYM: acronym })

            if (!p) {
                var p = new Protein({ ACRONYM: acronym })
                p.save({}, {
                    success: function() {
                        self.proteins.add(p)
                        self.$el.find('table.samples select[name=PROTEINID]').eq(0).combobox('value', p.get('PROTEINID')).trigger('change')
                        self.$el.find('table.samples input[name=NAME]').eq(0).val('x1').trigger('change')
                        self.clonePuck()
                    }
                })
            } else {
                this.$el.find('table.samples select[name=PROTEINID]').eq(0).combobox('value', p.get('PROTEINID')).trigger('change')
                this.$el.find('table.samples input[name=NAME]').eq(0).val('x1').trigger('change')
                this.clonePuck()
            }
        },

        clearPuck: function(e) {
            if (e) e.preventDefault()
            this.ui.name.val('')
            this.$el.find('.clear').each(function(i,c) { $(c).trigger('click') })
        },

        clonePuck: function(e) {
            if (e) e.preventDefault()
            if (this.stable) this.stable.cloneAll()
        },

        // Paste from old spreadsheet
        pasteFrom: function(e) {
            e.preventDefault()
            var pf = new PastFromView({ proteins: this.proteins })
            this.listenTo(pf, 'content:parsed', this.insertContent, this)
            app.dialog.show(pf)
        },

        insertContent: function(data) {
            this.samples.set(data.samples, { remove: false })
            this.table.currentView.render()
            this.ui.name.val(data.title)
        },

        // Cache container as user types
        cacheContainer: function() {
            console.log('caching')
            var hasData = false
            this.samples.each(function(s) {
                if (s.get('PROTEINID') > -1) hasData = true
                return
            })

            console.log('caching', hasData)
            if (!hasData) return

            var populated_samples = new Samples(this.samples.filter(function(s) { return s.get('PROTEINID') > -1 }))

            var data = {
                samples: populated_samples.toJSON(),
                title: this.ui.name.val(),
                time: new Date(),
            }

            this.cache.set({ data: data })
            this.cache.save({}, {
                success: function() {
                    app.alert({ message: 'Container contents last saved: '+new Date(), persist: 'saved', className: 'message notify', scrollTo: false })
                }
            })
        },

        loadContainerCache: function() {
            if (!this.cache.get('data')) return

            _.each(this.cache.get('data').samples, function(s) {
                var samp = this.samples.findWhere({ LOCATION: s.LOCATION })
                samp.get('components').reset(s.components)
                delete s.components
                samp.set(s)
            }, this)

            this.table.currentView.render()

            this.ui.name.val(this.cache.get('data').title)

            app.alert({ message: 'Container contents last saved: '+this.cache.get('data').time, persist: 'saved', className: 'message notify', scrollTo: false })
            console.log('loaded cache', this.cache)
        },

        // Callbacks for ajax requests
        success: function() {
            var self = this

            this.samples.each(function(s) {
                s.set({ CONTAINERID: this.model.get('CONTAINERID') }, { silent: true })
            }, this)

            var samples = new Samples(this.samples.filter(function(m) { return m.get('PROTEINID') > - 1 }))
            if (samples.length) {
                samples.save({
                    success: function() {
                        self.finished()
                    }
                })
            } else this.finished()
        },

        finished: function() {
            app.alert({ message: 'New container "'+this.model.get('NAME')+'" created, Click here to view it', persist: 'cadd'+this.model.get('CONTAINERID'), className: 'message notify' })
            this.clearPuck()
            this.model.set({ CONTAINERID: null })
        },

        error: function() {
            app.alert({ message: 'Something went wrong registering this container, please try again' })
        },

        createModel: function() {
            this.model = new Container({ DEWARID: this.dewar.get('DEWARID') })
        },

        selectSample: function() {
            if (this.type.get('name') != 'Puck') {
                var s = this.samples.findWhere({ isSelected: true })
                if (s) {
                    this.singlesample.setModel(s)
                    console.log('select sample', s)

                    var w = this.type.getWell(s.get('LOCATION'))
                    var g = this.screencomponentgroups.findWhere({ POSITION: (w+1).toString() })
                    if (g) this.group.setModel(g)
                        else this.group.setModel(null)
                }
            }
        },

        initialize: function(options) {
            this.ready = []

            this.dewar = options.dewar
            this.samples = new Samples(null, { model: LocationSample })
            this.listenTo(this.samples, 'selected:change', this.selectSample)
            //this.buildCollection()
            this.setupValidation()

            this.users = new Users()
            this.users.queryParams.all = 1
            this.users.queryParams.pid = app.proposal.get('PROPOSALID')
            this.ready.push(this.users.fetch())

            this.proteins = new DistinctProteins()
            this.ready.push(this.proteins.fetch())

            this.gproteins = new DistinctProteins()

            this.cache = new Cache({ name: 'container' })
            this.ready2 = this.cache.fetch()

            if (!app.user_can('disp_cont')) PlateTypes.remove(PlateTypes.findWhere({ name: 'ReferencePlate' }))
            this.ctypes = PlateTypes

            this.cacheContainer = _.debounce(this.cacheContainer, 3000)

            var self = this
            this.schedules = new Schedules()
            this.schedules.fetch().done(function() {
                self.ui.schedule.html('<option value=""> - </option>'+self.schedules.opts())
            })

            this.screens = new Screens()
            this.screens.fetch().done(function() {
                self.ui.screen.html('<option value=""> - </option>'+self.screens.opts())
            })

            this.screencomponentgroups = new ScreenComponentGroups()
            this.screencomponentgroups.queryParams.scid = this.getScreen.bind(this)

            this.screencomponents = new ScreenComponents()
            this.screencomponents.queryParams.scid = this.getScreen.bind(this)

        },

        buildCollection: function() {
            var samples = []
            _.each(_.range(1,this.type.get('capacity')+1), function(i) {
                samples.push(new LocationSample({ LOCATION: i.toString(), PROTEINID: -1, new: true }))
            }, this)
            this.samples.reset(samples)
            this.samples.at(0).set('isSelected', true)
        },

        onShow: function() {
            this.getOption('visit') ? this.$el.find('a.autofill').show() : this.$el.find('a.autofill').hide()
            $.when.apply($, this.ready).then(this.doOnShow.bind(this))
        },

        doOnShow: function() {
            console.log('show new puck')
            //this.puck.show(new PuckView({ collection: this.samples }))
            //this.table.show(new SampleTableView({ proteins: this.proteins, collection: this.samples, childTemplate: row, template: table }))
            this.ui.type.html(this.ctypes.opts())
            this.setType()

            this.ready2.done(this.loadContainerCache.bind(this))

            this.ui.pid.html(this.users.opts()).val(app.personid)
            this.checkPerson()
        }
    })

})<|endoftext|>


<commit_before>module.exports = function(config) {
  var options = {
    basePath: '../public',

    // frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'sinon', 'chai', 'browserify', 'detectBrowsers'],

    files: [
      'app.js',
      '../tests/helpers/browser.js',
      'tests/*.js',
      {pattern: 'index.html', include: false},
      {pattern: 'css/**/*.css', include: false}
      //{pattern: 'css/**/*.ttf', watched:false, include: false}
    ],

    exclude: [],

    // preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '../tests/helpers/browser.js': ['browserify']
    },

    proxies: {
      '/app.js': '/base/app.js',
      '/index.html': '/base/index.html'
    },

    // possible values: 'dots', 'progress'
    // reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],
    port: 9876,
    colors: true,

    // possible values: LOG_{DISABLE,ERROR,WARN,INFO,DEBUG}
    logLevel: config.LOG_INFO,

    // launchers: https://npmjs.org/browse/keyword/karma-launcher
    // When not running under CI, `browsers` will actually get set by
    // karma-detect-browsers.
    browsers: [],
    detectBrowsers: {
      // Work around karma-detect-browsers adding multiple Firefox builds, and
      // force Chrome to run in headless mode by default on integration systems:
      // https://developers.google.com/web/updates/2017/04/headless-chrome
      // https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai
      postDetection(browsers) {
        return browsers
          .filter(b => !b.startsWith('Firefox') || b === 'Firefox')
          .map(b => (b === 'Chrome' && process.env.CI) ? 'ChromeHeadless' : b)
      }
    },

    plugins: [ 'karma-*' ],

    concurrency: Infinity
  }

  if (process.env.CI === 'true') {
    options.autoWatch = false
    options.singleRun = true
  }

  if (process.env.KARMA_BROWSERS !== undefined) {
    options.browsers = process.env.KARMA_BROWSERS.split(',')
    options.detectBrowsers.enabled = false
  }

  config.set(options)
}
<commit_msg>.config/karma: Fix lint error due to long comment<commit_after>module.exports = function(config) {
  var options = {
    basePath: '../public',

    // frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'sinon', 'chai', 'browserify', 'detectBrowsers'],

    files: [
      'app.js',
      '../tests/helpers/browser.js',
      'tests/*.js',
      {pattern: 'index.html', include: false},
      {pattern: 'css/**/*.css', include: false}
      //{pattern: 'css/**/*.ttf', watched:false, include: false}
    ],

    exclude: [],

    // preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '../tests/helpers/browser.js': ['browserify']
    },

    proxies: {
      '/app.js': '/base/app.js',
      '/index.html': '/base/index.html'
    },

    // possible values: 'dots', 'progress'
    // reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],
    port: 9876,
    colors: true,

    // possible values: LOG_{DISABLE,ERROR,WARN,INFO,DEBUG}
    logLevel: config.LOG_INFO,

    // launchers: https://npmjs.org/browse/keyword/karma-launcher
    // When not running under CI, `browsers` will actually get set by
    // karma-detect-browsers.
    browsers: [],
    detectBrowsers: {
      // Work around karma-detect-browsers adding multiple Firefox builds, and
      // force Chrome to run in headless mode by default on integration systems:
      // - https://developers.google.com/web/updates/2017/04/headless-chrome
      // eslint-disable-next-line max-len
      // - https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai
      postDetection(browsers) {
        return browsers
          .filter(b => !b.startsWith('Firefox') || b === 'Firefox')
          .map(b => (b === 'Chrome' && process.env.CI) ? 'ChromeHeadless' : b)
      }
    },

    plugins: [ 'karma-*' ],

    concurrency: Infinity
  }

  if (process.env.CI === 'true') {
    options.autoWatch = false
    options.singleRun = true
  }

  if (process.env.KARMA_BROWSERS !== undefined) {
    options.browsers = process.env.KARMA_BROWSERS.split(',')
    options.detectBrowsers.enabled = false
  }

  config.set(options)
}
<|endoftext|>


<commit_before>
<commit_msg>Download json function is added on map result page.<commit_after>
<|endoftext|>


<commit_before>import React from 'react'
import injectSheet from 'react-jss'

const Tabs = ({ classes, tabNames }) => (

{tabNames}

)

const styles = {
	root: {
		height: '47px',
		// 'background-color': 'rgba(240,100,154,0.15)',
		'background-color': '#F0649A',
		color: '#FFFFFF',
		'font-family': 'sans-serif',
		'font-size': '16px',
		'letter-spacing': '4px',
		'line-height': '20px',
		'text-transform': 'uppercase',
	},
}

export default injectSheet(styles)(Tabs)
<commit_msg>Update tabs component<commit_after>import React from 'react'
import injectSheet from 'react-jss'
import classNames from 'classnames'
import { Link } from 'react-router-dom'

const Tabs = ({ classes, tabNames }) => (

			<Link to="/verification/community-health-center" className={classes.link}>
				{tabNames[0]}
			</Link>

			<Link
				to="/verification/pregnancy-resource-center"
				className={classes.link}
			>
				{tabNames[1]}
			</Link>

)

const styles = {
	grid: {
		display: 'grid',
		'grid-template-columns': 'repeat(2, 1fr)',
		'grid-template-rows': '1',
		height: '47px',
		color: '#FFFFFF',
		'background-color': '#F0649A',
		'font-family': 'sans-serif',
		'font-size': '16px',
		'letter-spacing': '4px',
		'line-height': '20px',
		'text-transform': 'uppercase',
		cursor: 'pointer',
	},
	gridItems: {
		'justify-self': 'center',
		'align-self': 'center',
		'text-decoration': 'none !important',
		// '&:hover': {
		// 	'background-color': 'rgba(240,100,154,0.15)',
		// },
	},
	link: {
		height: '100%',
		width: '100%',
	},
}

export default injectSheet(styles)(Tabs)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

/*
 * vRouter Flows tab
 */
monitorInfraComputeFlowsClass = (function() {
    this.parseFlowsData = function(response){

        var origResponse = response;
        var isFromACLFlows = false;
        var ret = [];
        response = jsonPath(origResponse,"$..SandeshFlowData")[0];
        if (response == null){
            isFromACLFlows = true;
            response = jsonPath(origResponse,"$..FlowSandeshData")[0];
        }
        var flowKey = jsonPath(origResponse,"$..flow_key")[0];
        var iterationKey = jsonPath(origResponse,"$..iteration_key")[0];
       // var retArr = [];
       /* for (var i = 0; i < response.length; i++) {
            var currACL = response[i];
            for (var j = 0; j < currACL['flowData'].length; j++) {
                var currFlow = currACL['flowData'][j];
                var aclUuid = currACL['acl_uuid'];
                retArr.push($.extend(currFlow, {acl_uuid:aclUuid}));
            }
        }*/
        if( response != null ){
            if(!(response instanceof Array)){
                response = [response];
            }
            if(isFromACLFlows) {
                $.each(response,function(idx,obj) {
                    var rawJson = obj;
                    ret.push({src_vn:ifNullOrEmptyObject(obj['src_vn'],noDataStr),
                        dst_vn:ifNullOrEmptyObject(obj['dst_vn'],noDataStr),
                        sip:ifNullOrEmptyObject(obj['sip'],noDataStr),
                        protocol:ifNullOrEmptyObject(obj['protocol'],noDataStr),
                        dip:ifNullOrEmptyObject(obj['dst'],noDataStr),
                        stats_bytes:ifNullOrEmptyObject(obj['bytes'],noDataStr),
                        stats_packets:ifNullOrEmptyObject(obj['packets'],noDataStr),
                        raw_json:rawJson});
                });
            }
            $.each(response,function(idx,obj) {
                var rawJson = obj;
                ret.push({src_vn:ifNullOrEmptyObject(obj['src_vn'],noDataStr),
                        dst_vn:ifNullOrEmptyObject(obj['dst_vn'],noDataStr),
                        protocol:ifNullOrEmptyObject(obj['protocol'],noDataStr),
                        sip:ifNullOrEmptyObject(obj['sip'],noDataStr),
                        src_port:ifNullOrEmptyObject(obj['src_port'],noDataStr),
                        dip:ifNullOrEmptyObject(obj['dip'],noDataStr),
                        dst_port:ifNullOrEmptyObject(obj['dst_port'],noDataStr),
                        setup_time_utc:ifNullOrEmptyObject(obj['setup_time_utc'],noDataStr),
                        stats_bytes:ifNullOrEmptyObject(obj['stats_bytes'],noDataStr),
                        stats_packets:ifNullOrEmptyObject(obj['stats_packets'],noDataStr),
                        raw_json:rawJson});
            });
        }
        //Push the flowKey to the stack for Next use
        if(flowKey != null && !$.isEmptyObject(flowKey)){
            //Had to add this hack because sometimes we get into to this parse function twice leading this to be added twice to the stack
            if(flowKey != "0:0:0:0:0.0.0.0:0.0.0.0" && flowKeyStack[flowKeyStack.length - 1] != flowKey)
                flowKeyStack.push(flowKey);
        }
        //Push the aclIterKey to the stack for Next use
        if(iterationKey != null && !$.isEmptyObject(iterationKey)){
            //Had to add this hack because sometimes we get into to this parse function twice leading this to be added twice to the stack
            if(iterationKey.indexOf('0:0:0:0:0.0.0.0:0.0.0.0') == -1 && aclIterKeyStack[aclIterKeyStack.length - 1] != iterationKey)
                aclIterKeyStack.push(iterationKey);
        }
        //$('#flowCnt').text(response.flowData.length);
        return ret;

    }

    this.populateFlowsTab = function (obj,filters) {
        var isAclPrevFirstTimeClicked = true;
        var isAllPrevFirstTimeClicked = true;
        var selectedAcl = 'All';
        flowKeyStack = [];
        aclIterKeyStack = [];
        /*TODO this filtering is causing issues like unable to move next and previous so commenting for now.
         * if(obj['filters'] != null){
            selectedAcl = obj['filters'];
        }*/
        $('#btnNextFlows').unbind("click").click(onNextClick);
        $('#btnPrevFlows').unbind("click").click(onPrevClick);
        layoutHandler.setURLHashParams({tab:'flows',node: obj['name']},{triggerHashChange:false});
        if (!isInitialized('#aclDropDown')){
            $('#aclDropDown').contrailDropdown({
                dataSource: {
                    type: 'remote',
                     url: contrail.format(monitorInfraUrls['VROUTER_ACL'], getIPOrHostName(obj)),
                     parse:function(response){
                         var retArr = [{text:'All',value:'All'}];
                         response = jsonPath(response,'$..AclSandeshData')[0];
                         var uuidArr = [];
                         if(response != null){
                             if(!(response instanceof Array)){
                                 response = [response];
                             }
                             for (var i = 0; i < response.length; i++) {
                                 uuidArr.push(response[i].uuid);
                             }
                         }
                        // $.map(uuidArr, function (value) {
                             $.each(uuidArr, function (key, value) {
                                 retArr.push({text:value, value:value});
                             });
                        // });
                         return retArr;
                     }
                 },
                dataValueField:'value',
                dataTextField:'text',
                change:onSelectAcl
            }).data('contrailDropdown');
        }

        if (!isInitialized('#gridComputeFlows')) {
            $("#gridComputeFlows").contrailGrid({
                header : {
                    title : {
                        text : 'Flows'
                    }
                },
                columnHeader : {
                    columns: [

                                   {
                                    field:"acl_uuid",
                                    name:"ACL / SG UUID",
                                    formatter:function(r,c,v,cd,dc){
                                        return getAclSgUuuidString(dc);
                                    },
                                    searchFn: function(data) {
                                       return getAclSgUuuidString(data);
                                    },
                                    minWidth:270
                                    },
                                   {
                                       field:"protocol",
                                       name:"Protocol",
                                       minWidth:70,
                                       formatter:function(r,c,v,cd,dc){
                                           return formatProtocol(dc['protocol']);
                                       }
                                   },
                                   {
                                       field:"src_vn",
                                       name:"Src Network",
                                       cssClass:'cell-hyperlink-blue',
                                       events: {
                                           onClick: function(e,dc){
                                               var tabIdx = $.inArray("networks", computeNodeTabs);
                                               selectTab(computeNodeTabStrip,tabIdx);
                                           }
                                        },
                                       minWidth:220
                                   },
                                   {
                                       field:"sip",
                                       name:"Src IP",
                                       minWidth:80
                                   },
                                   {
                                       field:"src_port",
                                       name:"Src Port",
                                       minWidth:70
                                   },
                                   {
                                       field:"dst_vn",
                                       name:"Dest Network",
                                       cssClass:'cell-hyperlink-blue',
                                       events: {
                                           onClick: function(e,dc){
                                               var tabIdx = $.inArray("networks", computeNodeTabs);
                                               selectTab(computeNodeTabStrip,tabIdx);
                                           }
                                        },
                                       minWidth:220
                                   },
                                   {
                                       field:"dip",
                                       name:"Dest IP",
                                       minWidth:80
                                   },
                                   {
                                       field:"dst_port",
                                       name:"Dest Port",
                                       minWidth:70
                                   },
                                   {
                                       field:"stats_bytes",
                                       name:"Bytes/Pkts",
                                       minWidth:135,
                                       formatter:function(r,c,v,cd,dc){
                                           return contrail.format("{0}/{1}",dc['stats_bytes'],dc['stats_packets']);
                                       },
                                       searchFn:function(d){
                                           return d['stats_bytes']+ '/ ' +d['stats_packets'];
                                       }
                                   },
                                   {
                                       field:"setup_time_utc",
                                       name:"Setup Time",
                                       formatter:function(r,c,v,cd,dc){
                                           return new XDate(dc['setup_time_utc']/1000).toLocaleString();
                                       },
                                       minWidth:150
                                   }
                               ]
                },
                body : {
                    options : {
                        //checkboxSelectable: true,
                        forceFitColumns: true,
                        detail:{
                            template: $("#gridsTemplateJSONDetails").html()
                        }
                    },
                    dataSource : {
                        remote: {
                            ajaxConfig: {
                                url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                                /* TODO use this while implementing context filtering
                                function () {
                                    var aclFilter = '';
                                    if(selectedAcl != 'All'){
                                        aclFilter = '&aclUUID=' + selectedAcl;
                                    }
                                    return '/api/admin/monitor/infrastructure/vrouter/flows?ip=' + getIPOrHostName(obj) + aclFilter;
                                }*/
                                type: 'GET'
                            },
                            dataParser: self.parseFlowsData
                        }
                    },
                    statusMessages: {
                        loading: {
                            text: 'Loading Flows..',
                        },
                        empty: {
                            text: 'No Flows to display'
                        },
                        errorGettingData: {
                            type: 'error',
                            iconClasses: 'icon-warning',
                            text: 'Error in getting Data.'
                        }
                    }
                },
                footer : {
                    pager : {
                        options : {
                            pageSize : 50,
                            pageSizeSelect : [10, 50, 100, 200, 500 ]
                        }
                    }
                },
                change:onFlowChange
            });
            flowGrid = $('#gridComputeFlows').data('contrailGrid');
            flowGrid.showGridMessage('loading');
            /*TODO context filtering
             * if(filters == null || filters == "" || filters == undefined){
                flowGrid.dataSource.filter({});
            }*/
        } else {
            /* TODO use it when implementing context filtering
             * if(filters != null) {
                flowGrid.filter({field: "acl_uuid", operator: "startswith", value: filters});
            }
            flowGrid.dataSource.transport.options.read.url = '/api/admin/monitor/infrastructure/vrouter/flows?ip=' + getIPOrHostName(obj);
            */
            reloadGrid(flowGrid);
            //flowGrid.showColumn(0);
        }
        function getAclSgUuuidString (data){
            var aclUuid = ifNull(jsonPath(data,"$..policy..FlowAclUuid..uuid")[0],noDataStr);
            var sgUuid = ifNull(jsonPath(data,"$..sg..FlowAclUuid..uuid")[0],noDataStr);
            if(aclUuid != null)
            var ret = aclUuid;
            if(sgUuid != null && sgUuid != noDataStr){
                ret = ret + ' / </br>' + sgUuid;
            }
            return ret;
        }
        function onSelectAcl() {
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var newAjaxConfig = "";
            flowKeyStack = [];
            aclIterKeyStack = [];
            if (acluuid != 'All') {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                                                            + '&aclUUID=' + acluuid,
                        type:'Get'
                    };
            } else {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onNextClick(){
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var newAjaxConfig = "";
            isAllPrevFirstTimeClicked = true;
            isAclPrevFirstTimeClicked = true;
            if(acluuid == 'All' && flowKeyStack.length > 0 && flowKeyStack[flowKeyStack.length - 1] != null){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                                                            + '&flowKey=' + flowKeyStack[flowKeyStack.length - 1],
                        type:'Get'
                    };
            }
            else if (acluuid != 'All' && aclIterKeyStack.length > 0 && aclIterKeyStack[aclIterKeyStack.length -1] != null){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                        + '&iterKey=' + aclIterKeyStack[aclIterKeyStack.length -1],
                        type:'Get'
                    };
            } else if (acluuid == "All"){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onPrevClick(){
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var newAjaxConfig = "";
            if(isAllPrevFirstTimeClicked) {
                //we need to do this because when we click the prev for the first time the stack would contain the next uuid as well.
                //We need to pop out the uuids 3 times to get the prev uuid.
                flowKeyStack.pop();
                isAllPrevFirstTimeClicked = false;
            }
            flowKeyStack.pop();//need to pop twice to get the prev last flowkey
            if(isAclPrevFirstTimeClicked) {
                aclIterKeyStack.pop();
                isAclPrevFirstTimeClicked = false;
            }
            aclIterKeyStack.pop();
            if(acluuid == 'All' && flowKeyStack.length > 0) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                            + '&flowKey=' + flowKeyStack.pop(),
                        type:'Get'
                    };
            } else if (acluuid == 'All' && flowKeyStack.length < 1){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            } else if(acluuid != 'All' && aclIterKeyStack.length > 0) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                        + '&iterKey=' + aclIterKeyStack.pop(),
                        type:'Get'
                    };
            } else if(acluuid != 'All' && aclIterKeyStack.length < 1) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                            + '&aclUUID=' + acluuid,
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onFlowChange() {
            var name;
            if (name = isCellSelectable(this.select())) {
                if ($.inArray(name, ['src_vn', 'dst_vn']) > -1){
                    var tabIdx = $.inArray("networks", computeNodeTabs);
                    selectTab(computeNodeTabStrip, tabIdx);
                }
            }
        }
    }
    return {populateFlowsTab:populateFlowsTab};
})();<commit_msg>Fix for Bug 3022: Clicking on a particular ACL in Flows tab not popluating all values.<commit_after>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

/*
 * vRouter Flows tab
 */
monitorInfraComputeFlowsClass = (function() {
    this.parseFlowsData = function(response){

        var origResponse = response;
        var isFromACLFlows = false;
        var ret = [];
        response = jsonPath(origResponse,"$..SandeshFlowData")[0];
        if (response == null){
            isFromACLFlows = true;
            response = jsonPath(origResponse,"$..FlowSandeshData")[0];
        }
        var flowKey = jsonPath(origResponse,"$..flow_key")[0];
        var iterationKey = jsonPath(origResponse,"$..iteration_key")[0];
       // var retArr = [];
       /* for (var i = 0; i < response.length; i++) {
            var currACL = response[i];
            for (var j = 0; j < currACL['flowData'].length; j++) {
                var currFlow = currACL['flowData'][j];
                var aclUuid = currACL['acl_uuid'];
                retArr.push($.extend(currFlow, {acl_uuid:aclUuid}));
            }
        }*/
        if( response != null ){
            if(!(response instanceof Array)){
                response = [response];
            }
            if(isFromACLFlows) {
                $.each(response,function(idx,obj) {
                    var rawJson = obj;
                    ret.push({src_vn:ifNullOrEmptyObject(obj['source_vn'],noDataStr),
                        dst_vn:ifNullOrEmptyObject(obj['dest_vn'],noDataStr),
                        sip:ifNullOrEmptyObject(obj['src'],noDataStr),
                        src_port:ifNullOrEmptyObject(obj['src_port'],noDataStr),
                        dst_port:ifNullOrEmptyObject(obj['dst_port'],noDataStr),
                        setup_time_utc:ifNullOrEmptyObject(obj['setup_time_utc'],noDataStr),
                        protocol:ifNullOrEmptyObject(obj['protocol'],noDataStr),
                        dip:ifNullOrEmptyObject(obj['dst'],noDataStr),
                        stats_bytes:ifNullOrEmptyObject(obj['bytes'],noDataStr),
                        stats_packets:ifNullOrEmptyObject(obj['packets'],noDataStr),
                        raw_json:rawJson});
                });
            } else {
                $.each(response,function(idx,obj) {
                    var rawJson = obj;
                    ret.push({src_vn:ifNullOrEmptyObject(obj['src_vn'],noDataStr),
                        dst_vn:ifNullOrEmptyObject(obj['dst_vn'],noDataStr),
                        protocol:ifNullOrEmptyObject(obj['protocol'],noDataStr),
                        sip:ifNullOrEmptyObject(obj['sip'],noDataStr),
                        src_port:ifNullOrEmptyObject(obj['src_port'],noDataStr),
                        dip:ifNullOrEmptyObject(obj['dip'],noDataStr),
                        dst_port:ifNullOrEmptyObject(obj['dst_port'],noDataStr),
                        setup_time_utc:ifNullOrEmptyObject(obj['setup_time_utc'],noDataStr),
                        stats_bytes:ifNullOrEmptyObject(obj['stats_bytes'],noDataStr),
                        stats_packets:ifNullOrEmptyObject(obj['stats_packets'],noDataStr),
                        raw_json:rawJson});
                });
            }
        }
        //Push the flowKey to the stack for Next use
        if(flowKey != null && !$.isEmptyObject(flowKey)){
            //Had to add this hack because sometimes we get into to this parse function twice leading this to be added twice to the stack
            if(flowKey != "0:0:0:0:0.0.0.0:0.0.0.0" && flowKeyStack[flowKeyStack.length - 1] != flowKey)
                flowKeyStack.push(flowKey);
        }
        //Push the aclIterKey to the stack for Next use
        if(iterationKey != null && !$.isEmptyObject(iterationKey)){
            //Had to add this hack because sometimes we get into to this parse function twice leading this to be added twice to the stack
            if(iterationKey.indexOf('0:0:0:0:0.0.0.0:0.0.0.0') == -1 && aclIterKeyStack[aclIterKeyStack.length - 1] != iterationKey)
                aclIterKeyStack.push(iterationKey);
        }
        //$('#flowCnt').text(response.flowData.length);
        return ret;

    }

    this.populateFlowsTab = function (obj,filters) {
        var isAclPrevFirstTimeClicked = true;
        var isAllPrevFirstTimeClicked = true;
        var selectedAcl = 'All';
        flowKeyStack = [];
        aclIterKeyStack = [];
        /*TODO this filtering is causing issues like unable to move next and previous so commenting for now.
         * if(obj['filters'] != null){
            selectedAcl = obj['filters'];
        }*/
        $('#btnNextFlows').unbind("click").click(onNextClick);
        $('#btnPrevFlows').unbind("click").click(onPrevClick);
        layoutHandler.setURLHashParams({tab:'flows',node: obj['name']},{triggerHashChange:false});
        if (!isInitialized('#aclDropDown')){
            $('#aclDropDown').contrailDropdown({
                dataSource: {
                    type: 'remote',
                     url: contrail.format(monitorInfraUrls['VROUTER_ACL'], getIPOrHostName(obj)),
                     parse:function(response){
                         var retArr = [{text:'All',value:'All'}];
                         response = jsonPath(response,'$..AclSandeshData')[0];
                         var uuidArr = [];
                         if(response != null){
                             if(!(response instanceof Array)){
                                 response = [response];
                             }
                             for (var i = 0; i < response.length; i++) {
                                 uuidArr.push(response[i].uuid);
                             }
                         }
                        // $.map(uuidArr, function (value) {
                             $.each(uuidArr, function (key, value) {
                                 retArr.push({text:value, value:value});
                             });
                        // });
                         return retArr;
                     }
                 },
                dataValueField:'value',
                dataTextField:'text',
                change:onSelectAcl
            }).data('contrailDropdown');
        }

        if (!isInitialized('#gridComputeFlows')) {
            $("#gridComputeFlows").contrailGrid({
                header : {
                    title : {
                        text : 'Flows'
                    }
                },
                columnHeader : {
                    columns: [

                                   {
                                    field:"acl_uuid",
                                    name:"ACL / SG UUID",
                                    formatter:function(r,c,v,cd,dc){
                                        return getAclSgUuuidString(dc);
                                    },
                                    searchFn: function(data) {
                                       return getAclSgUuuidString(data);
                                    },
                                    minWidth:270
                                    },
                                   {
                                       field:"protocol",
                                       name:"Protocol",
                                       minWidth:70,
                                       formatter:function(r,c,v,cd,dc){
                                           return formatProtocol(dc['protocol']);
                                       }
                                   },
                                   {
                                       field:"src_vn",
                                       name:"Src Network",
                                       cssClass:'cell-hyperlink-blue',
                                       events: {
                                           onClick: function(e,dc){
                                               var tabIdx = $.inArray("networks", computeNodeTabs);
                                               selectTab(computeNodeTabStrip,tabIdx);
                                           }
                                        },
                                       minWidth:220
                                   },
                                   {
                                       field:"sip",
                                       name:"Src IP",
                                       minWidth:80
                                   },
                                   {
                                       field:"src_port",
                                       name:"Src Port",
                                       minWidth:70
                                   },
                                   {
                                       field:"dst_vn",
                                       name:"Dest Network",
                                       cssClass:'cell-hyperlink-blue',
                                       events: {
                                           onClick: function(e,dc){
                                               var tabIdx = $.inArray("networks", computeNodeTabs);
                                               selectTab(computeNodeTabStrip,tabIdx);
                                           }
                                        },
                                       minWidth:220
                                   },
                                   {
                                       field:"dip",
                                       name:"Dest IP",
                                       minWidth:80
                                   },
                                   {
                                       field:"dst_port",
                                       name:"Dest Port",
                                       minWidth:70
                                   },
                                   {
                                       field:"stats_bytes",
                                       name:"Bytes/Pkts",
                                       minWidth:135,
                                       formatter:function(r,c,v,cd,dc){
                                           return contrail.format("{0}/{1}",dc['stats_bytes'],dc['stats_packets']);
                                       },
                                       searchFn:function(d){
                                           return d['stats_bytes']+ '/ ' +d['stats_packets'];
                                       }
                                   },
                                   {
                                       field:"setup_time_utc",
                                       name:"Setup Time",
                                       formatter:function(r,c,v,cd,dc){
                                           return new XDate(dc['setup_time_utc']/1000).toLocaleString();
                                       },
                                       minWidth:150
                                   }
                               ]
                },
                body : {
                    options : {
                        //checkboxSelectable: true,
                        forceFitColumns: true,
                        detail:{
                            template: $("#gridsTemplateJSONDetails").html()
                        }
                    },
                    dataSource : {
                        remote: {
                            ajaxConfig: {
                                url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                                /* TODO use this while implementing context filtering
                                function () {
                                    var aclFilter = '';
                                    if(selectedAcl != 'All'){
                                        aclFilter = '&aclUUID=' + selectedAcl;
                                    }
                                    return '/api/admin/monitor/infrastructure/vrouter/flows?ip=' + getIPOrHostName(obj) + aclFilter;
                                }*/
                                type: 'GET'
                            },
                            dataParser: self.parseFlowsData
                        }
                    },
                    statusMessages: {
                        loading: {
                            text: 'Loading Flows..',
                        },
                        empty: {
                            text: 'No Flows to display'
                        },
                        errorGettingData: {
                            type: 'error',
                            iconClasses: 'icon-warning',
                            text: 'Error in getting Data.'
                        }
                    }
                },
                footer : {
                    pager : {
                        options : {
                            pageSize : 50,
                            pageSizeSelect : [10, 50, 100, 200, 500 ]
                        }
                    }
                },
                change:onFlowChange
            });
            flowGrid = $('#gridComputeFlows').data('contrailGrid');
            flowGrid.showGridMessage('loading');
            /*TODO context filtering
             * if(filters == null || filters == "" || filters == undefined){
                flowGrid.dataSource.filter({});
            }*/
        } else {
            /* TODO use it when implementing context filtering
             * if(filters != null) {
                flowGrid.filter({field: "acl_uuid", operator: "startswith", value: filters});
            }
            flowGrid.dataSource.transport.options.read.url = '/api/admin/monitor/infrastructure/vrouter/flows?ip=' + getIPOrHostName(obj);
            */
            reloadGrid(flowGrid);
            //flowGrid.showColumn(0);
        }
        function getAclSgUuuidString (data){
            var aclUuid = ifNull(jsonPath(data,"$..policy..FlowAclUuid..uuid")[0],noDataStr);
            var sgUuid = ifNull(jsonPath(data,"$..sg..FlowAclUuid..uuid")[0],noDataStr);
            if(aclUuid != null)
            var ret = aclUuid;
            if(sgUuid != null && sgUuid != noDataStr){
                ret = ret + ' / </br>' + sgUuid;
            }
            return ret;
        }
        function onSelectAcl() {
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var newAjaxConfig = "";
            flowKeyStack = [];
            aclIterKeyStack = [];
            if (acluuid != 'All') {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                                                            + '&aclUUID=' + acluuid,
                        type:'Get'
                    };
            } else {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onNextClick(){
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var newAjaxConfig = "";
            isAllPrevFirstTimeClicked = true;
            isAclPrevFirstTimeClicked = true;
            if(acluuid == 'All' && flowKeyStack.length > 0 && flowKeyStack[flowKeyStack.length - 1] != null){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                                                            + '&flowKey=' + flowKeyStack[flowKeyStack.length - 1],
                        type:'Get'
                    };
            }
            else if (acluuid != 'All' && aclIterKeyStack.length > 0 && aclIterKeyStack[aclIterKeyStack.length -1] != null){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                        + '&iterKey=' + aclIterKeyStack[aclIterKeyStack.length -1],
                        type:'Get'
                    };
            } else if (acluuid == "All"){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onPrevClick(){
            var flowGrid = $('#gridComputeFlows').data('contrailGrid');
            var acluuid = $('#aclDropDown').data("contrailDropdown").value();
            var newAjaxConfig = "";
            if(isAllPrevFirstTimeClicked) {
                //we need to do this because when we click the prev for the first time the stack would contain the next uuid as well.
                //We need to pop out the uuids 3 times to get the prev uuid.
                flowKeyStack.pop();
                isAllPrevFirstTimeClicked = false;
            }
            flowKeyStack.pop();//need to pop twice to get the prev last flowkey
            if(isAclPrevFirstTimeClicked) {
                aclIterKeyStack.pop();
                isAclPrevFirstTimeClicked = false;
            }
            aclIterKeyStack.pop();
            if(acluuid == 'All' && flowKeyStack.length > 0) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                            + '&flowKey=' + flowKeyStack.pop(),
                        type:'Get'
                    };
            } else if (acluuid == 'All' && flowKeyStack.length < 1){
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj),
                        type:'Get'
                    };
            } else if(acluuid != 'All' && aclIterKeyStack.length > 0) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                        + '&iterKey=' + aclIterKeyStack.pop(),
                        type:'Get'
                    };
            } else if(acluuid != 'All' && aclIterKeyStack.length < 1) {
                newAjaxConfig = {
                        url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(obj)
                            + '&aclUUID=' + acluuid,
                        type:'Get'
                    };
            }
            flowGrid.setRemoteAjaxConfig(newAjaxConfig);
            reloadGrid(flowGrid);
        }
        function onFlowChange() {
            var name;
            if (name = isCellSelectable(this.select())) {
                if ($.inArray(name, ['src_vn', 'dst_vn']) > -1){
                    var tabIdx = $.inArray("networks", computeNodeTabs);
                    selectTab(computeNodeTabStrip, tabIdx);
                }
            }
        }
    }
    return {populateFlowsTab:populateFlowsTab};
})();<|endoftext|>


<commit_before>/*!
 * transform
 * Version: 0.0.1
 * Date: 2016/8/1
 * https://github.com/Nuintun/fengine
 *
 * Original Author: http://www.jsbug.com/lab/samples/fengine/
 *
 * This is licensed under the MIT License (MIT).
 * For details, see: https://github.com/Nuintun/fengine/blob/master/LICENSE
 */

'use strict';

var fs = require('fs');
var path = require('path');
var util = require('./util');
var Events = require('./events');

var DIRECTIVE = {
  SLOT: 'slot',
  LAYOUT: 'layout',
  INCLUDE: 'include',
  NONLAYOUT: '!layout'
};
var EVENTS = {
  END: 'end',
  DATA: 'data',
  SLOT: '__SLOT__'
};
var CWD = process.cwd();

var assert = {
  delimiter: function (options, defaults){
    Object.keys(options.delimiter).forEach(function (key){
      var def = defaults.delimiter[key];
      var delimiter = options.delimiter[key];

      if (!util.array(delimiter)) {
        options.delimiter[key] = def;
      } else {
        if (!util.string(delimiter[0])) {
          delimiter[0] = def[0];
        }

        if (!util.string(delimiter[1])) {
          delimiter[1] = def[1];
        }
      }
    });
  },
  data: function (options, defaults){
    Object.keys(options.data).forEach(function (key){
      var def = defaults.data[key];
      var data = options.data[key];

      if (util.fn(data)) {
        data = data(options.src);
      }

      if (!util.string(data)) {
        options.data[key] = def;
      }
    });
  }
};

/**
 * Transform
 * @param src
 * @param source
 * @param options
 * @constructor
 */
function Transform(src, source, options){
  if (!util.string(src)) {
    throw new TypeError('options.src must be a file path.');
  }

  if (!util.string(source)) {
    throw new TypeError('source must be a string.');
  }

  var context = this;
  var defaults = {
    root: CWD,
    layout: null,
    delimiter: {
      data: ['{{', '}}'],
      directive: ['<!--', '-->']
    },
    data: {
      dirname: 'dirname',
      filename: 'filename'
    }
  };

  context.index = 0;
  context.entry = null;
  context.slot = false;
  context.source = source;
  context.isLayout = false;
  context.options = options = util.mix(defaults, options);

  assert.data(options, defaults);
  assert.delimiter(options, defaults);

  context.src = path.resolve(CWD, src);
  context.dirname = path.dirname(context.src);
  context.filename = path.basename(context.src);
  context.root = path.resolve(CWD, util.string(options.root) ? options.root : CWD);
  context.layout = util.fn(options.layout) ? options.layout(context.src) : options.layout;
  context.layout = util.string(context.layout) ? context.resolve(context.layout) : null;

  var dataDelimiter = options.delimiter.data.map(function (directive){
    return util.str4regex(directive);
  });

  var dataDirective = Object.keys(options.data).map(function (data){
    return util.str4regex(data);
  }).join('|');

  var directiveDelimiter = options.delimiter.directive.map(function (directive){
    return util.str4regex(directive);
  });

  context.regexp = {
    transform: new RegExp(
      directiveDelimiter[0]
      + '\\s*('
      + util.str4regex(DIRECTIVE.INCLUDE)
      + '\\s+\\(\\s*(.+?)\\s*\\)|'
      + util.str4regex(DIRECTIVE.SLOT)
      + ')\\s*'
      + directiveDelimiter[1]
      + '|'
      + dataDelimiter[0]
      + '\\s*('
      + dataDirective
      + ')\\s*'
      + dataDelimiter[1],
      'img'
    ),
    layout: new RegExp(
      directiveDelimiter[0]
      + '\\s*'
      + util.str4regex(DIRECTIVE.LAYOUT)
      + '\\s+\\(\\s*(.+?)\\s*\\)\\s*'
      + directiveDelimiter[1]
    ),
    nonlayout: new RegExp(
      directiveDelimiter[0]
      + '\\s*'
      + util.str4regex(DIRECTIVE.NONLAYOUT)
      + '\\s*'
      + directiveDelimiter[1]
    )
  };

  context.transform();
}

/**
 * extend
 * @type {EventEmitter}
 */
Transform.prototype = Object.create(Events.prototype, {
  constructor: { value: Transform }
});

Transform.prototype.transform = function (){
  var context = this;

  process.nextTick(function (){
    var src;
    var layout = context.regexp.layout.exec(context.source);
    var nonlayout = context.regexp.nonlayout.exec(context.source);

    if (layout && (!nonlayout || layout.index < nonlayout.index)) {
      src = context.resolve(layout[1]);
    }

    src = src || context.layout;

    if (src && src !== context.src) {
      context.setLayout(src);
    } else {
      context.next();
    }
  });
};

Transform.prototype.setLayout = function (src){
  var context = this;

  fs.readFile(src, function (error, source){
    if (error) {
      return context.next();
    }

    var options = util.mix({}, context.options);

    options.layout = null;

    var layout = new Transform(src, source.toString(), options);

    layout.entry = context;
    layout.isLayout = true;

    layout.on(EVENTS.DATA, function (data){
      context.write(data);
    });

    context.once(EVENTS.SLOT, function (){
      layout.next();
    });

    layout.once(EVENTS.END, function (){
      context.end();
    });
  });
};

Transform.prototype.exec = function (){
  var context = this;
  var match = context.regexp.transform.exec(context.source);

  if (!match) return false;

  var index = match.index;
  var type = match[1] ? 'directive' : 'data';
  var command = type === 'directive' ? match[1] : match[3];

  match = match[0];

  context.write(context.source.substring(context.index, index));

  context.index = index + match.length;

  if (type === 'directive') {
    command = command.toLowerCase();

    switch (command) {
      case DIRECTIVE.SLOT:
        if (context.isLayout && !context.slot && context.entry) {
          context.slot = true;

          context.entry.next();
        } else {
          context.write(match);
          context.next();
        }
        break;
      default:
        if (command.indexOf(DIRECTIVE.INCLUDE) === 0) {
          var entry = context.entry;

          while (entry instanceof Transform) {
            if (context.src === entry.src) {
              context.entry = null;

              return true;
            }

            entry = entry.entry;
          }

          var src = context.resolve(command);

          fs.readFile(src, function (error, source){
            if (error) {
              return context.next();
            }

            var options = util.mix({}, context.options);

            options.layout = null;

            var child = new Transform(src, source.toString(), options);

            child.entry = context;

            child.on(EVENTS.DATA, function (data){
              entry.write(data);
            });

            child.once(EVENTS.END, function (){
              var entry = this.entry;

              if (this.entry instanceof Transform) {
                entry.next();
              }
            });
          });
        } else {
          context.write(match);
          context.next();
        }
        break;
    }
  } else {
    context.write(context.options.data[command] || match);
    context.next();
  }

  return true;
};

Transform.prototype.resolve = function (url){
  return path.resolve(this.dirname, url);
};

Transform.prototype.write = function (data){
  this.emit(EVENTS.DATA, data);

  return data;
};

Transform.prototype.end = function (data){
  if (data) {
    this.emit(EVENTS.DATA, data);
  }

  this.emit(EVENTS.END);

  return data;
};

Transform.prototype.next = function (){
  var context = this;

  if (!context.exec()) {
    context.write(context.source.substring(context.index));

    if (context.isLayout) {
      context.end();
    } else {
      if (context.layout) {
        context.emit(EVENTS.SLOT);
      } else {
        context.end();
      }
    }
  }
};

// exports
module.exports = Transform;
<commit_msg>update files<commit_after>/*!
 * transform
 * Version: 0.0.1
 * Date: 2016/8/1
 * https://github.com/Nuintun/fengine
 *
 * Original Author: http://www.jsbug.com/lab/samples/fengine/
 *
 * This is licensed under the MIT License (MIT).
 * For details, see: https://github.com/Nuintun/fengine/blob/master/LICENSE
 */

'use strict';

var fs = require('fs');
var path = require('path');
var util = require('./util');
var Events = require('./events');

var DIRECTIVE = {
  SLOT: 'slot',
  LAYOUT: 'layout',
  INCLUDE: 'include',
  NONLAYOUT: '!layout'
};
var EVENTS = {
  END: 'end',
  DATA: 'data',
  SLOT: '__SLOT__'
};
var CWD = process.cwd();

var assert = {
  delimiter: function (options, defaults){
    Object.keys(options.delimiter).forEach(function (key){
      var def = defaults.delimiter[key];
      var delimiter = options.delimiter[key];

      if (!util.array(delimiter)) {
        options.delimiter[key] = def;
      } else {
        if (!util.string(delimiter[0])) {
          delimiter[0] = def[0];
        }

        if (!util.string(delimiter[1])) {
          delimiter[1] = def[1];
        }
      }
    });
  },
  data: function (options, defaults){
    Object.keys(options.data).forEach(function (key){
      var def = defaults.data[key];
      var data = options.data[key];

      if (util.fn(data)) {
        data = data(options.src);
      }

      if (!util.string(data)) {
        options.data[key] = def;
      }
    });
  }
};

/**
 * Transform
 * @param src
 * @param source
 * @param options
 * @constructor
 */
function Transform(src, source, options){
  if (!util.string(src)) {
    throw new TypeError('options.src must be a file path.');
  }

  if (!util.string(source)) {
    throw new TypeError('source must be a string.');
  }

  var context = this;
  var defaults = {
    root: CWD,
    layout: null,
    delimiter: {
      data: ['{{', '}}'],
      directive: ['<!--', '-->']
    },
    data: {
      dirname: 'dirname',
      filename: 'filename'
    }
  };

  context.index = 0;
  context.entry = null;
  context.slot = false;
  context.source = source;
  context.isLayout = false;
  context.options = options = util.mix(defaults, options);

  assert.data(options, defaults);
  assert.delimiter(options, defaults);

  context.src = path.resolve(CWD, src);
  context.dirname = path.dirname(context.src);
  context.filename = path.basename(context.src);
  context.root = path.resolve(CWD, util.string(options.root) ? options.root : CWD);
  context.layout = util.fn(options.layout) ? options.layout(context.src) : options.layout;
  context.layout = util.string(context.layout) ? context.resolve(context.layout) : null;

  var dataDelimiter = options.delimiter.data.map(function (directive){
    return util.str4regex(directive);
  });

  var dataDirective = Object.keys(options.data).map(function (data){
    return util.str4regex(data);
  }).join('|');

  var directiveDelimiter = options.delimiter.directive.map(function (directive){
    return util.str4regex(directive);
  });

  context.regexp = {
    transform: new RegExp(
      directiveDelimiter[0]
      + '\\s*('
      + util.str4regex(DIRECTIVE.INCLUDE)
      + '\\s*\\(\\s*(.+?)\\s*\\)|'
      + util.str4regex(DIRECTIVE.SLOT)
      + ')\\s*'
      + directiveDelimiter[1]
      + '|'
      + dataDelimiter[0]
      + '\\s*('
      + dataDirective
      + ')\\s*'
      + dataDelimiter[1],
      'img'
    ),
    layout: new RegExp(
      directiveDelimiter[0]
      + '\\s*'
      + util.str4regex(DIRECTIVE.LAYOUT)
      + '\\s+\\(\\s*(.+?)\\s*\\)\\s*'
      + directiveDelimiter[1]
    ),
    nonlayout: new RegExp(
      directiveDelimiter[0]
      + '\\s*'
      + util.str4regex(DIRECTIVE.NONLAYOUT)
      + '\\s*'
      + directiveDelimiter[1]
    )
  };

  context.transform();
}

/**
 * extend
 * @type {EventEmitter}
 */
Transform.prototype = Object.create(Events.prototype, {
  constructor: { value: Transform }
});

Transform.prototype.transform = function (){
  var context = this;

  process.nextTick(function (){
    var src;
    var layout = context.regexp.layout.exec(context.source);
    var nonlayout = context.regexp.nonlayout.exec(context.source);

    if (layout && (!nonlayout || layout.index < nonlayout.index)) {
      src = context.resolve(layout[1]);
    }

    src = src || context.layout;

    if (src && src !== context.src) {
      context.setLayout(src);
    } else {
      context.next();
    }
  });
};

Transform.prototype.setLayout = function (src){
  var context = this;

  fs.readFile(src, function (error, source){
    if (error) {
      return context.next();
    }

    var options = util.mix({}, context.options);

    options.layout = null;

    var layout = new Transform(src, source.toString(), options);

    layout.entry = context;
    layout.isLayout = true;

    layout.on(EVENTS.DATA, function (data){
      context.write(data);
    });

    context.once(EVENTS.SLOT, function (){
      layout.next();
    });

    layout.once(EVENTS.END, function (){
      context.end();
    });
  });
};

Transform.prototype.exec = function (){
  var context = this;
  var match = context.regexp.transform.exec(context.source);

  if (!match) return false;

  var index = match.index;
  var type = match[1] ? 'directive' : 'data';
  var command = type === 'directive' ? match[1] : match[3];

  match = match[0];

  context.write(context.source.substring(context.index, index));

  context.index = index + match.length;

  if (type === 'directive') {
    command = command.toLowerCase();

    switch (command) {
      case DIRECTIVE.SLOT:
        if (context.isLayout && !context.slot && context.entry) {
          context.slot = true;

          context.entry.next();
        } else {
          context.write(match);
          context.next();
        }
        break;
      default:
        if (command.indexOf(DIRECTIVE.INCLUDE) === 0) {
          var entry = context.entry;

          while (entry instanceof Transform) {
            if (context.src === entry.src) {
              context.entry = null;

              return true;
            }

            entry = entry.entry;
          }

          var src = context.resolve(command);

          fs.readFile(src, function (error, source){
            if (error) {
              return context.next();
            }

            var options = util.mix({}, context.options);

            options.layout = null;

            var child = new Transform(src, source.toString(), options);

            child.entry = context;

            child.on(EVENTS.DATA, function (data){
              entry.write(data);
            });

            child.once(EVENTS.END, function (){
              var entry = this.entry;

              if (this.entry instanceof Transform) {
                entry.next();
              }
            });
          });
        } else {
          context.write(match);
          context.next();
        }
        break;
    }
  } else {
    context.write(context.options.data[command] || match);
    context.next();
  }

  return true;
};

Transform.prototype.resolve = function (url){
  return path.resolve(this.dirname, url);
};

Transform.prototype.write = function (data){
  this.emit(EVENTS.DATA, data);

  return data;
};

Transform.prototype.end = function (data){
  if (data) {
    this.emit(EVENTS.DATA, data);
  }

  this.emit(EVENTS.END);

  return data;
};

Transform.prototype.next = function (){
  var context = this;

  if (!context.exec()) {
    context.write(context.source.substring(context.index));

    if (context.isLayout) {
      context.end();
    } else {
      if (context.layout) {
        context.emit(EVENTS.SLOT);
      } else {
        context.end();
      }
    }
  }
};

// exports
module.exports = Transform;
<|endoftext|>


<commit_before>import extend from 'extend';
import Delta from 'rich-text/lib/delta';
import Parchment from 'parchment';
import Block from '../blots/block';
import Container from '../blots/container';

class ListItem extends Block {
  static formats(domNode) {
    return domNode.tagName === ListItem.tagName ? undefined : super.formats(domNode);
  }

  format(name, value) {
    if (name === List.blotName && !value) {
      this.replaceWith(Parchment.create(this.statics.scope));
    } else {
      super.format(name, value);
    }
  }

  remove() {
    if (this.prev == null && this.next == null) {
      this.parent.remove();
    } else {
      super.remove();
    }
  }

  replaceWith(name, value) {
    this.parent.isolate(this.offset(this.parent), this.length());
    if (name === List.blotName) {
      this.parent.replaceWith(name, value);
      return this;
    } else {
      this.parent.unwrap();
      return super.replaceWith(name, value);
    }
  }
}
ListItem.blotName = 'list-item';
ListItem.tagName = 'LI';

class List extends Container {
  static create(value) {
    if (value === 'ordered') {
      value = 'OL';
    } else if (value === 'bullet') {
      value = 'UL';
    }
    return super.create(value);
  }

  static formats(domNode) {
    if (domNode.tagName === 'OL') return 'ordered';
    if (domNode.tagName === 'UL') return 'bullet';
    return undefined;
  }

  format(name, value) {
    if (this.children.length > 0) {
      this.children.tail.format(name, value);
    }
  }

  formats() {
    // We don't inherit from FormatBlot
    return { [this.statics.blotName]: this.statics.formats(this.domNode) };
  }

  optimize() {
    super.optimize();
    let next = this.next;
    if (next != null && next.prev === this &&
        next.statics.blotName === this.statics.blotName &&
        next.domNode.tagName === this.domNode.tagName) {
      next.moveChildren(this);
      next.remove();
    }
  }

  replace(target) {
    if (target.statics.blotName !== this.statics.blotName) {
      let item = Parchment.create(this.statics.defaultChild);
      target.moveChildren(item);
      this.appendChild(item);
    }
    super.replace(target);
  }
}
List.blotName = 'list';
List.scope = Parchment.Scope.BLOCK_BLOT;
List.tagName = ['OL', 'UL'];
List.defaultChild = 'list-item';
List.allowedChildren = [ListItem];

export { ListItem, List as default };
<commit_msg>make easier to extend list classes<commit_after>import extend from 'extend';
import Delta from 'rich-text/lib/delta';
import Parchment from 'parchment';
import Block from '../blots/block';
import Container from '../blots/container';

class ListItem extends Block {
  static formats(domNode) {
    return domNode.tagName === this.tagName ? undefined : super.formats(domNode);
  }

  format(name, value) {
    if (name === List.blotName && !value) {
      this.replaceWith(Parchment.create(this.statics.scope));
    } else {
      super.format(name, value);
    }
  }

  remove() {
    if (this.prev == null && this.next == null) {
      this.parent.remove();
    } else {
      super.remove();
    }
  }

  replaceWith(name, value) {
    this.parent.isolate(this.offset(this.parent), this.length());
    if (name === this.parent.statics.blotName) {
      this.parent.replaceWith(name, value);
      return this;
    } else {
      this.parent.unwrap();
      return super.replaceWith(name, value);
    }
  }
}
ListItem.blotName = 'list-item';
ListItem.tagName = 'LI';

class List extends Container {
  static create(value) {
    if (value === 'ordered') {
      value = 'OL';
    } else if (value === 'bullet') {
      value = 'UL';
    }
    return super.create(value);
  }

  static formats(domNode) {
    if (domNode.tagName === 'OL') return 'ordered';
    if (domNode.tagName === 'UL') return 'bullet';
    return undefined;
  }

  format(name, value) {
    if (this.children.length > 0) {
      this.children.tail.format(name, value);
    }
  }

  formats() {
    // We don't inherit from FormatBlot
    return { [this.statics.blotName]: this.statics.formats(this.domNode) };
  }

  optimize() {
    super.optimize();
    let next = this.next;
    if (next != null && next.prev === this &&
        next.statics.blotName === this.statics.blotName &&
        next.domNode.tagName === this.domNode.tagName) {
      next.moveChildren(this);
      next.remove();
    }
  }

  replace(target) {
    if (target.statics.blotName !== this.statics.blotName) {
      let item = Parchment.create(this.statics.defaultChild);
      target.moveChildren(item);
      this.appendChild(item);
    }
    super.replace(target);
  }
}
List.blotName = 'list';
List.scope = Parchment.Scope.BLOCK_BLOT;
List.tagName = ['OL', 'UL'];
List.defaultChild = 'list-item';
List.allowedChildren = [ListItem];

export { ListItem, List as default };
<|endoftext|>