<commit_before>/**
 * guy
 * @class BI.BasicButton
 * @extends BI.Single
 *
 * 一般的button父级
 */
BI.BasicButton = BI.inherit(BI.Single, {
    _defaultConfig: function () {
        var conf = BI.BasicButton.superclass._defaultConfig.apply(this, arguments);
        return BI.extend(conf, {
            _baseCls: (conf._baseCls || "") + " bi-basic-button" + (conf.invalid ? "" : " cursor-pointer") + ((BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""),
            value: "",
            stopEvent: false,
            stopPropagation: false,
            selected: false,
            once: false, // 点击一次选中有效,再点无效
            forceSelected: false, // 点击即选中, 选中了就不会被取消,与once的区别是forceSelected不影响事件的触发
            forceNotSelected: false, // 无论怎么点击都不会被选中
            disableSelected: false, // 使能选中

            shadow: false,
            isShadowShowingOnSelected: false,  // 选中状态下是否显示阴影
            trigger: null,
            handler: BI.emptyFn,
            bubble: null
        });
    },
    _init: function () {
        BI.BasicButton.superclass._init.apply(this, arguments);
        var opts = this.options;
        if (opts.selected === true) {
            BI.nextTick(BI.bind(function () {
                this.setSelected(opts.selected);
            }, this));
        }
        BI.nextTick(BI.bind(this.bindEvent, this));

        if (opts.shadow) {
            this._createShadow();
        }
        if (opts.level) {
            this.element.addClass("button-" + opts.level);
        }
    },

    _createShadow: function () {
        var self = this, o = this.options;

        var assertMask = function () {
            if (!self.$mask) {
                self.$mask = BI.createWidget(BI.isObject(o.shadow) ? o.shadow : {}, {
                    type: "bi.layout",
                    cls: "bi-button-mask"
                });
                self.$mask.invisible();
                BI.createWidget({
                    type: "bi.absolute",
                    element: self,
                    items: [{
                        el: self.$mask,
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }]
                });
            }
        };

        this.element.mouseup(function () {
            if (!self._hover && !o.isShadowShowingOnSelected) {
                assertMask();
                self.$mask.invisible();
            }
        });
        this.element.on("mouseenter." + this.getName(), function (e) {
            if (self.element.__isMouseInBounds__(e)) {
                if (self.isEnabled() && !self._hover && (o.isShadowShowingOnSelected || !self.isSelected())) {
                    assertMask();
                    self.$mask.visible();
                }
            }
        });
        this.element.on("mousemove." + this.getName(), function (e) {
            if (!self.element.__isMouseInBounds__(e)) {
                if (self.isEnabled() && !self._hover) {
                    assertMask();
                    self.$mask.invisible();
                }
            }
        });
        this.element.on("mouseleave." + this.getName(), function () {
            if (self.isEnabled() && !self._hover) {
                assertMask();
                self.$mask.invisible();
            }
        });
    },

    bindEvent: function () {
        var self = this;
        var o = this.options, hand = this.handle();
        if (!hand) {
            return;
        }
        hand = hand.element;
        var triggerArr = (o.trigger || "").split(",");
        BI.each(triggerArr, function (idx, trigger) {
            switch (trigger) {
                case "mouseup":
                    var mouseDown = false;
                    hand.mousedown(function () {
                        mouseDown = true;
                    });
                    hand.mouseup(function (e) {
                        if (mouseDown === true) {
                            clk(e);
                        }
                        mouseDown = false;
                        ev(e);
                    });
                    break;
                case "mousedown":
                    var mouseDown = false;
                    var selected = false;
                    hand.mousedown(function (e) {
                        // if (e.button === 0) {
                        BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
                            // if (e.button === 0) {
                            if (BI.DOM.isExist(self) && !hand.__isMouseInBounds__(e) && mouseDown === true && !selected) {
                                // self.setSelected(!self.isSelected());
                                self._trigger();
                            }
                            mouseDown = false;
                            BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                            // }
                        });
                        if (mouseDown === true) {
                            return;
                        }
                        if (self.isSelected()) {
                            selected = true;
                        } else {
                            clk(e);
                        }
                        mouseDown = true;
                        ev(e);
                        // }
                    });
                    hand.mouseup(function (e) {
                        // if (e.button === 0) {
                        if (BI.DOM.isExist(self) && mouseDown === true && selected === true) {
                            clk(e);
                        }
                        mouseDown = false;
                        selected = false;
                        BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                        // }
                    });
                    break;
                case "dblclick":
                    hand.dblclick(clk);
                    break;
                case "lclick":
                    var mouseDown = false;
                    var interval;
                    hand.mousedown(function (e) {
                        BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
                            interval && clearInterval(interval);
                            interval = null;
                            mouseDown = false;
                            BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                        });
                        if (mouseDown === true) {
                            return;
                        }
                        if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
                            return;
                        }
                        interval = setInterval(function () {
                            if (self.isEnabled()) {
                                self.doClick();
                            }
                        }, 180);
                        mouseDown = true;
                        ev(e);
                    });
                    break;
                default:
                    if (o.stopEvent || o.stopPropagation) {
                        hand.mousedown(function (e) {
                            ev(e);
                        });
                    }
                    hand.click(clk);
                    break;
            }
        });

        // 之后的300ms点击无效
        var onClick = BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, {
            "leading": true,
            "trailing": false
        });

        function ev (e) {
            if (o.stopEvent) {
                e.stopEvent();
            }
            if (o.stopPropagation) {
                e.stopPropagation();
            }
        }

        function clk (e) {
            ev(e);
            if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
                return;
            }
            if (BI.isKey(o.bubble) || BI.isFunction(o.bubble)) {
                if (BI.isNull(self.combo)) {
                    var popup;
                    BI.createWidget({
                        type: "bi.absolute",
                        element: self,
                        items: [{
                            el: {
                                type: "bi.bubble_combo",
                                trigger: "",
                                // bubble的提示不需要一直存在在界面上
                                destroyWhenHide: true,
                                ref: function () {
                                    self.combo = this;
                                },
                                el: {
                                    type: "bi.layout",
                                    height: "100%"
                                },
                                popup: {
                                    type: "bi.text_bubble_bar_popup_view",
                                    text: getBubble(),
                                    ref: function () {
                                        popup = this;
                                    },
                                    listeners: [{
                                        eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON,
                                        action: function (v) {
                                            self.combo.hideView();
                                            if (v) {
                                                onClick.apply(self, arguments);
                                            }
                                        }
                                    }]
                                },
                                listeners: [{
                                    eventName: BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW,
                                    action: function () {
                                        popup.populate(getBubble());
                                    }
                                }]
                            },
                            left: 0,
                            right: 0,
                            bottom: 0,
                            top: 0
                        }]
                    });
                }
                if (self.combo.isViewVisible()) {
                    self.combo.hideView();
                } else {
                    self.combo.showView();
                }
                return;
            }
            onClick.apply(self, arguments);
        }

        function getBubble () {
            var bubble = self.options.bubble;
            if (BI.isFunction(bubble)) {
                return bubble();
            }
            return bubble;
        }
    },

    _trigger: function (e) {
        var o = this.options;
        if (!this.isEnabled()) {
            return;
        }
        if (!this.isDisableSelected()) {
            this.isForceSelected() ? this.setSelected(true) :
                (this.isForceNotSelected() ? this.setSelected(false) :
                    this.setSelected(!this.isSelected()));
        }
        if (this.isValid()) {
            var v = this.getValue();
            o.handler.call(this, v, this, e);
            this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, v, this, e);
            this.fireEvent(BI.BasicButton.EVENT_CHANGE, v, this);
            if (o.action) {
                BI.Actions.runAction(o.action, "click", o, this);
            }
            BI.Actions.runGlobalAction("click", o, this);
        }
    },

    _doClick: function (e) {
        if (this.isValid()) {
            this.beforeClick(e);
        }
        this._trigger(e);
        if (this.isValid()) {
            this.doClick(e);
        }
    },

    beforeClick: function () {

    },

    doClick: function () {

    },

    handle: function () {
        return this;
    },

    hover: function () {
        this._hover = true;
        this.handle().element.addClass("hover");
        if (this.options.shadow) {
            this.$mask && this.$mask.setVisible(true);
        }
    },

    dishover: function () {
        this._hover = false;
        this.handle().element.removeClass("hover");
        if (this.options.shadow) {
            this.$mask && this.$mask.setVisible(false);
        }
    },

    setSelected: function (b) {
        var o = this.options;
        o.selected = b;
        if (b) {
            this.handle().element.addClass("active");
        } else {
            this.handle().element.removeClass("active");
        }
        if (o.shadow && !o.isShadowShowingOnSelected) {
            this.$mask && this.$mask.setVisible(false);
        }
        this.options.setSelected && this.options.setSelected.call(this, b);
    },

    isSelected: function () {
        return this.options.selected;
    },

    isOnce: function () {
        return this.options.once;
    },

    isForceSelected: function () {
        return this.options.forceSelected;
    },

    isForceNotSelected: function () {
        return this.options.forceNotSelected;
    },

    isDisableSelected: function () {
        return this.options.disableSelected;
    },

    setText: function (text) {
        this.options.text = text;
        this.options.setText && this.options.setText.call(this, text);
    },

    getText: function () {
        return this.options.text;
    },

    _setEnable: function (enable) {
        BI.BasicButton.superclass._setEnable.apply(this, arguments);
        if (enable === true) {
            this.element.removeClass("base-disabled disabled");
        } else if (enable === false) {
            this.element.addClass("base-disabled disabled");
        }
        if (!enable) {
            if (this.options.shadow) {
                this.$mask && this.$mask.setVisible(false);
            }
        }
    },

    empty: function () {
        BI.Widget._renderEngine.createElement(document).unbind("mouseup." + this.getName());
        BI.BasicButton.superclass.empty.apply(this, arguments);
    }
});
BI.BasicButton.EVENT_CHANGE = "BasicButton.EVENT_CHANGE";
BI.shortcut("bi.basic_button", BI.BasicButton);
<commit_msg>basic_button支持el<commit_after>/**
 * guy
 * @class BI.BasicButton
 * @extends BI.Single
 *
 * 一般的button父级
 */
BI.BasicButton = BI.inherit(BI.Single, {
    _defaultConfig: function () {
        var conf = BI.BasicButton.superclass._defaultConfig.apply(this, arguments);
        return BI.extend(conf, {
            _baseCls: (conf._baseCls || "") + " bi-basic-button" + (conf.invalid ? "" : " cursor-pointer") + ((BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""),
            // el: {} // 可以通过el来创建button元素
            value: "",
            stopEvent: false,
            stopPropagation: false,
            selected: false,
            once: false, // 点击一次选中有效,再点无效
            forceSelected: false, // 点击即选中, 选中了就不会被取消,与once的区别是forceSelected不影响事件的触发
            forceNotSelected: false, // 无论怎么点击都不会被选中
            disableSelected: false, // 使能选中

            shadow: false,
            isShadowShowingOnSelected: false,  // 选中状态下是否显示阴影
            trigger: null,
            handler: BI.emptyFn,
            bubble: null
        });
    },

    _init: function () {
        BI.BasicButton.superclass._init.apply(this, arguments);
        var opts = this.options;
        if (opts.selected === true) {
            BI.nextTick(BI.bind(function () {
                this.setSelected(opts.selected);
            }, this));
        }
        BI.nextTick(BI.bind(this.bindEvent, this));

        if (opts.shadow) {
            this._createShadow();
        }
        if (opts.level) {
            this.element.addClass("button-" + opts.level);
        }
    },

    // 默认render方法
    render: function () {
        return this.options.el;
    },

    _createShadow: function () {
        var self = this, o = this.options;

        var assertMask = function () {
            if (!self.$mask) {
                self.$mask = BI.createWidget(BI.isObject(o.shadow) ? o.shadow : {}, {
                    type: "bi.layout",
                    cls: "bi-button-mask"
                });
                self.$mask.invisible();
                BI.createWidget({
                    type: "bi.absolute",
                    element: self,
                    items: [{
                        el: self.$mask,
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }]
                });
            }
        };

        this.element.mouseup(function () {
            if (!self._hover && !o.isShadowShowingOnSelected) {
                assertMask();
                self.$mask.invisible();
            }
        });
        this.element.on("mouseenter." + this.getName(), function (e) {
            if (self.element.__isMouseInBounds__(e)) {
                if (self.isEnabled() && !self._hover && (o.isShadowShowingOnSelected || !self.isSelected())) {
                    assertMask();
                    self.$mask.visible();
                }
            }
        });
        this.element.on("mousemove." + this.getName(), function (e) {
            if (!self.element.__isMouseInBounds__(e)) {
                if (self.isEnabled() && !self._hover) {
                    assertMask();
                    self.$mask.invisible();
                }
            }
        });
        this.element.on("mouseleave." + this.getName(), function () {
            if (self.isEnabled() && !self._hover) {
                assertMask();
                self.$mask.invisible();
            }
        });
    },

    bindEvent: function () {
        var self = this;
        var o = this.options, hand = this.handle();
        if (!hand) {
            return;
        }
        hand = hand.element;
        var triggerArr = (o.trigger || "").split(",");
        BI.each(triggerArr, function (idx, trigger) {
            switch (trigger) {
                case "mouseup":
                    var mouseDown = false;
                    hand.mousedown(function () {
                        mouseDown = true;
                    });
                    hand.mouseup(function (e) {
                        if (mouseDown === true) {
                            clk(e);
                        }
                        mouseDown = false;
                        ev(e);
                    });
                    break;
                case "mousedown":
                    var mouseDown = false;
                    var selected = false;
                    hand.mousedown(function (e) {
                        // if (e.button === 0) {
                        BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
                            // if (e.button === 0) {
                            if (BI.DOM.isExist(self) && !hand.__isMouseInBounds__(e) && mouseDown === true && !selected) {
                                // self.setSelected(!self.isSelected());
                                self._trigger();
                            }
                            mouseDown = false;
                            BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                            // }
                        });
                        if (mouseDown === true) {
                            return;
                        }
                        if (self.isSelected()) {
                            selected = true;
                        } else {
                            clk(e);
                        }
                        mouseDown = true;
                        ev(e);
                        // }
                    });
                    hand.mouseup(function (e) {
                        // if (e.button === 0) {
                        if (BI.DOM.isExist(self) && mouseDown === true && selected === true) {
                            clk(e);
                        }
                        mouseDown = false;
                        selected = false;
                        BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                        // }
                    });
                    break;
                case "dblclick":
                    hand.dblclick(clk);
                    break;
                case "lclick":
                    var mouseDown = false;
                    var interval;
                    hand.mousedown(function (e) {
                        BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
                            interval && clearInterval(interval);
                            interval = null;
                            mouseDown = false;
                            BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
                        });
                        if (mouseDown === true) {
                            return;
                        }
                        if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
                            return;
                        }
                        interval = setInterval(function () {
                            if (self.isEnabled()) {
                                self.doClick();
                            }
                        }, 180);
                        mouseDown = true;
                        ev(e);
                    });
                    break;
                default:
                    if (o.stopEvent || o.stopPropagation) {
                        hand.mousedown(function (e) {
                            ev(e);
                        });
                    }
                    hand.click(clk);
                    break;
            }
        });

        // 之后的300ms点击无效
        var onClick = BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, {
            "leading": true,
            "trailing": false
        });

        function ev (e) {
            if (o.stopEvent) {
                e.stopEvent();
            }
            if (o.stopPropagation) {
                e.stopPropagation();
            }
        }

        function clk (e) {
            ev(e);
            if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
                return;
            }
            if (BI.isKey(o.bubble) || BI.isFunction(o.bubble)) {
                if (BI.isNull(self.combo)) {
                    var popup;
                    BI.createWidget({
                        type: "bi.absolute",
                        element: self,
                        items: [{
                            el: {
                                type: "bi.bubble_combo",
                                trigger: "",
                                // bubble的提示不需要一直存在在界面上
                                destroyWhenHide: true,
                                ref: function () {
                                    self.combo = this;
                                },
                                el: {
                                    type: "bi.layout",
                                    height: "100%"
                                },
                                popup: {
                                    type: "bi.text_bubble_bar_popup_view",
                                    text: getBubble(),
                                    ref: function () {
                                        popup = this;
                                    },
                                    listeners: [{
                                        eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON,
                                        action: function (v) {
                                            self.combo.hideView();
                                            if (v) {
                                                onClick.apply(self, arguments);
                                            }
                                        }
                                    }]
                                },
                                listeners: [{
                                    eventName: BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW,
                                    action: function () {
                                        popup.populate(getBubble());
                                    }
                                }]
                            },
                            left: 0,
                            right: 0,
                            bottom: 0,
                            top: 0
                        }]
                    });
                }
                if (self.combo.isViewVisible()) {
                    self.combo.hideView();
                } else {
                    self.combo.showView();
                }
                return;
            }
            onClick.apply(self, arguments);
        }

        function getBubble () {
            var bubble = self.options.bubble;
            if (BI.isFunction(bubble)) {
                return bubble();
            }
            return bubble;
        }
    },

    _trigger: function (e) {
        var o = this.options;
        if (!this.isEnabled()) {
            return;
        }
        if (!this.isDisableSelected()) {
            this.isForceSelected() ? this.setSelected(true) :
                (this.isForceNotSelected() ? this.setSelected(false) :
                    this.setSelected(!this.isSelected()));
        }
        if (this.isValid()) {
            var v = this.getValue();
            o.handler.call(this, v, this, e);
            this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, v, this, e);
            this.fireEvent(BI.BasicButton.EVENT_CHANGE, v, this);
            if (o.action) {
                BI.Actions.runAction(o.action, "click", o, this);
            }
            BI.Actions.runGlobalAction("click", o, this);
        }
    },

    _doClick: function (e) {
        if (this.isValid()) {
            this.beforeClick(e);
        }
        this._trigger(e);
        if (this.isValid()) {
            this.doClick(e);
        }
    },

    beforeClick: function () {

    },

    doClick: function () {

    },

    handle: function () {
        return this;
    },

    hover: function () {
        this._hover = true;
        this.handle().element.addClass("hover");
        if (this.options.shadow) {
            this.$mask && this.$mask.setVisible(true);
        }
    },

    dishover: function () {
        this._hover = false;
        this.handle().element.removeClass("hover");
        if (this.options.shadow) {
            this.$mask && this.$mask.setVisible(false);
        }
    },

    setSelected: function (b) {
        var o = this.options;
        o.selected = b;
        if (b) {
            this.handle().element.addClass("active");
        } else {
            this.handle().element.removeClass("active");
        }
        if (o.shadow && !o.isShadowShowingOnSelected) {
            this.$mask && this.$mask.setVisible(false);
        }
        this.options.setSelected && this.options.setSelected.call(this, b);
    },

    isSelected: function () {
        return this.options.selected;
    },

    isOnce: function () {
        return this.options.once;
    },

    isForceSelected: function () {
        return this.options.forceSelected;
    },

    isForceNotSelected: function () {
        return this.options.forceNotSelected;
    },

    isDisableSelected: function () {
        return this.options.disableSelected;
    },

    setText: function (text) {
        this.options.text = text;
        this.options.setText && this.options.setText.call(this, text);
    },

    getText: function () {
        return this.options.text;
    },

    _setEnable: function (enable) {
        BI.BasicButton.superclass._setEnable.apply(this, arguments);
        if (enable === true) {
            this.element.removeClass("base-disabled disabled");
        } else if (enable === false) {
            this.element.addClass("base-disabled disabled");
        }
        if (!enable) {
            if (this.options.shadow) {
                this.$mask && this.$mask.setVisible(false);
            }
        }
    },

    empty: function () {
        BI.Widget._renderEngine.createElement(document).unbind("mouseup." + this.getName());
        BI.BasicButton.superclass.empty.apply(this, arguments);
    }
});
BI.BasicButton.EVENT_CHANGE = "BasicButton.EVENT_CHANGE";
BI.shortcut("bi.basic_button", BI.BasicButton);
<|endoftext|>


<commit_before>module.exports = function () {
    return {
      unit: {
        configFile: 'karma-conf.js',
        autoWatch: false,
        singleRun: true
      },
      e2e: {
        configFile: 'karma-e2e.conf.js',
        autoWatch: false,
        singleRun: true
      }
    }
};
<commit_msg>Update<commit_after>module.exports = function () {
    return {
      unit: {
        configFile: 'karma.conf.js',
        autoWatch: false,
        singleRun: true
      },
      e2e: {
        configFile: 'karma-e2e.conf.js',
        autoWatch: false,
        singleRun: true
      }
    }
};
<|endoftext|>


<commit_before>import React, {PropTypes, PureComponent} from 'react';
import NotificationGroup from './notification-group';
import NotificationAdd from './notification-add';
import NotificationError from './notification-error';

import { addNotification, readNotification, readNotificationGroup, closeCenter } from '../actions';
import { fetchNotifications } from '../actions/fetch-notifications';
import {getConfig} from '../config';

function translate(key) {
    const {translateText} = getConfig();
    return translateText(key);
}

class NotificationCenterPanel extends PureComponent {
    constructor(props) {
        super(props);
        this._hideBodyOverflow = this._hideBodyOverflow.bind(this);
        this._restoreBodyOverflow = this._restoreBodyOverflow.bind(this);
        this._onClosePanel = this._onClosePanel.bind(this);
    }
    componentDidMount() {
        this._hideBodyOverflow();
    }
    /**
    * Store the body overgflow property, and set it to hidden
    */
    _hideBodyOverflow() {
        document.body.style['overflow-y'] = 'hidden';
    }
    /**
    * Restore body overflow property
    */
    _restoreBodyOverflow() {
        document.body.style['overflow-y'] = 'auto';
    }
    _onClosePanel(evt) {
        const {onClosePanel} = this.props;
        onClosePanel(evt);
        this._restoreBodyOverflow();
    }
    render() {
        const {hasAddNotif, isFetching, unreadNotifs, onGroupRead, onSingleRead, onSingleClick, onTitleClick, onAddClick, onDismissError, error, zIndex, panelHeader, panelFooter} = this.props;
        const {translateText} = getConfig();
        const hasNotifications = unreadNotifs.length > 0;
        return (

                        <button className='mdl-button mdl-button--icon' data-focus='notification-center-close' onClick={this._onClosePanel}>{'clear'}</button>

{translateText('focus.notifications.title')}

                        {panelHeader && panelHeader}

                    {hasAddNotif && <NotificationAdd onAddClick={onAddClick} />}
                    {error && <NotificationError onDismiss={onDismissError} {...error}/>}
                    {hasNotifications &&
                        <NotificationGroup
                            data={unreadNotifs}
                            onGroupRead={onGroupRead}
                            onSingleRead={onSingleRead}
                            onSingleClick={onSingleClick} />
                    }
                    {!hasNotifications &&

{translate('focus.notifications.nothing')}

                    }
                    {panelFooter && {panelFooter}}

        );
    }
}
NotificationCenterPanel.displayName = 'NotificationCenterPanel';
NotificationCenterPanel.propTypes = {
    error: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
    onDismissError: PropTypes.func.isRequired,
    hasAddNotif: PropTypes.bool.isRequired,
    isFetching: PropTypes.bool.isRequired,
    unreadNotifs: PropTypes.array.isRequired,
    onGroupRead: PropTypes.func.isRequired,
    onSingleClick: PropTypes.func.isRequired,
    onSingleRead: PropTypes.func.isRequired,
    onClosePanel: PropTypes.func.isRequired,
    onTitleClick: PropTypes.func.isRequired,
    onAddClick: PropTypes.func.isRequired,
    zIndex: PropTypes.number.isRequired
};
export default NotificationCenterPanel;
<commit_msg>fix restore overflow-y to visible<commit_after>import React, { PropTypes, PureComponent } from 'react';
import NotificationGroup from './notification-group';
import NotificationAdd from './notification-add';
import NotificationError from './notification-error';

import { addNotification, readNotification, readNotificationGroup, closeCenter } from '../actions';
import { fetchNotifications } from '../actions/fetch-notifications';
import { getConfig } from '../config';

function translate(key) {
    const { translateText } = getConfig();
    return translateText(key);
}

class NotificationCenterPanel extends PureComponent {
    constructor(props) {
        super(props);
        this._hideBodyOverflow = this._hideBodyOverflow.bind(this);
        this._restoreBodyOverflow = this._restoreBodyOverflow.bind(this);
        this._onClosePanel = this._onClosePanel.bind(this);
    }
    componentDidMount() {
        this._hideBodyOverflow();
    }
    /**
    * Store the body overgflow property, and set it to hidden
    */
    _hideBodyOverflow() {
        document.body.style['overflow-y'] = 'hidden';
    }
    /**
    * Restore body overflow property
    */
    _restoreBodyOverflow() {
        document.body.style['overflow-y'] = 'visible';
    }
    _onClosePanel(evt) {
        const { onClosePanel } = this.props;
        onClosePanel(evt);
        this._restoreBodyOverflow();
    }
    render() {
        const { hasAddNotif, isFetching, unreadNotifs, onGroupRead, onSingleRead, onSingleClick, onTitleClick, onAddClick, onDismissError, error, zIndex, panelHeader, panelFooter } = this.props;
        const { translateText } = getConfig();
        const hasNotifications = unreadNotifs.length > 0;
        return (

                        <button className='mdl-button mdl-button--icon' data-focus='notification-center-close' onClick={this._onClosePanel}>{'clear'}</button>

{translateText('focus.notifications.title')}

                        {panelHeader && panelHeader}

                    {hasAddNotif && <NotificationAdd onAddClick={onAddClick} />}
                    {error && <NotificationError onDismiss={onDismissError} {...error} />}
                    {hasNotifications &&
                        <NotificationGroup
                            data={unreadNotifs}
                            onGroupRead={onGroupRead}
                            onSingleRead={onSingleRead}
                            onSingleClick={onSingleClick}
                        />
                    }
                    {!hasNotifications &&

{translate('focus.notifications.nothing')}

                    }
                    {panelFooter && {panelFooter}}

        );
    }
}
NotificationCenterPanel.displayName = 'NotificationCenterPanel';
NotificationCenterPanel.propTypes = {
    error: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
    onDismissError: PropTypes.func.isRequired,
    hasAddNotif: PropTypes.bool.isRequired,
    isFetching: PropTypes.bool.isRequired,
    unreadNotifs: PropTypes.array.isRequired,
    onGroupRead: PropTypes.func.isRequired,
    onSingleClick: PropTypes.func.isRequired,
    onSingleRead: PropTypes.func.isRequired,
    onClosePanel: PropTypes.func.isRequired,
    onTitleClick: PropTypes.func.isRequired,
    onAddClick: PropTypes.func.isRequired,
    zIndex: PropTypes.number.isRequired
};
export default NotificationCenterPanel;
<|endoftext|>


<commit_before>import { consoleError } from '../../../util/console'
import * as easingPatterns from '../../../util/easing-patterns'

const defaults = {
  duration: 500,
  offset: 0,
  easing: 'easeInOutCubic'
}

function getDocumentHeight () {
  return Math.max(
    document.body.scrollHeight,
    document.documentElement.scrollHeight,
    document.body.offsetHeight,
    document.documentElement.offsetHeight,
    document.body.clientHeight,
    document.documentElement.clientHeight
  )
}

function getWindowHeight () {
  return window.innerHeight ||
    (document.documentElement || document.body).clientHeight
}

function isVueComponent (obj) {
  return obj &&
    obj.constructor &&
    obj.constructor.name === 'VueComponent'
}

function getTargetLocation (target, settings) {
  let location

  if (target instanceof Element) {
    location = target.offsetTop
  } else if (isVueComponent(target)) {
    location = target.$el.offsetTop
  } else if (typeof target === 'string') {
    location = document.querySelector(target).offsetTop
  } else if (typeof target === 'number') {
    location = target
  } else {
    return undefined
  }

  return Math.round(
    Math.min(
      Math.max(location + settings.offset, 0),
      getDocumentHeight() - getWindowHeight()
    )
  )
}

export default function goTo (target, options) {
  if (typeof window === 'undefined') return

  const settings = Object.assign({}, defaults, options)

  const startTime = performance.now()
  const startLocation = window.pageYOffset
  const targetLocation = getTargetLocation(target, settings)
  const distanceToScroll = targetLocation - startLocation
  const easingFunction = typeof settings.easing === 'function' ? settings.easing : easingPatterns[settings.easing]

  if (isNaN(targetLocation)) {
    const type = target && target.constructor ? target.constructor.name : target
    return consoleError(`Target must be a Selector/Number/DOMElement/VueComponent, received ${type} instead.`)
  }
  if (!easingFunction) return consoleError(`Easing function '${settings.easing}' not found.`)

  function step (currentTime) {
    let progressPercentage = Math.min(1, ((currentTime - startTime) / settings.duration))
    let targetPosition = Math.floor(startLocation + distanceToScroll * easingFunction(progressPercentage))

    window.scrollTo(0, targetPosition)
    if (Math.round(window.pageYOffset) === targetLocation) return
    window.requestAnimationFrame(step)
  }

  window.requestAnimationFrame(step)
}
<commit_msg>fix(goTo) Always respect progressPercentage. Fixes #3608 (#3609)<commit_after>import { consoleError } from '../../../util/console'
import * as easingPatterns from '../../../util/easing-patterns'

const defaults = {
  duration: 500,
  offset: 0,
  easing: 'easeInOutCubic'
}

function getDocumentHeight () {
  return Math.max(
    document.body.scrollHeight,
    document.documentElement.scrollHeight,
    document.body.offsetHeight,
    document.documentElement.offsetHeight,
    document.body.clientHeight,
    document.documentElement.clientHeight
  )
}

function getWindowHeight () {
  return window.innerHeight ||
    (document.documentElement || document.body).clientHeight
}

function isVueComponent (obj) {
  return obj &&
    obj.constructor &&
    obj.constructor.name === 'VueComponent'
}

function getTargetLocation (target, settings) {
  let location

  if (target instanceof Element) {
    location = target.offsetTop
  } else if (isVueComponent(target)) {
    location = target.$el.offsetTop
  } else if (typeof target === 'string') {
    location = document.querySelector(target).offsetTop
  } else if (typeof target === 'number') {
    location = target
  } else {
    return undefined
  }

  return Math.round(
    Math.min(
      Math.max(location + settings.offset, 0),
      getDocumentHeight() - getWindowHeight()
    )
  )
}

export default function goTo (target, options) {
  if (typeof window === 'undefined') return

  const settings = Object.assign({}, defaults, options)

  const startTime = performance.now()
  const startLocation = window.pageYOffset
  const targetLocation = getTargetLocation(target, settings)
  const distanceToScroll = targetLocation - startLocation
  const easingFunction = typeof settings.easing === 'function' ? settings.easing : easingPatterns[settings.easing]

  if (isNaN(targetLocation)) {
    const type = target && target.constructor ? target.constructor.name : target
    return consoleError(`Target must be a Selector/Number/DOMElement/VueComponent, received ${type} instead.`)
  }
  if (!easingFunction) return consoleError(`Easing function '${settings.easing}' not found.`)

  function step (currentTime) {
    let progressPercentage = Math.min(1, ((currentTime - startTime) / settings.duration))
    let targetPosition = Math.floor(startLocation + distanceToScroll * easingFunction(progressPercentage))

    window.scrollTo(0, targetPosition)

    if (
      Math.round(window.pageYOffset) === targetLocation ||
      progressPercentage === 1
    ) return

    window.requestAnimationFrame(step)
  }

  window.requestAnimationFrame(step)
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
    Text,
    View,
    TouchableOpacity
} from 'react-native';
import { EventModal } from './common';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { SPECIAL_SUBJECTS } from '../actions/defaults';
import _ from 'lodash';
import i18n from 'react-native-i18n';
import bundledTranslations from '../translations';
import ListItem from './EventItemComponent';

class WeekView extends Component {
    state = {
        columnWidth: -1,
        showEventModal: false
    };

    componentDidMount() {
        Actions.refresh({key: 'timetable', title: i18n.t('week_view')});
    }

    setEventModal(eventJSON) {
        let masterdataJSON = JSON.parse(this.props.masterdata);
        let eventLecturers = [];

        let eventName = _.find(masterdataJSON["programs"][this.props.program]["courses"], { 'course': eventJSON["course"] })["shortname"];
        let eventRoom = eventJSON["rooms"][0];
        for (let lecturer in eventJSON["lecturers"]) {
            eventLecturers.push(_.get(masterdataJSON["persons"], eventJSON["lecturers"][lecturer])["name"]);
        }
        eventLecturers = JSON.stringify(eventLecturers);
        let eventNote = eventJSON["note"];
        let eventSlot = eventJSON["slot"];

        let contentEventModal = (
            <ListItem eventName={eventName} eventRoom={eventRoom} eventLecturers={eventLecturers} eventNote={eventNote} eventSlot={eventSlot}/>
        );

        this.setState({ contentEventModal: contentEventModal });

        this.setState({ showEventModal: true });
    }

    closeEventModal() {
        this.setState({ showEventModal: false });
    }

    renderEventModal() {
        return this.state.contentEventModal;
    }

    renderTimeslots() {
        let slots = this.props.slots;
        const realSlots = slots.slice(1);  // Used a constant here to avoid the slicing on every call of the method

        return realSlots.map((slots) =>
            <View key={slots.start} style={styles.slotView}>
                <Text style={styles.slotsText}>{slots.start}</Text>
                <Text style={styles.slotsText}>—</Text>
                <Text style={styles.slotsText}>{slots.end}</Text>
            </View>
        );
    }

    renderDay(day) {
        if (this.state.columnWidth !== -1) {  // Only trigger after the width of a day column was read
            let dayEvents = _.filter(this.props.events, { 'day': day });

            let masterdataJSON = JSON.parse(this.props.masterdata);
            let eventShortname;
            let eventNote;

            let special_subjectProgram = SPECIAL_SUBJECTS[this.props.program];
            let special_subjectRegEx = '';
            for (let special_subject in special_subjectProgram) {
                special_subjectRegEx += `(${special_subjectProgram[special_subject]["shortname"].toUpperCase()})`;
                if ((parseInt(special_subject) + 1) !== special_subjectProgram.length) {  // Check if it's NOT the last iteration
                    special_subjectRegEx += '|'
                }
            }
            special_subjectRegEx = new RegExp(special_subjectRegEx);

            for (let event in dayEvents) {
                eventShortname = _.find(masterdataJSON["programs"][this.props.program]["courses"], { 'course': dayEvents[event]["course"] })["shortname"];
                dayEvents[event].shortname = eventShortname;
                eventNote = dayEvents[event]["note"];

                if (this.props.special_subject !== 'all' && !eventShortname.includes(this.props.special_subject.toUpperCase())) {
                    if (
                        !special_subjectRegEx.test(eventShortname) ||  // If the 'event' is not a 'special_subject'
                        this.props.program + this.props.semester !== this.props.user  // If the user changed their default semester
                    ) {
                        dayEvents[event].toRemove = false;
                    } else {
                        dayEvents[event].toRemove = true;
                    }
                }
            }

            _.remove(dayEvents, 'toRemove');

            return dayEvents.map((event) =>
                <TouchableOpacity
                    key={event.timestamp}
                    onPress={this.setEventModal.bind(this, event)}
                    activeOpacity={0.8}
                    style={[
                        styles.dayView,
                        {
                            top: (((parseInt(event.start) - 1) * 100)),  // How far from the top of the day column should be located
                            height: ((parseInt(event.end) - parseInt(event.start)) * 100),  // Calculate the height of the event if it spans multiple timeslots
                            width: ((this.state.columnWidth / parseInt(event.multiple))),  // Take the calculated total width of a day column and divide it by how many concurrent events there are
                            left: ((parseInt(event.candidate) - 1) * (this.state.columnWidth / parseInt(event.multiple))),  // If there are multiple events in one timeslot move them next to each other based on the 'candidate' value from the API
                            right: ((parseInt(event.candidate) - parseInt(event.multiple)) * (this.state.columnWidth / parseInt(event.multiple)))
                        }
                    ]}
                >
                    <Text>
                        {event.shortname}
                    </Text>
                </TouchableOpacity>
            );
        }
    }

    renderCells() {
        let cells = [];
        let slots = this.props.slots;
        const realSlots = slots.slice(1);  // Used a constant here to avoid the slicing on every call of the method

        for (let i = 0; i < realSlots.length; i++) {
            cells.push(i * 100);
        }

        return cells.map((event) =>
            <View key={event} style={[styles.cellView, { top: event }]}>
            </View>
        );
    }

    render() {
        return (
            <View style={styles.columnContainer}>
                <View style={styles.slotsColumn}>
                    <Text style={styles.columnHeader}>{i18n.t('timeslots')}</Text>
                    {this.renderTimeslots()}
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Mon')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('mon')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Tue')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('tue')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Wed')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('wed')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Thu')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('thu')}
                    </View>
                </View>
                <View
                    style={styles.column}
                    onLayout={(event) => { this.setState({columnWidth: event.nativeEvent.layout.width}); }}  // Saves the width of a day column used for calculating the width of a slot with multiple events
                >
                    <Text style={styles.columnHeader}>{i18n.t('Fri')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('fri')}
                    </View>
                </View>
                <EventModal
                    visible={this.state.showEventModal}
                    onClose={this.closeEventModal.bind(this)}
                >
                    {this.renderEventModal()}
                </EventModal>
            </View>
        );
    }
}

i18n.fallbacks = true;
i18n.translations = bundledTranslations;

const styles = {
    columnContainer: {
        flex: 1,
        flexDirection: "row",
        paddingTop: 10,
        paddingBottom: 10,
        paddingLeft: 10,
        paddingRight: 10
    },
    columnHeader: {
        fontSize: 18,
        fontWeight: "bold",
        alignSelf: "center",
        marginBottom: 18
    },
    column: {
        flex: 1,
        flexDirection: "column",
        marginLeft: 2.5,
        marginRight: 2.5
    },
    slotsColumn: {
        flexDirection: "column",
        marginRight: 15
    },
    slotView: {
        justifyContent: "center",
        alignItems: "center",
        height: 100
    },
    dayView: {
        alignSelf: "center",
        alignItems: "center",
        position: "absolute",
        height: 100,
        backgroundColor: "white",
        borderWidth: 1,
        borderColor: "black",
        padding: 10,
        elevation: 2.5,
        shadowColor: '#333333',
        shadowOffset: {
          width: 0,
          height: 1
        },
        shadowRadius: 1,
        shadowOpacity: 0.60
    },
    cellView: {
        position: "absolute",
        left: 0,
        right: 0,
        height: 100,
        backgroundColor: "#EEEEEE",
        borderTopWidth: 3,
        borderTopColor: "white"
    },
    eventCell: {
        position: "relative"
    },
    slotsText: {
        fontSize: 15,
        fontWeight: "bold"
    }
};

const mapStateToProps = state => {
    return {
        user: state.login.user,
        program: state.login.program,
        masterdata: state.timetable.masterdata,
        slots: state.timetable.timeslots,
        semester: state.settings.semester,
        special_subject: state.settings.special_subject
    }
};

export default connect(mapStateToProps, {})(WeekView);
<commit_msg>Closed Issue #17<commit_after>import React, { Component } from 'react';
import {
    Text,
    View,
    TouchableOpacity,
    Platform
} from 'react-native';
import { EventModal } from './common';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { SPECIAL_SUBJECTS } from '../actions/defaults';
import _ from 'lodash';
import i18n from 'react-native-i18n';
import bundledTranslations from '../translations';
import ListItem from './EventItemComponent';

class WeekView extends Component {
    state = {
        columnWidth: -1,
        showEventModal: false
    };

    componentDidMount() {
        Actions.refresh({key: 'timetable', title: i18n.t('week_view')});
    }

    setEventModal(eventJSON) {
        let masterdataJSON = JSON.parse(this.props.masterdata);
        let eventLecturers = [];

        let eventName = _.find(masterdataJSON["programs"][this.props.program]["courses"], { 'course': eventJSON["course"] })["shortname"];
        let eventRoom = eventJSON["rooms"][0];
        for (let lecturer in eventJSON["lecturers"]) {
            eventLecturers.push(_.get(masterdataJSON["persons"], eventJSON["lecturers"][lecturer])["name"]);
        }
        eventLecturers = JSON.stringify(eventLecturers);
        let eventNote = eventJSON["note"];
        let eventSlot = eventJSON["slot"];

        let contentEventModal = (
            <ListItem eventName={eventName} eventRoom={eventRoom} eventLecturers={eventLecturers} eventNote={eventNote} eventSlot={eventSlot}/>
        );

        this.setState({ contentEventModal: contentEventModal });

        this.setState({ showEventModal: true });
    }

    closeEventModal() {
        this.setState({ showEventModal: false });
    }

    renderEventModal() {
        return this.state.contentEventModal;
    }

    renderTimeslots() {
        let slots = this.props.slots;
        const realSlots = slots.slice(1);  // Used a constant here to avoid the slicing on every call of the method

        return realSlots.map((slots) =>
            <View key={slots.start} style={styles.slotView}>
                <Text style={styles.slotsText}>{slots.start}</Text>
                <Text style={styles.slotsText}>—</Text>
                <Text style={styles.slotsText}>{slots.end}</Text>
            </View>
        );
    }

    renderDay(day) {
        if (this.state.columnWidth !== -1) {  // Only trigger after the width of a day column was read
            let dayEvents = _.filter(this.props.events, { 'day': day });

            let masterdataJSON = JSON.parse(this.props.masterdata);
            let eventShortname;
            let eventNote;

            let special_subjectProgram = SPECIAL_SUBJECTS[this.props.program];
            let special_subjectRegEx = '';
            for (let special_subject in special_subjectProgram) {
                special_subjectRegEx += `(${special_subjectProgram[special_subject]["shortname"].toUpperCase()})`;
                if ((parseInt(special_subject) + 1) !== special_subjectProgram.length) {  // Check if it's NOT the last iteration
                    special_subjectRegEx += '|'
                }
            }
            special_subjectRegEx = new RegExp(special_subjectRegEx);

            for (let event in dayEvents) {
                eventShortname = _.find(masterdataJSON["programs"][this.props.program]["courses"], { 'course': dayEvents[event]["course"] })["shortname"];
                dayEvents[event].shortname = eventShortname;
                eventNote = dayEvents[event]["note"];

                if (this.props.special_subject !== 'all' && !eventShortname.includes(this.props.special_subject.toUpperCase())) {
                    if (
                        !special_subjectRegEx.test(eventShortname) ||  // If the 'event' is not a 'special_subject'
                        this.props.program + this.props.semester !== this.props.user  // If the user changed their default semester
                    ) {
                        dayEvents[event].toRemove = false;
                    } else {
                        dayEvents[event].toRemove = true;
                    }
                }
            }

            _.remove(dayEvents, 'toRemove');

            return dayEvents.map((event) =>
                <TouchableOpacity
                    key={event.timestamp}
                    onPress={this.setEventModal.bind(this, event)}
                    activeOpacity={0.8}
                    style={[
                        styles.dayView,
                        {
                            top: (((parseInt(event.start) - 1) * 100)),  // How far from the top of the day column should be located
                            height: ((parseInt(event.end) - parseInt(event.start)) * 100),  // Calculate the height of the event if it spans multiple timeslots
                            width: ((this.state.columnWidth / parseInt(event.multiple))),  // Take the calculated total width of a day column and divide it by how many concurrent events there are
                            left: ((parseInt(event.candidate) - 1) * (this.state.columnWidth / parseInt(event.multiple))),  // If there are multiple events in one timeslot move them next to each other based on the 'candidate' value from the API
                            right: ((parseInt(event.candidate) - parseInt(event.multiple)) * (this.state.columnWidth / parseInt(event.multiple)))
                        }
                    ]}
                >
                    <Text>
                        {event.shortname}
                    </Text>
                </TouchableOpacity>
            );
        }
    }

    renderCells() {
        let cells = [];
        let slots = this.props.slots;
        const realSlots = slots.slice(1);  // Used a constant here to avoid the slicing on every call of the method

        for (let i = 0; i < realSlots.length; i++) {
            cells.push(i * 100);
        }

        return cells.map((event) =>
            <View key={event} style={[styles.cellView, { top: event }]}>
            </View>
        );
    }

    render() {
        return (
            <View style={styles.columnContainer}>
                <View style={styles.slotsColumn}>
                    <Text style={styles.columnHeader}>{i18n.t('timeslots')}</Text>
                    {this.renderTimeslots()}
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Mon')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('mon')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Tue')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('tue')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Wed')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('wed')}
                    </View>
                </View>
                <View style={styles.column}>
                    <Text style={styles.columnHeader}>{i18n.t('Thu')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('thu')}
                    </View>
                </View>
                <View
                    style={styles.column}
                    onLayout={(event) => { this.setState({columnWidth: event.nativeEvent.layout.width}); }}  // Saves the width of a day column used for calculating the width of a slot with multiple events
                >
                    <Text style={styles.columnHeader}>{i18n.t('Fri')}</Text>
                    <View style={styles.eventCell}>
                        {this.renderCells()}
                        {this.renderDay('fri')}
                    </View>
                </View>
                <EventModal
                    visible={this.state.showEventModal}
                    onClose={this.closeEventModal.bind(this)}
                >
                    {this.renderEventModal()}
                </EventModal>
            </View>
        );
    }
}

i18n.fallbacks = true;
i18n.translations = bundledTranslations;

const styles = {
    columnContainer: {
        flex: 1,
        flexDirection: "row",
        paddingTop: 10,
        paddingBottom: 10,
        paddingLeft: 10,
        paddingRight: 10
    },
    columnHeader: {
        fontSize: (Platform.OS === 'android') ? 18 : 14,
        fontWeight: "bold",
        alignSelf: "center",
        marginBottom: 18
    },
    column: {
        flex: 1,
        flexDirection: "column",
        marginLeft: 2.5,
        marginRight: 2.5
    },
    slotsColumn: {
        flexDirection: "column",
        marginRight: 15
    },
    slotView: {
        justifyContent: "center",
        alignItems: "center",
        height: 100
    },
    dayView: {
        alignSelf: "center",
        alignItems: "center",
        position: "absolute",
        height: 100,
        backgroundColor: "white",
        borderWidth: 1,
        borderColor: "black",
        padding: 10,
        elevation: 2.5,
        shadowColor: '#333333',
        shadowOffset: {
          width: 0,
          height: 1
        },
        shadowRadius: 1,
        shadowOpacity: 0.60
    },
    cellView: {
        position: "absolute",
        left: 0,
        right: 0,
        height: 100,
        backgroundColor: "#EEEEEE",
        borderTopWidth: 3,
        borderTopColor: "white"
    },
    eventCell: {
        position: "relative"
    },
    slotsText: {
        fontSize: 15,
        fontWeight: "bold"
    }
};

const mapStateToProps = state => {
    return {
        user: state.login.user,
        program: state.login.program,
        masterdata: state.timetable.masterdata,
        slots: state.timetable.timeslots,
        semester: state.settings.semester,
        special_subject: state.settings.special_subject
    }
};

export default connect(mapStateToProps, {})(WeekView);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import d3 from 'd3';
import moment from 'moment';

class BGLSummary extends Component {
    render() {
        const valueExtent = d3.extent(this.props.data, (d) => (d.value));

        const timeExtent = d3.extent(this.props.data, (d) => (d.timestamp)).map((d) => (moment(d).format('MMM Mo, YYYY h:MM a')));

        const median = d3.median(this.props.data, (d) => (d.value));

        const deviation = d3.deviation(this.props.data, (d) => (d.value));

        /**
         * d3 scales accept an input domain (consider this like calibration values), and output valus in a specified range
         * this can be numeric, color interpolation, or categories!
         */
        const colorScale = d3.scale.linear().domain(valueExtent).range(['green', 'red']);

        const randomReading = this.props.data[Math.floor(this.props.data.length * Math.random())] || {};

        console.log(randomReading);

        return (

Data Summary

The records begin on {timeExtent[0]}, and continue through {timeExtent[1]}.

Values range from {valueExtent[0]} to {valueExtent[1]}.

The median value is {median}.

The standard deviation is {deviation}.

If we make a cool color scale, a glucose reading of {randomReading.value} would be this color.

        );
    }
}

export default BGLSummary;
<commit_msg>Updating summary page<commit_after>import React, { Component, PropTypes } from 'react';
import d3 from 'd3';
import moment from 'moment';

class BGLSummary extends Component {
    render() {
        const valueExtent = d3.extent(this.props.data, (d) => (d.value));

        const timeExtent = d3.extent(this.props.data, (d) => (d.timestamp)).map((d) => (moment(d).format('MMM Mo, YYYY h:MM a')));

        const median = d3.median(this.props.data, (d) => (d.value));

        const deviation = d3.deviation(this.props.data, (d) => (d.value));

        const highs = this.props.data.filter((d) => (d.value > 180));

        const lows = this.props.data.filter((d) => (d.value < 65));

        /**
         * d3 scales accept an input domain (consider this like calibration values), and output valus in a specified range
         * this can be numeric, color interpolation, or categories!
         */
        const colorScale = d3.scale.linear().domain(valueExtent).range(['green', 'red']);

        const randomReading = this.props.data[Math.floor(this.props.data.length * Math.random())] || {};

        console.log(randomReading);

        return (

Data Summary

The records begin on {timeExtent[0]}, and continue through {timeExtent[1]}.

Values range from {valueExtent[0]} to {valueExtent[1]}.

The median value is {median}.

The standard deviation is {deviation}.

In this data set, there are {lows.length} low glucose readings, about {Math.round(100 * lows.length / this.props.data.length)}% of all readings

In this data set, there are {highs.length} high glucose readings, about {Math.round(100 * highs.length / this.props.data.length)}% of all readings

If we make a cool color scale, a glucose reading of {randomReading.value} would be this color.

        );
    }
}

export default BGLSummary;
<|endoftext|>


<commit_before>import listenOnRootMixin from '../../mixins/listen-on-root'
import { hasClass, reflow, getCS, getBCR, eventOn, eventOff } from '../../utils/dom'

// Events we emit on $root
const EVENT_STATE = 'bv::collapse::state'
const EVENT_ACCORDION = 'bv::collapse::accordion'
// Events we listen to on $root
const EVENT_TOGGLE = 'bv::toggle::collapse'

export default {
  mixins: [listenOnRootMixin],
  render (h) {
    const content = h(
      this.tag,
      {
        class: this.classObject,
        directives: [ { name: 'show', value: this.show } ],
        attrs: { id: this.id || null },
        on: { click: this.clickHandler }
      },
      [ this.$slots.default ]
    )
    return h(
      'transition',
      {
        props: {
          enterClass: '',
          enterActiveClass: 'collapsing',
          enterToClass: '',
          leaveClass: '',
          leaveActiveClass: 'collapsing',
          leaveToClass: ''
        },
        on: {
          enter: this.onEnter,
          afterEnter: this.onAfterEnter,
          leave: this.onLeave,
          afterLeave: this.onAfterLeave
        }
      },
      [ content ]
    )
  },
  data () {
    return {
      show: this.visible,
      transitioning: false
    }
  },
  model: {
    prop: 'visible',
    event: 'input'
  },
  props: {
    id: {
      type: String,
      required: true
    },
    isNav: {
      type: Boolean,
      default: false
    },
    accordion: {
      type: String,
      default: null
    },
    visible: {
      type: Boolean,
      default: false
    },
    tag: {
      type: String,
      default: 'div'
    }
  },
  watch: {
    visible (newVal) {
      if (newVal !== this.show) {
        this.show = newVal
      }
    },
    show (newVal, oldVal) {
      if (newVal !== oldVal) {
        this.emitState()
      }
    }
  },
  computed: {
    classObject () {
      return {
        'navbar-collapse': this.isNav,
        'collapse': !this.transitioning,
        'show': this.show && !this.transitioning
      }
    }
  },
  methods: {
    toggle () {
      this.show = !this.show
    },
    onEnter (el) {
      el.style.height = 0
      reflow(el)
      el.style.height = el.scrollHeight + 'px'
      this.transitioning = true
      // This should be moved out so we can add cancellable events
      this.$emit('show')
    },
    onAfterEnter (el) {
      el.style.height = null
      this.transitioning = false
      this.$emit('shown')
    },
    onLeave (el) {
      el.style.height = 'auto'
      el.style.display = 'block'
      el.style.height = getBCR(el).height + 'px'
      reflow(el)
      this.transitioning = true
      el.style.height = 0
      // This should be moved out so we can add cancellable events
      this.$emit('hide')
    },
    onAfterLeave (el) {
      el.style.height = null
      this.transitioning = false
      this.$emit('hidden')
    },
    emitState () {
      this.$emit('input', this.show)
      // Let v-b-toggle know the state of this collapse
      this.$root.$emit(EVENT_STATE, this.id, this.show)
      if (this.accordion && this.show) {
        // Tell the other collapses in this accordion to close
        this.$root.$emit(EVENT_ACCORDION, this.id, this.accordion)
      }
    },
    clickHandler (evt) {
      // If we are in a nav/navbar, close the collapse when non-disabled link clicked
      const el = evt.target
      if (!this.isNav || !el || getCS(this.$el).display !== 'block') {
        return
      }
      if (hasClass(el, 'nav-link') || hasClass(el, 'dropdown-item')) {
        this.show = false
      }
    },
    handleToggleEvt (target) {
      if (target !== this.id) {
        return
      }
      this.toggle()
    },
    handleAccordionEvt (openedId, accordion) {
      if (!this.accordion || accordion !== this.accordion) {
        return
      }
      if (openedId === this.id) {
        // Open this collapse if not shown
        if (!this.show) {
          this.toggle()
        }
      } else {
        // Close this collapse if shown
        if (this.show) {
          this.toggle()
        }
      }
    },
    handleResize () {
      // Handler for orientation/resize to set collapsed state in nav/navbar
      this.show = (getCS(this.$el).display === 'block')
    }
  },
  created () {
    // Listen for toggle events to open/close us
    this.listenOnRoot(EVENT_TOGGLE, this.handleToggleEvt)
    // Listen to otehr collapses for accordion events
    this.listenOnRoot(EVENT_ACCORDION, this.handleAccordionEvt)
  },
  mounted () {
    if (this.isNav && typeof document !== 'undefined') {
      // Set up handlers
      eventOn(window, 'resize', this.handleResize, false)
      eventOn(window, 'orientationchange', this.handleResize, false)
      this.handleResize()
    }
    this.emitState()
  },
  updated () {
    this.$root.$emit(EVENT_STATE, this.id, this.show)
  },
  beforeDestroy () {
    if (this.isNav && typeof document !== 'undefined') {
      eventOff(window, 'resize', this.handleResize, false)
      eventOff(window, 'orientationchange', this.handleResize, false)
    }
  }
}
<commit_msg>fix(collapse): when is-nav, do better checking of click events (Fixes #2222) (#2225)<commit_after>import listenOnRootMixin from '../../mixins/listen-on-root'
import { closest, matches, reflow, getCS, getBCR, eventOn, eventOff } from '../../utils/dom'

// Events we emit on $root
const EVENT_STATE = 'bv::collapse::state'
const EVENT_ACCORDION = 'bv::collapse::accordion'
// Events we listen to on $root
const EVENT_TOGGLE = 'bv::toggle::collapse'

export default {
  mixins: [listenOnRootMixin],
  render (h) {
    const content = h(
      this.tag,
      {
        class: this.classObject,
        directives: [ { name: 'show', value: this.show } ],
        attrs: { id: this.id || null },
        on: { click: this.clickHandler }
      },
      [ this.$slots.default ]
    )
    return h(
      'transition',
      {
        props: {
          enterClass: '',
          enterActiveClass: 'collapsing',
          enterToClass: '',
          leaveClass: '',
          leaveActiveClass: 'collapsing',
          leaveToClass: ''
        },
        on: {
          enter: this.onEnter,
          afterEnter: this.onAfterEnter,
          leave: this.onLeave,
          afterLeave: this.onAfterLeave
        }
      },
      [ content ]
    )
  },
  data () {
    return {
      show: this.visible,
      transitioning: false
    }
  },
  model: {
    prop: 'visible',
    event: 'input'
  },
  props: {
    id: {
      type: String,
      required: true
    },
    isNav: {
      type: Boolean,
      default: false
    },
    accordion: {
      type: String,
      default: null
    },
    visible: {
      type: Boolean,
      default: false
    },
    tag: {
      type: String,
      default: 'div'
    }
  },
  watch: {
    visible (newVal) {
      if (newVal !== this.show) {
        this.show = newVal
      }
    },
    show (newVal, oldVal) {
      if (newVal !== oldVal) {
        this.emitState()
      }
    }
  },
  computed: {
    classObject () {
      return {
        'navbar-collapse': this.isNav,
        'collapse': !this.transitioning,
        'show': this.show && !this.transitioning
      }
    }
  },
  methods: {
    toggle () {
      this.show = !this.show
    },
    onEnter (el) {
      el.style.height = 0
      reflow(el)
      el.style.height = el.scrollHeight + 'px'
      this.transitioning = true
      // This should be moved out so we can add cancellable events
      this.$emit('show')
    },
    onAfterEnter (el) {
      el.style.height = null
      this.transitioning = false
      this.$emit('shown')
    },
    onLeave (el) {
      el.style.height = 'auto'
      el.style.display = 'block'
      el.style.height = getBCR(el).height + 'px'
      reflow(el)
      this.transitioning = true
      el.style.height = 0
      // This should be moved out so we can add cancellable events
      this.$emit('hide')
    },
    onAfterLeave (el) {
      el.style.height = null
      this.transitioning = false
      this.$emit('hidden')
    },
    emitState () {
      this.$emit('input', this.show)
      // Let v-b-toggle know the state of this collapse
      this.$root.$emit(EVENT_STATE, this.id, this.show)
      if (this.accordion && this.show) {
        // Tell the other collapses in this accordion to close
        this.$root.$emit(EVENT_ACCORDION, this.id, this.accordion)
      }
    },
    clickHandler (evt) {
      // If we are in a nav/navbar, close the collapse when non-disabled link clicked
      const el = evt.target
      if (!this.isNav || !el || getCS(this.$el).display !== 'block') {
        return
      }
      if (matches(el, '.nav-link,.dropdown-item') || closest('.nav-link,.dropdown-item', el)) {
        this.show = false
      }
    },
    handleToggleEvt (target) {
      if (target !== this.id) {
        return
      }
      this.toggle()
    },
    handleAccordionEvt (openedId, accordion) {
      if (!this.accordion || accordion !== this.accordion) {
        return
      }
      if (openedId === this.id) {
        // Open this collapse if not shown
        if (!this.show) {
          this.toggle()
        }
      } else {
        // Close this collapse if shown
        if (this.show) {
          this.toggle()
        }
      }
    },
    handleResize () {
      // Handler for orientation/resize to set collapsed state in nav/navbar
      this.show = (getCS(this.$el).display === 'block')
    }
  },
  created () {
    // Listen for toggle events to open/close us
    this.listenOnRoot(EVENT_TOGGLE, this.handleToggleEvt)
    // Listen to otehr collapses for accordion events
    this.listenOnRoot(EVENT_ACCORDION, this.handleAccordionEvt)
  },
  mounted () {
    if (this.isNav && typeof document !== 'undefined') {
      // Set up handlers
      eventOn(window, 'resize', this.handleResize, false)
      eventOn(window, 'orientationchange', this.handleResize, false)
      this.handleResize()
    }
    this.emitState()
  },
  updated () {
    this.$root.$emit(EVENT_STATE, this.id, this.show)
  },
  beforeDestroy () {
    if (this.isNav && typeof document !== 'undefined') {
      eventOff(window, 'resize', this.handleResize, false)
      eventOff(window, 'orientationchange', this.handleResize, false)
    }
  }
}
<|endoftext|>


<commit_before>import _each from 'lodash/each';
import _cloneDeep from 'lodash/cloneDeep';
import _clone from 'lodash/clone';
import _isArray from 'lodash/isArray';
import { FormioComponents } from '../Components';
export class DataGridComponent extends FormioComponents {
  constructor(component, options, data) {
    super(component, options, data);
    this.type = 'datagrid';
  }

  build() {
    this.createElement();
    this.createLabel(this.element);
    if (!this.data.hasOwnProperty(this.component.key)) {
      this.addNewValue();
    }
    this.visibleColumns = true;
    this.buildTable();
    this.createDescription(this.element);
  }

  buildTable(data) {
    data = data || {};
    if (this.tableElement) {
      this.element.removeChild(this.tableElement);
      this.tableElement.innerHTML = '';
    }

    let tableClass = 'table datagrid-table table-bordered form-group formio-data-grid ';
    _each(['striped', 'bordered', 'hover', 'condensed'], (prop) => {
      if (this.component[prop]) {
        tableClass += 'table-' + prop + ' ';
      }
    });
    this.tableElement = this.ce('table', {
      class: tableClass
    });

    let thead = this.ce('thead');

    // Build the header.
    let tr = this.ce('tr');
    _each(this.component.components, (comp) => {
      if ((this.visibleColumns === true) || (this.visibleColumns[comp.key])) {
        let th = this.ce('th');
        if (comp.validate && comp.validate.required) {
          th.setAttribute('class', 'field-required');
        }
        let title = comp.label || comp.title;
        if (title) {
          th.appendChild(this.text(title));
          this.createTooltip(th, comp);
        }
        tr.appendChild(th);
      }
    });

    // Add the remove column if it is not disabled.
    if (!this.shouldDisable) {
      let th = this.ce('th');
      tr.appendChild(th);

      // add the "+" - "add another" button
      if (this.component.addAnotherPosition === "top" || this.component.addAnotherPosition === "both") {
        th.appendChild(this.addIconButton());
        tr.appendChild(th);
      }
    }

    thead.appendChild(tr);
    this.tableElement.appendChild(thead);

    // Create the table body.
    this.tbody = this.ce('tbody');

    // Build the rows.
    this.buildRows(data);

    // Add the body to the table and to the element.
    this.tableElement.appendChild(this.tbody);
    this.element.appendChild(this.tableElement);
  }

  get defaultValue() {
    return {};
  }

  buildRows(data) {
    this.tbody.innerHTML = '';
    this.rows = [];
    this.components = [];
    _each(this.data[this.component.key], (row, index) => {
      let tr = this.ce('tr');
      let cols = {};
      _each(this.component.components, (col) => {
        let column = _cloneDeep(col);
        column.label = false;
        column.row = this.row + '-' + index;
        let options = _clone(this.options);
        options.name += '[' + index + ']';
        let comp = this.createComponent(column, options, row);
        if (row.hasOwnProperty(column.key)) {
          comp.setValue(row[column.key]);
        }
        else if (comp.type === 'components') {
          comp.setValue(row);
        }
        cols[column.key] = comp;
        if ((this.visibleColumns === true) || this.visibleColumns[col.key]) {
          let td = this.ce('td');
          td.appendChild(comp.element);
          tr.appendChild(td);
          comp.checkConditions(data);
        }
      });
      this.rows.push(cols);

      // Add the remove column if not disabled.
      if (!this.shouldDisable) {
        let td = this.ce('td');
        td.appendChild(this.removeButton(index));
        tr.appendChild(td);
      }

      this.tbody.appendChild(tr);
    });

    // Add the add button if not disabled.
    if (!this.shouldDisable && (
      !this.component.addAnotherPosition ||
      this.component.addAnotherPosition === "bottom" ||
      this.component.addAnotherPosition === "both"
      )){
        let tr = this.ce('tr');
        let td = this.ce('td', {
          colspan: (this.component.components.length + 1)
        });
        td.appendChild(this.addButton());
        tr.appendChild(td);
        this.tbody.appendChild(tr);

      // if(
      //   this.component.addAnotherPosition === "top" ||
      //   this.component.addAnotherPosition === "both"
      // ){
      //   let tr = this.ce('tr');
      //   let td = this.ce('td', {
      //     colspan: (this.component.components.length)
      //   });
      //   td.appendChild(this.addIconButton());
      //   tr.appendChild(td);
      //   this.tbody.appendChild(tr);
      // }
    }
  }

  checkConditions(data) {
    let show = super.checkConditions(data);
    let rebuild = false;
    if (this.visibleColumns === true) {
      this.visibleColumns = {};
    }
    _each(this.component.components, (col) => {
      let showColumn = false;
      _each(this.rows, (comps) => {
        showColumn |= comps[col.key].checkConditions(data);
      });
      if (
        (this.visibleColumns[col.key] && !showColumn) ||
        (!this.visibleColumns[col.key] && showColumn)
      ) {
        rebuild = true
      }

      this.visibleColumns[col.key] = showColumn;
      show |= showColumn;
    });

    // If a rebuild is needed, then rebuild the table.
    if (rebuild && show) {
      this.buildTable(data);
    }

    // Return if this table should show.
    return show;
  }

  setValue(value, flags) {
    flags = this.getFlags.apply(this, arguments);
    if (!value) {
      return;
    }
    if (!_isArray(value)) {
      return;
    }

    this.value = value;

    // Add needed rows.
    for (let i=this.rows.length; i < value.length; i++) {
      this.addValue();
    }

    _each(this.rows, (row, index) => {
      if (value.length <= index) {
        return;
      }
      _each(row, (col, key) => {
        if (col.type === 'components') {
          col.setValue(value[index], flags);
        }
        else if (value[index].hasOwnProperty(key)) {
          col.setValue(value[index][key], flags);
        }
      });
    });
  }

  /**
   * Get the value of this component.
   *
   * @returns {*}
   */
  getValue() {
    let values = [];
    _each(this.rows, (row) => {
      let value = {};
      _each(row, (col) => {
        if (
          col &&
          col.component &&
          col.component.key
        ) {
          value[col.component.key] = col.getValue();
        }
      });
      values.push(value);
    });
    return values;
  }
}
<commit_msg>Removed commented code<commit_after>import _each from 'lodash/each';
import _cloneDeep from 'lodash/cloneDeep';
import _clone from 'lodash/clone';
import _isArray from 'lodash/isArray';
import { FormioComponents } from '../Components';
export class DataGridComponent extends FormioComponents {
  constructor(component, options, data) {
    super(component, options, data);
    this.type = 'datagrid';
  }

  build() {
    this.createElement();
    this.createLabel(this.element);
    if (!this.data.hasOwnProperty(this.component.key)) {
      this.addNewValue();
    }
    this.visibleColumns = true;
    this.buildTable();
    this.createDescription(this.element);
  }

  buildTable(data) {
    data = data || {};
    if (this.tableElement) {
      this.element.removeChild(this.tableElement);
      this.tableElement.innerHTML = '';
    }

    let tableClass = 'table datagrid-table table-bordered form-group formio-data-grid ';
    _each(['striped', 'bordered', 'hover', 'condensed'], (prop) => {
      if (this.component[prop]) {
        tableClass += 'table-' + prop + ' ';
      }
    });
    this.tableElement = this.ce('table', {
      class: tableClass
    });

    let thead = this.ce('thead');

    // Build the header.
    let tr = this.ce('tr');
    _each(this.component.components, (comp) => {
      if ((this.visibleColumns === true) || (this.visibleColumns[comp.key])) {
        let th = this.ce('th');
        if (comp.validate && comp.validate.required) {
          th.setAttribute('class', 'field-required');
        }
        let title = comp.label || comp.title;
        if (title) {
          th.appendChild(this.text(title));
          this.createTooltip(th, comp);
        }
        tr.appendChild(th);
      }
    });

    // Add the remove column if it is not disabled.
    if (!this.shouldDisable) {
      let th = this.ce('th');
      tr.appendChild(th);

      // add the "+" - "add another" button
      if (this.component.addAnotherPosition === "top" || this.component.addAnotherPosition === "both") {
        th.appendChild(this.addIconButton());
        tr.appendChild(th);
      }
    }

    thead.appendChild(tr);
    this.tableElement.appendChild(thead);

    // Create the table body.
    this.tbody = this.ce('tbody');

    // Build the rows.
    this.buildRows(data);

    // Add the body to the table and to the element.
    this.tableElement.appendChild(this.tbody);
    this.element.appendChild(this.tableElement);
  }

  get defaultValue() {
    return {};
  }

  buildRows(data) {
    this.tbody.innerHTML = '';
    this.rows = [];
    this.components = [];
    _each(this.data[this.component.key], (row, index) => {
      let tr = this.ce('tr');
      let cols = {};
      _each(this.component.components, (col) => {
        let column = _cloneDeep(col);
        column.label = false;
        column.row = this.row + '-' + index;
        let options = _clone(this.options);
        options.name += '[' + index + ']';
        let comp = this.createComponent(column, options, row);
        if (row.hasOwnProperty(column.key)) {
          comp.setValue(row[column.key]);
        }
        else if (comp.type === 'components') {
          comp.setValue(row);
        }
        cols[column.key] = comp;
        if ((this.visibleColumns === true) || this.visibleColumns[col.key]) {
          let td = this.ce('td');
          td.appendChild(comp.element);
          tr.appendChild(td);
          comp.checkConditions(data);
        }
      });
      this.rows.push(cols);

      // Add the remove column if not disabled.
      if (!this.shouldDisable) {
        let td = this.ce('td');
        td.appendChild(this.removeButton(index));
        tr.appendChild(td);
      }

      this.tbody.appendChild(tr);
    });

    // Add the add button if not disabled.
    if (!this.shouldDisable && (
      !this.component.addAnotherPosition ||
      this.component.addAnotherPosition === "bottom" ||
      this.component.addAnotherPosition === "both"
      )){
        let tr = this.ce('tr');
        let td = this.ce('td', {
          colspan: (this.component.components.length + 1)
        });
        td.appendChild(this.addButton());
        tr.appendChild(td);
        this.tbody.appendChild(tr);
    }
  }

  checkConditions(data) {
    let show = super.checkConditions(data);
    let rebuild = false;
    if (this.visibleColumns === true) {
      this.visibleColumns = {};
    }
    _each(this.component.components, (col) => {
      let showColumn = false;
      _each(this.rows, (comps) => {
        showColumn |= comps[col.key].checkConditions(data);
      });
      if (
        (this.visibleColumns[col.key] && !showColumn) ||
        (!this.visibleColumns[col.key] && showColumn)
      ) {
        rebuild = true
      }

      this.visibleColumns[col.key] = showColumn;
      show |= showColumn;
    });

    // If a rebuild is needed, then rebuild the table.
    if (rebuild && show) {
      this.buildTable(data);
    }

    // Return if this table should show.
    return show;
  }

  setValue(value, flags) {
    flags = this.getFlags.apply(this, arguments);
    if (!value) {
      return;
    }
    if (!_isArray(value)) {
      return;
    }

    this.value = value;

    // Add needed rows.
    for (let i=this.rows.length; i < value.length; i++) {
      this.addValue();
    }

    _each(this.rows, (row, index) => {
      if (value.length <= index) {
        return;
      }
      _each(row, (col, key) => {
        if (col.type === 'components') {
          col.setValue(value[index], flags);
        }
        else if (value[index].hasOwnProperty(key)) {
          col.setValue(value[index][key], flags);
        }
      });
    });
  }

  /**
   * Get the value of this component.
   *
   * @returns {*}
   */
  getValue() {
    let values = [];
    _each(this.rows, (row) => {
      let value = {};
      _each(row, (col) => {
        if (
          col &&
          col.component &&
          col.component.key
        ) {
          value[col.component.key] = col.getValue();
        }
      });
      values.push(value);
    });
    return values;
  }
}
<|endoftext|>