<commit_before>const {remote} = require('electron')
const {Menu} = remote
const {h, Component} = require('preact')
const classNames = require('classnames')
const Pikaday = require('pikaday')

const Drawer = require('./Drawer')

const gametree = require('../../modules/gametree')
const helper = require('../../modules/helper')
const setting = remote.require('./modules/setting')
const {sgf} = require('../../modules/fileformats')

class InfoDrawerItem extends Component {
    render({title, children}) {
        return h('li', {},
            h('label', {},
                h('span', {}, title + ':'),
                children[0]
            ),
            children.slice(1)
        )
    }
}

class InfoDrawer extends Component {
    constructor() {
        super()

        this.handleSubmitButtonClick = evt => {
            evt.preventDefault()

            let [tree, index] = this.props.treePosition
            let emptyTree = !tree.parent && tree.nodes.length === 1 && tree.subtrees.length === 0

            let keys = ['blackName', 'blackRank', 'whiteName', 'whiteRank',
                'gameName', 'eventName', 'date', 'result', 'komi']

            let data = keys.reduce((acc, key) => {
                acc[key] = Array.isArray(this.state[key])
                    && this.state[key].every(x => x == null) ? null : this.state[key]
                return acc
            }, {})

            if (emptyTree) {
                data.handicap = this.state.handicap
                data.size = this.state.size
            }

            sabaki.setGameInfo(this.props.treePosition[0], data)
            sabaki.closeDrawer()
            sabaki.attachEngines(...this.state.engines)

            sabaki.setState(sabaki.state, () => {
                let i = this.props.currentPlayer > 0 ? 0 : 1

                if (sabaki.attachedEngineControllers[i] != null) {
                    sabaki.startGeneratingMoves()
                }
            })
        }

        this.handleCancelButtonClick = evt => {
            evt.preventDefault()
            sabaki.closeDrawer()
        }

        this.handleBoardWidthFocus = () => {
            this.combinedSizeFields = this.state.size[0] === this.state.size[1]
        }

        this.handleBoardWidthChange = evt => {
            let {value} = evt.currentTarget
            if (value === '') value = null

            this.setState(({size: [, height]}) => ({
                size: [value, this.combinedSizeFields ? value : height]
            }))
        }

        this.handleBoardHeightChange = evt => {
            let {value} = evt.currentTarget
            if (value === '') value = null

            this.setState(({size: [width, ]}) => ({size: [width, value]}))
        }

        this.handleSizeSwapButtonClick = () => {
            this.setState(({size}) => ({size: size.reverse()}))
        }

        this.handleSwapPlayers = () => {
            this.setState(({engines, blackName, blackRank, whiteName, whiteRank}) => ({
                engines: (engines || [null, null]).reverse(),
                blackName: whiteName,
                whiteName: blackName,
                blackRank: whiteRank,
                whiteRank: blackRank
            }))
        }

        this.handleDateInputChange = evt => {
            this.setState({date: evt.currentTarget.value})
            this.markDates()
        }

        this.handleDateInputFocus = () => {
            this.pikaday.show()
        }

        this.handleDateInputBlur = () => {
            setTimeout(() => {
                if (!this.elementInPikaday(document.activeElement))
                    this.pikaday.hide()
            }, 50)
        }

        this.handleInputChange = [
            'blackRank',
            'blackName',
            'whiteRanke',
            'whiteName',
            'gameName',
            'eventName',
            'komi',
            'result',
            'handicap'
        ].reduce((acc, key) => {
            acc[key] = ({currentTarget}) => {
                this.setState({[key]: currentTarget.value === '' ? null : currentTarget.value})
            }

            return acc
        }, {})

        this.handleEngineMenuClick = [0, 1].map(index => evt => {
            let engines = setting.get('engines.list')
            let nameKeys = ['blackName', 'whiteName']
            let template = [
                {
                    label: 'Manual',
                    type: 'checkbox',
                    checked: this.state.engines[index] == null,
                    click: () => {
                        let {engines} = this.state
                        if (engines[index] == null) return

                        engines[index] = null
                        this.setState({engines})
                    }
                },
                {type: 'separator'},
                ...engines.map(engine => ({
                    label: engine.name.trim() || '(Unnamed Engine)',
                    type: 'checkbox',
                    checked: engine === this.state.engines[index],
                    click: () => {
                        let {engines} = this.state
                        engines[index] = engine
                        this.setState({engines})
                    }
                })),
                engines.length > 0 && {type: 'separator'},
                {
                    label: 'Manage Engines…',
                    click: () => {
                        sabaki.setState({preferencesTab: 'engines'})
                        sabaki.openDrawer('preferences')
                    }
                }
            ].filter(x => !!x)

            let {left, bottom} = evt.currentTarget.getBoundingClientRect()
            let menu = Menu.buildFromTemplate(template)

            menu.popup(sabaki.window, {
                async: true,
                x: Math.round(left),
                y: Math.round(bottom)
            })
        })
    }

    componentWillReceiveProps({gameInfo, engines, show}) {
        if (!this.props.show && show) {
            this.setState(gameInfo)
            this.setState({engines: [...engines]})
        }
    }

    componentDidMount() {
        this.preparePikaday()
    }

    shouldComponentUpdate({show}) {
        return show !== this.props.show || show
    }

    markDates(pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        let dates = (sgf.string2dates(this.state.date || '') || []).filter(x => x.length === 3)

        for (let el of pikaday.el.querySelectorAll('.pika-button')) {
            let year = +el.dataset.pikaYear
            let month = +el.dataset.pikaMonth
            let day = +el.dataset.pikaDay

            el.parentElement.classList.toggle('is-multi-selected', dates.some(d => {
                return helper.shallowEquals(d, [year, month + 1, day])
            }))
        }
    }

    adjustPikadayPosition(pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        let {left, top} = this.dateInputElement.getBoundingClientRect()
        let {height} = pikaday.el.getBoundingClientRect()

        pikaday.el.style.position = 'absolute'
        pikaday.el.style.left = Math.round(left) + 'px'
        pikaday.el.style.top = Math.round(top - height) + 'px'
    }

    elementInPikaday(element, pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        while (element.parentElement) {
            if (element === pikaday.el) return true
            element = element.parentElement
        }

        return false
    }

    preparePikaday() {
        let self = this

        this.pikaday = new Pikaday({
            position: 'top left',
            firstDay: 1,
            yearRange: 6,
            onOpen() {
                let dates = (sgf.string2dates(self.state.date || '') || []).filter(x => x.length === 3)

                if (dates.length > 0) {
                    this.setDate(dates[0].join('-'), true)
                } else {
                    this.gotoToday()
                }

                self.adjustPikadayPosition(this)
            },
            onDraw() {
                if (!this.isVisible()) return

                self.adjustPikadayPosition(this)
                self.markDates(this)

                self.dateInputElement.focus()
            },
            onSelect() {
                let dates = sgf.string2dates(self.state.date || '') || []
                let date = this.getDate()
                date = [date.getFullYear(), date.getMonth() + 1, date.getDate()]

                if (!dates.some(x => helper.shallowEquals(x, date))) {
                    dates.push(date)
                } else {
                    dates = dates.filter(x => !helper.shallowEquals(x, date))
                }

                self.setState({date: sgf.dates2string(dates.sort(helper.lexicalCompare))})
            }
        })

        this.pikaday.hide()

        document.body.appendChild(this.pikaday.el)
        document.body.addEventListener('click', evt => {
            if (this.pikaday.isVisible()
            && document.activeElement !== this.dateInputElement
            && evt.target !== this.dateInputElement
            && !this.elementInPikaday(evt.target))
                this.pikaday.hide()
        })

        window.addEventListener('resize', () => this.adjustPikadayPosition())
    }

    render({
        treePosition,
        currentPlayer,
        show
    }, {
        engines = [null, null],
        blackName = null,
        blackRank = null,
        whiteName = null,
        whiteRank = null,
        gameName = null,
        eventName = null,
        date = null,
        result = null,
        komi = null,
        handicap = 0,
        size = [null, null]
    }) {
        let [tree, index] = treePosition
        let emptyTree = !tree.parent && tree.nodes.length === 1 && tree.subtrees.length === 0

        return h(Drawer,
            {
                type: 'info',
                show
            },

            h('form', {},
                h('section', {},
                    h('span', {},
                        h('img', {
                            src: './node_modules/octicons/build/svg/chevron-down.svg',
                            width: 16,
                            height: 16,
                            class: classNames({menu: true, active: engines[0] != null}),
                            onClick: this.handleEngineMenuClick[0]
                        }), ' ',

                        h('input', {
                            type: 'text',
                            name: 'rank_1',
                            placeholder: 'Rank',
                            value: blackRank,
                            onInput: this.handleInputChange.blackRank
                        }),

                        h('input', {
                            type: 'text',
                            name: 'name_1',
                            placeholder: 'Black',
                            value: blackName,
                            onInput: this.handleInputChange.blackName
                        })
                    ),

                    h('img', {
                        class: 'current-player',
                        src: `./img/ui/player_${currentPlayer}.svg`,
                        height: 31,
                        title: 'Swap',
                        onClick: this.handleSwapPlayers
                    }),

                    h('span', {},
                        h('input', {
                            type: 'text',
                            name: 'name_-1',
                            placeholder: 'White',
                            value: whiteName,
                            onInput: this.handleInputChange.whiteName
                        }),

                        h('input', {
                            type: 'text',
                            name: 'rank_-1',
                            placeholder: 'Rank',
                            value: whiteRank,
                            onInput: this.handleInputChange.whiteRank
                        }), ' ',

                        h('img', {
                            src: './node_modules/octicons/build/svg/chevron-down.svg',
                            width: 16,
                            height: 16,
                            class: classNames({menu: true, active: engines[1] != null}),
                            onClick: this.handleEngineMenuClick[1]
                        })
                    )
                ),

                h('ul', {},
                    h(InfoDrawerItem, {title: 'Name'},
                        h('input', {
                            type: 'text',
                            placeholder: '(Unnamed)',
                            value: gameName,
                            onInput: this.handleInputChange.gameName
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Event'},
                        h('input', {
                            type: 'text',
                            placeholder: 'None',
                            value: eventName,
                            onInput: this.handleInputChange.eventName
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Date'},
                        h('input', {
                            ref: el => this.dateInputElement = el,
                            type: 'text',
                            placeholder: 'None',
                            value: date,

                            onFocus: this.handleDateInputFocus,
                            onBlur: this.handleDateInputBlur,
                            onInput: this.handleDateInputChange
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Komi'},
                        h('input', {
                            type: 'number',
                            name: 'komi',
                            step: 0.5,
                            placeholder: 0,
                            value: komi == null ? '' : komi,
                            onInput: this.handleInputChange.komi
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Result'},
                        h('input', {
                            type: 'text',
                            placeholder: 'None',
                            value: result,
                            onInput: this.handleInputChange.result
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Handicap'},
                        h('select',
                            {
                                selectedIndex: Math.max(0, handicap - 1),
                                disabled: !emptyTree,
                                onChange: this.handleInputChange.handicap
                            },

                            h('option', {value: 0}, 'No stones'),
                            [...Array(8)].map((_, i) =>
                                h('option', {value: i + 2}, (i + 2) + ' stones')
                            )
                        )
                    ),
                    h(InfoDrawerItem, {title: 'Board Size'},
                        h('input', {
                            type: 'number',
                            name: 'size-width',
                            placeholder: 19,
                            max: 25,
                            min: 3,
                            value: size[0],
                            disabled: !emptyTree,
                            onFocus: this.handleBoardWidthFocus,
                            onInput: this.handleBoardWidthChange
                        }), ' ',

                        h('span', {
                            title: 'Swap',
                            style: {cursor: emptyTree ? 'pointer': 'default'},
                            onClick: !emptyTree ? helper.noop : this.handleSizeSwapButtonClick
                        }, '×'), ' ',

                        h('input', {
                            type: 'number',
                            name: 'size-height',
                            placeholder: 19,
                            max: 25,
                            min: 3,
                            value: size[1],
                            disabled: !emptyTree,
                            onInput: this.handleBoardHeightChange
                        })
                    )
                ),

                h('p', {},
                    h('button', {type: 'submit', onClick: this.handleSubmitButtonClick}, 'OK'), ' ',
                    h('button', {type: 'reset', onClick: this.handleCancelButtonClick}, 'Cancel')
                )
            )
        )
    }
}

module.exports = InfoDrawer
<commit_msg>[Fix #202] Fix typo in InfoDrawer.js<commit_after>const {remote} = require('electron')
const {Menu} = remote
const {h, Component} = require('preact')
const classNames = require('classnames')
const Pikaday = require('pikaday')

const Drawer = require('./Drawer')

const gametree = require('../../modules/gametree')
const helper = require('../../modules/helper')
const setting = remote.require('./modules/setting')
const {sgf} = require('../../modules/fileformats')

class InfoDrawerItem extends Component {
    render({title, children}) {
        return h('li', {},
            h('label', {},
                h('span', {}, title + ':'),
                children[0]
            ),
            children.slice(1)
        )
    }
}

class InfoDrawer extends Component {
    constructor() {
        super()

        this.handleSubmitButtonClick = evt => {
            evt.preventDefault()

            let [tree, index] = this.props.treePosition
            let emptyTree = !tree.parent && tree.nodes.length === 1 && tree.subtrees.length === 0

            let keys = ['blackName', 'blackRank', 'whiteName', 'whiteRank',
                'gameName', 'eventName', 'date', 'result', 'komi']

            let data = keys.reduce((acc, key) => {
                acc[key] = Array.isArray(this.state[key])
                    && this.state[key].every(x => x == null) ? null : this.state[key]
                return acc
            }, {})

            if (emptyTree) {
                data.handicap = this.state.handicap
                data.size = this.state.size
            }

            sabaki.setGameInfo(this.props.treePosition[0], data)
            sabaki.closeDrawer()
            sabaki.attachEngines(...this.state.engines)

            sabaki.setState(sabaki.state, () => {
                let i = this.props.currentPlayer > 0 ? 0 : 1

                if (sabaki.attachedEngineControllers[i] != null) {
                    sabaki.startGeneratingMoves()
                }
            })
        }

        this.handleCancelButtonClick = evt => {
            evt.preventDefault()
            sabaki.closeDrawer()
        }

        this.handleBoardWidthFocus = () => {
            this.combinedSizeFields = this.state.size[0] === this.state.size[1]
        }

        this.handleBoardWidthChange = evt => {
            let {value} = evt.currentTarget
            if (value === '') value = null

            this.setState(({size: [, height]}) => ({
                size: [value, this.combinedSizeFields ? value : height]
            }))
        }

        this.handleBoardHeightChange = evt => {
            let {value} = evt.currentTarget
            if (value === '') value = null

            this.setState(({size: [width, ]}) => ({size: [width, value]}))
        }

        this.handleSizeSwapButtonClick = () => {
            this.setState(({size}) => ({size: size.reverse()}))
        }

        this.handleSwapPlayers = () => {
            this.setState(({engines, blackName, blackRank, whiteName, whiteRank}) => ({
                engines: (engines || [null, null]).reverse(),
                blackName: whiteName,
                whiteName: blackName,
                blackRank: whiteRank,
                whiteRank: blackRank
            }))
        }

        this.handleDateInputChange = evt => {
            this.setState({date: evt.currentTarget.value})
            this.markDates()
        }

        this.handleDateInputFocus = () => {
            this.pikaday.show()
        }

        this.handleDateInputBlur = () => {
            setTimeout(() => {
                if (!this.elementInPikaday(document.activeElement))
                    this.pikaday.hide()
            }, 50)
        }

        this.handleInputChange = [
            'blackRank',
            'blackName',
            'whiteRank',
            'whiteName',
            'gameName',
            'eventName',
            'komi',
            'result',
            'handicap'
        ].reduce((acc, key) => {
            acc[key] = ({currentTarget}) => {
                this.setState({[key]: currentTarget.value === '' ? null : currentTarget.value})
            }

            return acc
        }, {})

        this.handleEngineMenuClick = [0, 1].map(index => evt => {
            let engines = setting.get('engines.list')
            let nameKeys = ['blackName', 'whiteName']
            let template = [
                {
                    label: 'Manual',
                    type: 'checkbox',
                    checked: this.state.engines[index] == null,
                    click: () => {
                        let {engines} = this.state
                        if (engines[index] == null) return

                        engines[index] = null
                        this.setState({engines})
                    }
                },
                {type: 'separator'},
                ...engines.map(engine => ({
                    label: engine.name.trim() || '(Unnamed Engine)',
                    type: 'checkbox',
                    checked: engine === this.state.engines[index],
                    click: () => {
                        let {engines} = this.state
                        engines[index] = engine
                        this.setState({engines})
                    }
                })),
                engines.length > 0 && {type: 'separator'},
                {
                    label: 'Manage Engines…',
                    click: () => {
                        sabaki.setState({preferencesTab: 'engines'})
                        sabaki.openDrawer('preferences')
                    }
                }
            ].filter(x => !!x)

            let {left, bottom} = evt.currentTarget.getBoundingClientRect()
            let menu = Menu.buildFromTemplate(template)

            menu.popup(sabaki.window, {
                async: true,
                x: Math.round(left),
                y: Math.round(bottom)
            })
        })
    }

    componentWillReceiveProps({gameInfo, engines, show}) {
        if (!this.props.show && show) {
            this.setState(gameInfo)
            this.setState({engines: [...engines]})
        }
    }

    componentDidMount() {
        this.preparePikaday()
    }

    shouldComponentUpdate({show}) {
        return show !== this.props.show || show
    }

    markDates(pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        let dates = (sgf.string2dates(this.state.date || '') || []).filter(x => x.length === 3)

        for (let el of pikaday.el.querySelectorAll('.pika-button')) {
            let year = +el.dataset.pikaYear
            let month = +el.dataset.pikaMonth
            let day = +el.dataset.pikaDay

            el.parentElement.classList.toggle('is-multi-selected', dates.some(d => {
                return helper.shallowEquals(d, [year, month + 1, day])
            }))
        }
    }

    adjustPikadayPosition(pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        let {left, top} = this.dateInputElement.getBoundingClientRect()
        let {height} = pikaday.el.getBoundingClientRect()

        pikaday.el.style.position = 'absolute'
        pikaday.el.style.left = Math.round(left) + 'px'
        pikaday.el.style.top = Math.round(top - height) + 'px'
    }

    elementInPikaday(element, pikaday = null) {
        if (pikaday == null) pikaday = this.pikaday

        while (element.parentElement) {
            if (element === pikaday.el) return true
            element = element.parentElement
        }

        return false
    }

    preparePikaday() {
        let self = this

        this.pikaday = new Pikaday({
            position: 'top left',
            firstDay: 1,
            yearRange: 6,
            onOpen() {
                let dates = (sgf.string2dates(self.state.date || '') || []).filter(x => x.length === 3)

                if (dates.length > 0) {
                    this.setDate(dates[0].join('-'), true)
                } else {
                    this.gotoToday()
                }

                self.adjustPikadayPosition(this)
            },
            onDraw() {
                if (!this.isVisible()) return

                self.adjustPikadayPosition(this)
                self.markDates(this)

                self.dateInputElement.focus()
            },
            onSelect() {
                let dates = sgf.string2dates(self.state.date || '') || []
                let date = this.getDate()
                date = [date.getFullYear(), date.getMonth() + 1, date.getDate()]

                if (!dates.some(x => helper.shallowEquals(x, date))) {
                    dates.push(date)
                } else {
                    dates = dates.filter(x => !helper.shallowEquals(x, date))
                }

                self.setState({date: sgf.dates2string(dates.sort(helper.lexicalCompare))})
            }
        })

        this.pikaday.hide()

        document.body.appendChild(this.pikaday.el)
        document.body.addEventListener('click', evt => {
            if (this.pikaday.isVisible()
            && document.activeElement !== this.dateInputElement
            && evt.target !== this.dateInputElement
            && !this.elementInPikaday(evt.target))
                this.pikaday.hide()
        })

        window.addEventListener('resize', () => this.adjustPikadayPosition())
    }

    render({
        treePosition,
        currentPlayer,
        show
    }, {
        engines = [null, null],
        blackName = null,
        blackRank = null,
        whiteName = null,
        whiteRank = null,
        gameName = null,
        eventName = null,
        date = null,
        result = null,
        komi = null,
        handicap = 0,
        size = [null, null]
    }) {
        let [tree, index] = treePosition
        let emptyTree = !tree.parent && tree.nodes.length === 1 && tree.subtrees.length === 0

        return h(Drawer,
            {
                type: 'info',
                show
            },

            h('form', {},
                h('section', {},
                    h('span', {},
                        h('img', {
                            src: './node_modules/octicons/build/svg/chevron-down.svg',
                            width: 16,
                            height: 16,
                            class: classNames({menu: true, active: engines[0] != null}),
                            onClick: this.handleEngineMenuClick[0]
                        }), ' ',

                        h('input', {
                            type: 'text',
                            name: 'rank_1',
                            placeholder: 'Rank',
                            value: blackRank,
                            onInput: this.handleInputChange.blackRank
                        }),

                        h('input', {
                            type: 'text',
                            name: 'name_1',
                            placeholder: 'Black',
                            value: blackName,
                            onInput: this.handleInputChange.blackName
                        })
                    ),

                    h('img', {
                        class: 'current-player',
                        src: `./img/ui/player_${currentPlayer}.svg`,
                        height: 31,
                        title: 'Swap',
                        onClick: this.handleSwapPlayers
                    }),

                    h('span', {},
                        h('input', {
                            type: 'text',
                            name: 'name_-1',
                            placeholder: 'White',
                            value: whiteName,
                            onInput: this.handleInputChange.whiteName
                        }),

                        h('input', {
                            type: 'text',
                            name: 'rank_-1',
                            placeholder: 'Rank',
                            value: whiteRank,
                            onInput: this.handleInputChange.whiteRank
                        }), ' ',

                        h('img', {
                            src: './node_modules/octicons/build/svg/chevron-down.svg',
                            width: 16,
                            height: 16,
                            class: classNames({menu: true, active: engines[1] != null}),
                            onClick: this.handleEngineMenuClick[1]
                        })
                    )
                ),

                h('ul', {},
                    h(InfoDrawerItem, {title: 'Name'},
                        h('input', {
                            type: 'text',
                            placeholder: '(Unnamed)',
                            value: gameName,
                            onInput: this.handleInputChange.gameName
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Event'},
                        h('input', {
                            type: 'text',
                            placeholder: 'None',
                            value: eventName,
                            onInput: this.handleInputChange.eventName
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Date'},
                        h('input', {
                            ref: el => this.dateInputElement = el,
                            type: 'text',
                            placeholder: 'None',
                            value: date,

                            onFocus: this.handleDateInputFocus,
                            onBlur: this.handleDateInputBlur,
                            onInput: this.handleDateInputChange
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Komi'},
                        h('input', {
                            type: 'number',
                            name: 'komi',
                            step: 0.5,
                            placeholder: 0,
                            value: komi == null ? '' : komi,
                            onInput: this.handleInputChange.komi
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Result'},
                        h('input', {
                            type: 'text',
                            placeholder: 'None',
                            value: result,
                            onInput: this.handleInputChange.result
                        })
                    ),
                    h(InfoDrawerItem, {title: 'Handicap'},
                        h('select',
                            {
                                selectedIndex: Math.max(0, handicap - 1),
                                disabled: !emptyTree,
                                onChange: this.handleInputChange.handicap
                            },

                            h('option', {value: 0}, 'No stones'),
                            [...Array(8)].map((_, i) =>
                                h('option', {value: i + 2}, (i + 2) + ' stones')
                            )
                        )
                    ),
                    h(InfoDrawerItem, {title: 'Board Size'},
                        h('input', {
                            type: 'number',
                            name: 'size-width',
                            placeholder: 19,
                            max: 25,
                            min: 3,
                            value: size[0],
                            disabled: !emptyTree,
                            onFocus: this.handleBoardWidthFocus,
                            onInput: this.handleBoardWidthChange
                        }), ' ',

                        h('span', {
                            title: 'Swap',
                            style: {cursor: emptyTree ? 'pointer': 'default'},
                            onClick: !emptyTree ? helper.noop : this.handleSizeSwapButtonClick
                        }, '×'), ' ',

                        h('input', {
                            type: 'number',
                            name: 'size-height',
                            placeholder: 19,
                            max: 25,
                            min: 3,
                            value: size[1],
                            disabled: !emptyTree,
                            onInput: this.handleBoardHeightChange
                        })
                    )
                ),

                h('p', {},
                    h('button', {type: 'submit', onClick: this.handleSubmitButtonClick}, 'OK'), ' ',
                    h('button', {type: 'reset', onClick: this.handleCancelButtonClick}, 'Cancel')
                )
            )
        )
    }
}

module.exports = InfoDrawer
<|endoftext|>


<commit_before>elation = require('utils/elation');
var fs = require('fs');

// We only care about the browser dependencies right now
/*
elation.env.isBrowser = true;
elation.env.isNode = false;
elation.env.isWorker = false;
*/

var depname = process.argv[2];
var requires = ['utils.events'];
if (process.argv.length > 2) {
  for (var i = 2; i < process.argv.length; i++) {
    requires.push(process.argv[i]);
  }
}
elation.require(requires);

var resolved = elation.requireactivebatchjs.resolve(elation.requireactivebatchjs.rootnode);
resolved.unshift({name: 'utils.elation'});
var resolvednames = [];
resolved.forEach(function(r) { resolvednames.push(r.name); });
console.log('===== RESOLVED ORDER =====', resolvednames);
var files = [];
var sources = [];
resolved.forEach(function(module) {
  var fname = 'htdocs/scripts/' + module.name.replace(/\./g, '/') + '.js';
  console.log(fname);
  if (fs.existsSync(fname)) {
    files.push(fname);
    //var source = fs.readFileSync(fname, 'utf8');
    var source = '';
    if (module.callback) source = wrapSource(module.name, module.callback.toString());
    else source = fs.readFileSync(fname, 'utf8');

    //source += '\nsetTimeout(function() { elation.requireactivebatchjs.finished("' + module.name + '"); }, 0)\n';
    //source = 'elation.utils.arrayset(elation, "' + module + '", true);\n' + source;
    sources.push(source);
  }
});
sources.push('setTimeout(elation.component.init, 0); elation.onloads.add("elation.component.init()"); ');

function wrapSource(name, source) {
  var pre = '// ===== BEGIN FILE: ' + name + ' ====\n(\n';
  var post = ')();\n// ===== END FILE: ' + name + ' =====\n';
  return pre + source + post;
}

if (elation.requireactivebatchcss) {
  var resolvedcss = elation.requireactivebatchcss.resolve(elation.requireactivebatchcss.rootnode);
  var resolvednames = [];
  var csssources = [];
  resolvedcss.forEach(function(module) {
    resolvednames.push(module.name);
    var fname = 'htdocs/css/' + module.name.replace(/\./g, '/') + '.css';
    console.log(fname);
    if (fs.existsSync(fname)) {
      files.push(fname);
      var source = fs.readFileSync(fname, 'utf8');

      csssources.push(source);
    }
  });
  console.log('===== RESOLVED ORDER =====', resolvednames);

  fs.writeFileSync('bundle-pack.css', csssources.join('\n'));
  //sources.push('elation.requireactivebatchcss.fulfill(' + JSON.stringify(resolvednames) + ');');
  sources.splice(1, 0, 'elation.requireactivebatchcss = new elation.require.batch("css", "/css"); elation.requireactivebatchcss.fulfill(' + JSON.stringify(resolvednames) + ');');

}
fs.writeFileSync('bundle-pack.js', sources.join('\n'));
console.log(elation.env);
<commit_msg>Append list of fulfilled js and css files to bundled JS file<commit_after>elation = require('utils/elation');
var fs = require('fs');

// We only care about the browser dependencies right now
/*
elation.env.isBrowser = true;
elation.env.isNode = false;
elation.env.isWorker = false;
*/

var depname = process.argv[2];
var requires = ['utils.events'];
if (process.argv.length > 2) {
  for (var i = 2; i < process.argv.length; i++) {
    requires.push(process.argv[i]);
  }
}
elation.require(requires);

var resolved = elation.requireactivebatchjs.resolve(elation.requireactivebatchjs.rootnode);
resolved.unshift({name: 'utils.elation'});
var resolvednamesjs = [];
resolved.forEach(function(r) { resolvednamesjs.push(r.name); });
console.log('===== RESOLVED ORDER =====', resolvednamesjs);
var files = [];
var sources = [];
resolved.forEach(function(module) {
  var fname = 'htdocs/scripts/' + module.name.replace(/\./g, '/') + '.js';
  console.log(fname);
  if (fs.existsSync(fname)) {
    files.push(fname);
    //var source = fs.readFileSync(fname, 'utf8');
    var source = '';
    if (module.callback) source = wrapSource(module.name, module.callback.toString());
    else source = fs.readFileSync(fname, 'utf8');

    //source += '\nsetTimeout(function() { elation.requireactivebatchjs.finished("' + module.name + '"); }, 0)\n';
    //source = 'elation.utils.arrayset(elation, "' + module + '", true);\n' + source;
    sources.push(source);
  }
});
sources.push('setTimeout(function() { elation.component.init(); }, 0); elation.onloads.add("elation.component.init()"); ');

function wrapSource(name, source) {
  var pre = '// ===== BEGIN FILE: ' + name + ' ====\n(\n';
  var post = ')();\n// ===== END FILE: ' + name + ' =====\n';
  return pre + source + post;
}

if (elation.requireactivebatchcss) {
  var resolvedcss = elation.requireactivebatchcss.resolve(elation.requireactivebatchcss.rootnode);
  var resolvednamescss = [];
  var csssources = [];
  resolvedcss.forEach(function(module) {
    resolvednamescss.push(module.name);
    var fname = 'htdocs/css/' + module.name.replace(/\./g, '/') + '.css';
    console.log(fname);
    if (fs.existsSync(fname)) {
      files.push(fname);
      var source = fs.readFileSync(fname, 'utf8');

      csssources.push(source);
    }
  });
  console.log('===== RESOLVED ORDER =====', resolvednamescss);

  fs.writeFileSync('bundle.css', csssources.join('\n'));
  //sources.push('elation.requireactivebatchcss.fulfill(' + JSON.stringify(resolvednamescss) + ');');
  sources.splice(1, 0, 'elation.requireactivebatchcss = new elation.require.batch("css", "/css"); elation.requireactivebatchcss.fulfill(' + JSON.stringify(resolvednamescss) + ');');
  sources.splice(1, 0, 'elation.requireactivebatchjs = new elation.require.batch("js", "/scripts"); elation.requireactivebatchjs.fulfill(' + JSON.stringify(resolvednamesjs) + ');');
}
fs.writeFileSync('bundle.js', sources.join('\n'));
console.log(elation.env);
<|endoftext|>


<commit_before>'use strict'

const path = require('path')
const fs = require('fs')
const { DefinePlugin, ProvidePlugin } = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = function(production, app) {
  var entry = {
    app: path.resolve(__dirname, `../targets/${app}/web/main`)
  }

  var plugins = [
    new DefinePlugin({
      __TARGET__: JSON.stringify('browser')
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, `../targets/${app}/web/index.ejs`),
      title: `cozy-${app}`,
      chunks: ['app'],
      inject: 'head',
      minify: {
        collapseWhitespace: true
      }
    }),
    new ProvidePlugin({
      PouchDB: 'pouchdb',
      pouchdbFind: 'pouchdb-find'
    })
  ]

  if (
    fs.existsSync(path.resolve(__dirname, `../targets/${app}/web/services.jsx`))
  ) {
    entry.services = path.resolve(__dirname, `../targets/${app}/web/services`)
    plugins.push(
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname, `../targets/${app}/web/services.ejs`),
        title: `cozy-${app}`,
        filename: 'services.html',
        chunks: ['services'],
        inject: 'head',
        minify: {
          collapseWhitespace: true
        }
      })
    )
  }

  if (
    fs.existsSync(
      path.resolve(__dirname, `../targets/${app}/web/public/main.jsx`)
    )
  ) {
    entry['public/app'] = path.resolve(
      __dirname,
      `../targets/${app}/web/public/main`
    )
    plugins.push(
      new HtmlWebpackPlugin({
        template: path.resolve(
          __dirname,
          `../targets/${app}/web/public/index.ejs`
        ),
        title: `cozy-${app}`,
        filename: 'public/index.html',
        chunks: ['public/app'],
        inject: 'head',
        minify: {
          collapseWhitespace: true
        }
      })
    )
  }

  return {
    entry: entry,
    output: {
      path: path.resolve(__dirname, `../build/${app}`),
      filename: '[name].js'
    },
    externals: {
      'cozy-client-js': 'cozy'
    },
    plugins: plugins
  }
}
<commit_msg>fix: Update page title, fix #1012<commit_after>'use strict'

const path = require('path')
const fs = require('fs')
const { DefinePlugin, ProvidePlugin } = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = function(production, app) {
  var entry = {
    app: path.resolve(__dirname, `../targets/${app}/web/main`)
  }

  var plugins = [
    new DefinePlugin({
      __TARGET__: JSON.stringify('browser')
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, `../targets/${app}/web/index.ejs`),
      title: `Cozy ${app.charAt(0).toUpperCase()}${app.slice(1)}`,
      chunks: ['app'],
      inject: 'head',
      minify: {
        collapseWhitespace: true
      }
    }),
    new ProvidePlugin({
      PouchDB: 'pouchdb',
      pouchdbFind: 'pouchdb-find'
    })
  ]

  if (
    fs.existsSync(path.resolve(__dirname, `../targets/${app}/web/services.jsx`))
  ) {
    entry.services = path.resolve(__dirname, `../targets/${app}/web/services`)
    plugins.push(
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname, `../targets/${app}/web/services.ejs`),
        title: `cozy-${app}`,
        filename: 'services.html',
        chunks: ['services'],
        inject: 'head',
        minify: {
          collapseWhitespace: true
        }
      })
    )
  }

  if (
    fs.existsSync(
      path.resolve(__dirname, `../targets/${app}/web/public/main.jsx`)
    )
  ) {
    entry['public/app'] = path.resolve(
      __dirname,
      `../targets/${app}/web/public/main`
    )
    plugins.push(
      new HtmlWebpackPlugin({
        template: path.resolve(
          __dirname,
          `../targets/${app}/web/public/index.ejs`
        ),
        title: `cozy-${app}`,
        filename: 'public/index.html',
        chunks: ['public/app'],
        inject: 'head',
        minify: {
          collapseWhitespace: true
        }
      })
    )
  }

  return {
    entry: entry,
    output: {
      path: path.resolve(__dirname, `../build/${app}`),
      filename: '[name].js'
    },
    externals: {
      'cozy-client-js': 'cozy'
    },
    plugins: plugins
  }
}
<|endoftext|>


<commit_before>'use strict';

/*
  Framed
*/
var evt = require('etudiant-mod-mediator');
var $ = require('jquery');
var mediaForm = require('etudiant-mod-mediaform');
var Block = require('../block');
var stToHTML = require('../to-html');
var Modal = require('etudiant-mod-modal');
var q  = require('q');

// create our modals
var modalStep1 = new Modal({
    slug: 'gallery-step-1',
    animation: 'fade',
    theme: 'medias'
});
var modalStep2 = new Modal({
    slug: 'gallery-step-2',
    animation: 'fade',
    theme: 'media'
});
// modal templates;
var modalTemplateFilters;
var modalTemplateStep1;
var modalTemplateStep2;

function openModalStep1(modalStep, template) {
    var tpl = template !== undefined ? template : modalTemplateStep1;
    modalStep.render({
        header: 'Image',
        head: modalTemplateFilters,
        content: tpl,
        footer: {
            next: 'Suite',
            before: 'Précédent'
        }
    });

    $.each($('.modal-row-picture img'), function() {
        $(this).attr('src', changeOriginalPictureSize($(this).attr('src'), '240x120'));
    });

    modalStep.open();

    var zoom = require('zoom.js');
    zoom.listen();
}

function openModalStep2(modal) {
    modal.render({
        header: 'Image',
        content: modalTemplateStep2,
        footer: {
            ok: 'Ok',
            dismiss: 'Annuler'
        }
    });
    var sizes = $('.framed-picture img').attr('sizes');
    $('.preview').attr('src', $('.framed-picture img').attr('src'));
    $('.picture-legend').val($('.framed-picture legend').val());
    if ($('.frame-link').attr('href') !== undefined) {
        $('.picture-link').attr('value', $('.frame-link').attr('href'));
    }
    $('.size').text(sizes);
    modal.open();
}

function startStep2(block) {
        modalStep1.close();
        evt.publish('modal-gallery-step-2', block);
}

function synchronizeAndOpenStep2(block) {
    $('.modal-gallery-step-1').on('click', '.validate', function(e){
        e.preventDefault();
        e.stopPropagation();
        var row = $(this).attr('class').split(' ')[1];
        var picture = updateData(row);
        var blockId = block.blockID;        //Update the picture
        var $picture = $('#' + blockId + ' .framed-picture img');
        var $pictureContainer = $('#' + blockId + ' .framed-picture');
        $picture.attr('src', picture.url);
        $picture.attr('sizes', picture.sizes);
        $pictureContainer.removeClass('hidden');
        $pictureContainer.css('display', 'inline-block');
        startStep2(block);
        $('.preview').attr('src', $picture.attr('src'));
        $('.size').text(picture.sizes);

    });
}

function synchronizeAndCloseStep2(block) {
    // Remove click handler on step 1
    var blockId = block.blockID;
    $('.modal-gallery-step-1').off('click', '.validate');

    $('.picture-link').on('keyup', function() {
        var internal = validateInternalUrl($('.picture-link').val());
        if (!internal) {
            $('.external-link').text('Lien externe');
        }
        else {
            $('.external-link').text('');
        }
    });

    $('#modal-gallery-step-2 .ok').on('click', function() {
        if ($('.picture-legend').val().length !== 0) {
            $('#' + blockId + ' .frame legend').text($('.picture-legend').val());
        }
        else {
            $('#' + blockId + ' .frame legend').text('&copy L\'Etudiant.');
        }
        if ($('.picture-link').val().length !== 0) {
            if($('#' + blockId + ' .framed-picture').parents().first().hasClass('frame-link')){
                $('#' + blockId + ' .framed-picture').unwrap();
            }
            $('#' + blockId + ' .framed-picture').wrap('');
        }
        var position = $('.position').find(':selected').val();
        updatePicturePosition(position);
    });
}

function updateData(row) {
    var picture = {};
    picture.url = $('.modal-row-picture.' + row).data('image');
    picture.sizes = $('.modal-row-content.' + row + ' .sizes').find(':selected').val();
    picture.width = picture.sizes.split('x')[0];
    picture.height = picture.sizes.split('x')[1];
    picture.name = picture.url;
    picture.url = changeOriginalPictureSize(picture.url, picture.sizes);
    return picture;
}

function updateZoom() {
    // 1 bind listener sur le change du select
    // 2 Quand la taille change j'update data-image de modal-row-picture-{id}
    $('#modal-gallery-step-1').on('change', '.modal-row .sizes', function(){
        var zoomedSize = $(this).find(':selected').val();
        var rowId = $(this).parent().parent().attr('class').split(' ')[1];
        var originalSize = $('.modal-row-picture.' + rowId).data('image');
        $('.modal-row-picture.' + rowId).data('zoom', changeOriginalPictureSize(originalSize, zoomedSize));
        //console.log($('.modal-row-picture.' + rowId).data('zoom'));
    });
}

function getTemplate(params) {
    var template = '';
    template += '
';
        template += '

<legend>&copy L etudiant </legend>
';
            template += '
';
        template += '
';
    template += '
';
    return template;
}

function togglePicture(ev, block) {
    ev.preventDefault();
    var framePicture = block.find('.framed-picture');
    framePicture.toggleClass('hidden');
    if (framePicture.hasClass('hidden')) {
        framePicture.css('display', 'none');
    }
    else {
        framePicture.css('display', 'inline-block');
    }
}

function changeOriginalPictureSize(src, size) {
    if (src.indexOf('original') > 0){
        src = src.replace('original', size);
        return src;
    }
}

function updatePicturePosition(side) {
    var framedPicture = $('.framed-picture');

    if (framedPicture.hasClass('hidden')) {
        return false;
    }
    else if (framedPicture.is('.f-left, .f-right')) {
        framedPicture.removeClass('f-left f-right');
    }
    framedPicture.addClass(side);
}

// Url validation
function validateInternalUrl(url) {
    var hostname = new RegExp(location.host);
    var internal;
    if (hostname.test(url)){
       internal = true;
    }
    else if (url.slice(0, 1) === '#'){
        internal = true;
    }
    else if (url.slice(0, 1) === '/'){
        internal = true;
    }
    else {
        internal = false;
    }
    return internal;
}

function ajaxWatcher() {
    $('#modal-gallery-step-1').on('change', '.modal-search .sizes', function(){
        var size = $(this).find(':selected').val();
        var modalTemplateSized = mediaForm.getTemplateMediasBySize(size);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
            var newSelector = $('#modal-gallery-step-1').find('.modal-search .sizes');
            newSelector.val(size).prop('selected', true);
        });
    });

    $('#modal-gallery-step-1').on('change', '.modal-search .categories', function(){
        var size = $(this).find(':selected').val();
        var modalTemplateSized = mediaForm.getTemplateMediasByCategory(size);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
            var newSelector = $('#modal-gallery-step-1').find('.modal-search .categories');
            newSelector.val(size).prop('selected', true);
        });
    });

    $('#modal-gallery-step-1').on('keyup', '.modal-search .search', function(){
        var text = $(this).val();
        var modalTemplateSized = mediaForm.getTemplateMediasByKeyword(text);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
        });
    });
}

module.exports = Block.extend({
    type: 'framed',
    title: function() { return i18n.t('blocks:framed:title'); },
    icon_name: 'quote',
    controllable: true,
    controls_position: 'bottom',
    controls_visible: true,
    controls: [
        {
            slug: 'show-picture',
            'icon': 'image',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this;
                evt.publish('modal-gallery-step-1', block); //Call the modal event
            }

        },
        {
            slug: 'update-picture',
            'icon': 'image1',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this.$framed;
                evt.publish('modal-gallery-step-2', block);
            }

        },
        {
            slug: 'add-picture',
            'icon': 'image+',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this.$framed;
                togglePicture(e, block);
            }
        }

    ],
    onBlockRender: function() {
        var template = getTemplate({
            frameColor: '#536A4C',
            frameBorder: '#6C8365',
            frameDisplay: 'block',
            frameTextDisplay: 'block',
            frameTextWidth: '100%',
            framePictureWidth: 'auto',
            framePictureHeight: 'auto',
            framedPictureDisplay: 'hidden'
        });

        this.$inner.prepend(template);
        this.$framed = this.$inner.find('.frame');

        //Handlebar formated template
        modalTemplateFilters = mediaForm.getTemplateFilters();
        modalTemplateStep1 = mediaForm.getTemplateMedias();
        // Ajax job before rendering modal
        q.all([ modalTemplateFilters, modalTemplateStep1 ]).then(function(data){

            modalTemplateFilters = data[0];
            modalTemplateStep1 = data[1];

            //Subcribe modals to mediator
            evt.subscribe('modal-gallery-step-1', function(param, channel) {
                channel.stopPropagation();

                openModalStep1(modalStep1);
                updateZoom();
                ajaxWatcher();
                synchronizeAndOpenStep2(param);
            });

            evt.subscribe('modal-gallery-step-2', function(param) {
                openModalStep2(modalStep2);
                synchronizeAndCloseStep2(param);
            });
        });

        modalTemplateStep2 = mediaForm.getTemplateMedia();
        return template;
    },
    loadData: function(data){
        this.getTextBlock().html(stToHTML(data.text, this.type));
        this.$('.st-picture-right').val(data.picture);
    },

    toMarkdown: function(markdown) {
        return markdown.replace(/^(.+)$/mg, '> $1');
    }

});
<commit_msg>Block framed without zoom<commit_after>'use strict';

/*
  Framed
*/
var evt = require('etudiant-mod-mediator');
var $ = require('jquery');
var mediaForm = require('etudiant-mod-mediaform');
var Block = require('../block');
var stToHTML = require('../to-html');
var Modal = require('etudiant-mod-modal');
var q  = require('q');
var zoom = require('etudiant-mod-zoom');

// create our modals
var modalStep1 = new Modal({
    slug: 'gallery-step-1',
    animation: 'fade',
    theme: 'medias'
});
var modalStep2 = new Modal({
    slug: 'gallery-step-2',
    animation: 'fade',
    theme: 'media'
});
// modal templates;
var modalTemplateFilters;
var modalTemplateStep1;
var modalTemplateStep2;

function openModalStep1(modalStep, template) {
    var tpl = template !== undefined ? template : modalTemplateStep1;
    modalStep.render({
        header: 'Image',
        head: modalTemplateFilters,
        content: tpl,
        footer: {
            next: 'Suite',
            before: 'Précédent'
        }
    });

    $.each($('.modal-row-picture img'), function() {
        $(this).attr('src', changeOriginalPictureSize($(this).attr('src'), '240x120'));
    });

    zoom.init({
        scope: '#modal-gallery-step-1',
    });

    modalStep.open();

}

function openModalStep2(modal) {
    modal.render({
        header: 'Image',
        content: modalTemplateStep2,
        footer: {
            ok: 'Ok',
            dismiss: 'Annuler'
        }
    });
    var sizes = $('.framed-picture img').attr('sizes');
    $('.preview').attr('src', $('.framed-picture img').attr('src'));
    $('.picture-legend').val($('.framed-picture legend').val());
    if ($('.frame-link').attr('href') !== undefined) {
        $('.picture-link').attr('value', $('.frame-link').attr('href'));
    }
    $('.size').text(sizes);
    modal.open();
}

function startStep2(block) {
        modalStep1.close();
        evt.publish('modal-gallery-step-2', block);
}

function synchronizeAndOpenStep2(block) {
    $('.modal-gallery-step-1').on('click', '.validate', function(e){
        e.preventDefault();
        e.stopPropagation();
        var row = $(this).attr('class').split(' ')[1];
        var picture = updateData(row);
        var blockId = block.blockID;        //Update the picture
        var $picture = $('#' + blockId + ' .framed-picture img');
        var $pictureContainer = $('#' + blockId + ' .framed-picture');
        $picture.attr('src', picture.url);
        $picture.attr('sizes', picture.sizes);
        $pictureContainer.removeClass('hidden');
        $pictureContainer.css('display', 'inline-block');
        startStep2(block);
        $('.preview').attr('src', $picture.attr('src'));
        $('.size').text(picture.sizes);

    });
}

function synchronizeAndCloseStep2(block) {
    // Remove click handler on step 1
    var blockId = block.blockID;
    $('.modal-gallery-step-1').off('click', '.validate');

    $('.picture-link').on('keyup', function() {
        var internal = validateInternalUrl($('.picture-link').val());
        if (!internal) {
            $('.external-link').text('Lien externe');
        }
        else {
            $('.external-link').text('');
        }
    });

    $('#modal-gallery-step-2 .ok').on('click', function() {
        if ($('.picture-legend').val().length !== 0) {
            $('#' + blockId + ' .frame legend').text($('.picture-legend').val());
        }
        else {
            $('#' + blockId + ' .frame legend').text('&copy L\'Etudiant.');
        }
        if ($('.picture-link').val().length !== 0) {
            if($('#' + blockId + ' .framed-picture').parents().first().hasClass('frame-link')){
                $('#' + blockId + ' .framed-picture').unwrap();
            }
            $('#' + blockId + ' .framed-picture').wrap('');
        }
        var position = $('.position').find(':selected').val();
        updatePicturePosition(position);
    });
}

function updateData(row) {
    var picture = {};
    picture.url = $('.modal-row-picture.' + row).data('image');
    picture.sizes = $('.modal-row-content.' + row + ' .sizes').find(':selected').val();
    picture.width = picture.sizes.split('x')[0];
    picture.height = picture.sizes.split('x')[1];
    picture.name = picture.url;
    picture.url = changeOriginalPictureSize(picture.url, picture.sizes);
    return picture;
}

function updateZoom() {
    // 1 bind listener sur le change du select
    // 2 Quand la taille change j'update data-image de modal-row-picture-{id}
    $('#modal-gallery-step-1').on('change', '.modal-row .sizes', function(){
        var zoomedSize = $(this).find(':selected').val();
        var rowId = $(this).parent().parent().attr('class').split(' ')[1];
        var originalSize = $('.modal-row-picture.' + rowId).data('image');
        $('.modal-row-picture.' + rowId).data('zoom', changeOriginalPictureSize(originalSize, zoomedSize));
        //console.log($('.modal-row-picture.' + rowId).data('zoom'));
    });
}

function getTemplate(params) {
    var template = '';
    template += '
';
        template += '

<legend>&copy L etudiant </legend>
';
            template += '
';
        template += '
';
    template += '
';
    return template;
}

function togglePicture(ev, block) {
    ev.preventDefault();
    var framePicture = block.find('.framed-picture');
    framePicture.toggleClass('hidden');
    if (framePicture.hasClass('hidden')) {
        framePicture.css('display', 'none');
    }
    else {
        framePicture.css('display', 'inline-block');
    }
}

function changeOriginalPictureSize(src, size) {
    if (src.indexOf('original') > 0){
        src = src.replace('original', size);
        return src;
    }
}

function updatePicturePosition(side) {
    var framedPicture = $('.framed-picture');

    if (framedPicture.hasClass('hidden')) {
        return false;
    }
    else if (framedPicture.is('.f-left, .f-right')) {
        framedPicture.removeClass('f-left f-right');
    }
    framedPicture.addClass(side);
}

// Url validation
function validateInternalUrl(url) {
    var hostname = new RegExp(location.host);
    var internal;
    if (hostname.test(url)){
       internal = true;
    }
    else if (url.slice(0, 1) === '#'){
        internal = true;
    }
    else if (url.slice(0, 1) === '/'){
        internal = true;
    }
    else {
        internal = false;
    }
    return internal;
}

function ajaxWatcher() {
    $('#modal-gallery-step-1').on('change', '.modal-search .sizes', function(){
        var size = $(this).find(':selected').val();
        var modalTemplateSized = mediaForm.getTemplateMediasBySize(size);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
            var newSelector = $('#modal-gallery-step-1').find('.modal-search .sizes');
            newSelector.val(size).prop('selected', true);
        });
    });

    $('#modal-gallery-step-1').on('change', '.modal-search .categories', function(){
        var size = $(this).find(':selected').val();
        var modalTemplateSized = mediaForm.getTemplateMediasByCategory(size);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
            var newSelector = $('#modal-gallery-step-1').find('.modal-search .categories');
            newSelector.val(size).prop('selected', true);
        });
    });

    $('#modal-gallery-step-1').on('keyup', '.modal-search .search', function(){
        var text = $(this).val();
        var modalTemplateSized = mediaForm.getTemplateMediasByKeyword(text);
        modalTemplateSized.then(function(data){
            openModalStep1(modalStep1, data);
        });
    });
}

module.exports = Block.extend({
    type: 'framed',
    title: function() { return i18n.t('blocks:framed:title'); },
    icon_name: 'quote',
    controllable: true,
    controls_position: 'bottom',
    controls_visible: true,
    controls: [
        {
            slug: 'show-picture',
            'icon': 'image',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this;
                evt.publish('modal-gallery-step-1', block); //Call the modal event
            }

        },
        {
            slug: 'update-picture',
            'icon': 'image1',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this.$framed;
                evt.publish('modal-gallery-step-2', block);
            }

        },
        {
            slug: 'add-picture',
            'icon': 'image+',
            eventTrigger: 'click',
            fn: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var block = this.$framed;
                togglePicture(e, block);
            }
        }

    ],
    onBlockRender: function() {
        var template = getTemplate({
            frameColor: '#536A4C',
            frameBorder: '#6C8365',
            frameDisplay: 'block',
            frameTextDisplay: 'block',
            frameTextWidth: '100%',
            framePictureWidth: 'auto',
            framePictureHeight: 'auto',
            framedPictureDisplay: 'hidden'
        });

        this.$inner.prepend(template);
        this.$framed = this.$inner.find('.frame');

        //Handlebar formated template
        modalTemplateFilters = mediaForm.getTemplateFilters();
        modalTemplateStep1 = mediaForm.getTemplateMedias();
        // Ajax job before rendering modal
        q.all([ modalTemplateFilters, modalTemplateStep1 ]).then(function(data){

            modalTemplateFilters = data[0];
            modalTemplateStep1 = data[1];

            //Subcribe modals to mediator
            evt.subscribe('modal-gallery-step-1', function(param, channel) {
                channel.stopPropagation();

                openModalStep1(modalStep1);

                ajaxWatcher();
                synchronizeAndOpenStep2(param);
            });

            evt.subscribe('modal-gallery-step-2', function(param) {
                openModalStep2(modalStep2);
                synchronizeAndCloseStep2(param);
            });
        });

        modalTemplateStep2 = mediaForm.getTemplateMedia();
        return template;
    },
    loadData: function(data){
        this.getTextBlock().html(stToHTML(data.text, this.type));
        this.$('.st-picture-right').val(data.picture);
    },

    toMarkdown: function(markdown) {
        return markdown.replace(/^(.+)$/mg, '> $1');
    }

});
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

//@ts-check
'use strict';

const loader = require('./vs/loader');
const bootstrap = require('./bootstrap');
const performance = require('./vs/base/common/performance');

// Bootstrap: NLS
const nlsConfig = bootstrap.setupNLS();

// Bootstrap: Loader
loader.config({
	baseUrl: bootstrap.fileUriFromPath(__dirname, { isWindows: process.platform === 'win32' }),
	catchError: true,
	nodeRequire: require,
	nodeMain: __filename,
	'vs/nls': nlsConfig,
	amdModulesPattern: /^vs\//,
	recordStats: true
});

// Running in Electron
if (process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron']) {
	loader.define('fs', ['original-fs'], function (originalFS) {
		return originalFS;  // replace the patched electron fs with the original node fs for all AMD code
	});
}

// Pseudo NLS support
if (nlsConfig && nlsConfig.pseudo) {
	loader(['vs/nls'], function (nlsPlugin) {
		nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
	});
}

exports.load = function (entrypoint, onLoad, onError) {
	if (!entrypoint) {
		return;
	}

	// cached data config
	if (process.env['VSCODE_NODE_CACHED_DATA_DIR']) {
		loader.config({
			nodeCachedData: {
				path: process.env['VSCODE_NODE_CACHED_DATA_DIR'],
				seed: entrypoint
			}
		});
	}

	onLoad = onLoad || function () { };
	onError = onError || function (err) { console.error(err); };

	performance.mark(`fork/willLoadCode`);
	loader([entrypoint], onLoad, onError);
};
<commit_msg>better fix for https://github.com/microsoft/vscode/issues/113852<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

//@ts-check
'use strict';

const loader = require('./vs/loader');
const bootstrap = require('./bootstrap');
const performance = require('./vs/base/common/performance');

// Bootstrap: NLS
const nlsConfig = bootstrap.setupNLS();

// Bootstrap: Loader
loader.config({
	baseUrl: bootstrap.fileUriFromPath(__dirname, { isWindows: process.platform === 'win32' }),
	catchError: true,
	nodeRequire: require,
	nodeMain: __filename,
	'vs/nls': nlsConfig,
	amdModulesPattern: /^vs\//,
	recordStats: true
});

// Running in Electron
if (process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron']) {
	loader.define('fs', ['original-fs'], function (originalFS) {
		return originalFS;  // replace the patched electron fs with the original node fs for all AMD code
	});
}

// Pseudo NLS support
if (nlsConfig && nlsConfig.pseudo) {
	loader(['vs/nls'], function (nlsPlugin) {
		nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
	});
}

exports.load = function (entrypoint, onLoad, onError) {
	if (!entrypoint) {
		return;
	}

	// cached data config
	if (process.env['VSCODE_NODE_CACHED_DATA_DIR']) {
		loader.config({
			nodeCachedData: {
				path: process.env['VSCODE_NODE_CACHED_DATA_DIR'],
				seed: entrypoint + process.arch
			}
		});
	}

	onLoad = onLoad || function () { };
	onError = onError || function (err) { console.error(err); };

	performance.mark(`fork/willLoadCode`);
	loader([entrypoint], onLoad, onError);
};
<|endoftext|>


<commit_before>'use strict';

/**
 * 어떤 일을 하고 있습니까?
 * @class Pin
 *
 */
var Pin = function()
{
	if (!(this instanceof Pin))
	{
		throw new Error(Messages.CONSTRUCT_ERROR);
	}
	this.texture; // default.***
	this.texturesArray = [];
	this.positionBuffer;
	this.texcoordBuffer;

};

Pin.prototype.createPin = function(gl)
{
	this.positionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);

	// Put a unit quad in the buffer
	var positionsPinQuad = [
		0, 0, 0,
		1, 0, 0,
		0, 1, 0,
		0, 1, 0,
		1, 0, 0,
		1, 1, 0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionsPinQuad), gl.STATIC_DRAW);

	this.texcoordBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
	var texcoordsPinQuad = [
		0, 0,
		1, 0,
		0, 1,
		0, 1,
		1, 0,
		1, 1
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoordsPinQuad), gl.STATIC_DRAW);

};

Pin.prototype.createPinCenterBottom = function(gl)
{
	this.positionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);

	// Put a unit quad in the buffer
	var positionsPinQuad = [
		-0.5, 0, 0,
		0.5, 0, 0,
		-0.5, 1, 0,
		-0.5, 1, 0,
		0.5, 0, 0,
		0.5, 1, 0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionsPinQuad), gl.STATIC_DRAW);

	this.texcoordBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
	var texcoordsPinQuad = [
		0, 0,
		1, 0,
		0, 1,
		0, 1,
		1, 0,
		1, 1
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoordsPinQuad), gl.STATIC_DRAW);

};<commit_msg>make comments on Pin.js<commit_after>'use strict';

/**
 * This is the pin which is created to be placed on the map
 * @class Pin
 *
 */
var Pin = function()
{
	if (!(this instanceof Pin))
	{
		throw new Error(Messages.CONSTRUCT_ERROR);
	}
	this.texture; // default.***
	this.texturesArray = [];
	this.positionBuffer;
	this.texcoordBuffer;

};

Pin.prototype.createPin = function(gl)
{
	this.positionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);

	// Put a unit quad in the buffer
	var positionsPinQuad = [
		0, 0, 0,
		1, 0, 0,
		0, 1, 0,
		0, 1, 0,
		1, 0, 0,
		1, 1, 0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionsPinQuad), gl.STATIC_DRAW);

	this.texcoordBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
	var texcoordsPinQuad = [
		0, 0,
		1, 0,
		0, 1,
		0, 1,
		1, 0,
		1, 1
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoordsPinQuad), gl.STATIC_DRAW);

};

/**
 * draw the bottom pick of the pin
 */
Pin.prototype.createPinCenterBottom = function(gl)
{
	this.positionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);

	// Put a unit quad in the buffer
	var positionsPinQuad = [
		-0.5, 0, 0,
		0.5, 0, 0,
		-0.5, 1, 0,
		-0.5, 1, 0,
		0.5, 0, 0,
		0.5, 1, 0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionsPinQuad), gl.STATIC_DRAW);

	this.texcoordBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
	var texcoordsPinQuad = [
		0, 0,
		1, 0,
		0, 1,
		0, 1,
		1, 0,
		1, 1
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoordsPinQuad), gl.STATIC_DRAW);

};<|endoftext|>


<commit_before>;
(function(root, factory) {
  if(typeof define === "function" && define.amd) {
    define(["./DateTime", "./DateFormat"], factory)
  } else {
    root.DateLocale = factory(root.DateTime, root.DateFormat)
  }
})(this, function(DateTime, DateFormat) {
  var DateLocale = {}

  DateLocale.FI = {
    id             : 'FI',
    monthNames     : ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],
    dayNames       : ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],
    shortDayNames  : ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'vuosi' : 'vuotta') },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'kuukausi' : 'kuukautta') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'päivä' : 'päivää') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'tunti' : 'tuntia')
    },
    shortDateFormat: 'j.n.Y',
    weekDateFormat : 'D j.n.Y',
    dateTimeFormat : 'D j.n.Y k\\lo G:i',
    firstWeekday   : DateTime.MONDAY
  }

  DateLocale.EN = {
    id             : 'EN',
    monthNames     : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    dayNames       : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    shortDayNames  : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Year' : 'Years'); },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Months' : 'Months') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Day' : 'Days') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes)
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Hour' : 'Hours')
    },
    shortDateFormat: 'n/j/Y',
    weekDateFormat : 'D n/j/Y',
    dateTimeFormat : 'D n/j/Y G:i',
    firstWeekday   : DateTime.SUNDAY
  }

  DateLocale.AU = {
    id             : 'AU',
    monthNames     : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    dayNames       : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    shortDayNames  : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Year' : 'Years'); },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Months' : 'Months') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Day' : 'Days') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes)
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Hour' : 'Hours')
    },
    shortDateFormat: 'j/n/Y',
    weekDateFormat : 'D j/n/Y',
    dateTimeFormat : 'D j/n/Y G:i',
    firstWeekday   : DateTime.SUNDAY
  }

  DateLocale.ET = {
    id             : 'ET',
    monthNames     : [ 'Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember'],
    dayNames       : ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
    shortDayNames  : ['Pü', 'Es', 'Te', 'Ko', 'Ne', 'Re', 'La'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Aasta' : 'Aastat') },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Kuu' : 'Kuud') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Päev' : 'Päeva') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Tund' : 'Tundi')
    },
    shortDateFormat: 'j.n.Y',
    weekDateFormat : 'D j.n.Y',
    dateTimeFormat : 'D j.n.Y k\\lo G:i',
    firstWeekday   : DateTime.MONDAY
  }

  DateLocale.RU = {
    id             : 'RU',
    monthNames     : [ 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
    dayNames       : ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
    shortDayNames  : ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Год' : 'Года') },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Месяц' : 'Месяца') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'День' : 'Дня') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Минута' : 'Минуты')
    },
    shortDateFormat: 'j.n.Y',
    weekDateFormat : 'D j.n.Y',
    dateTimeFormat : 'D j.n.Y k\\lo G:i',
    firstWeekday   : DateTime.MONDAY
  }

  DateLocale.SV = {
    id             : 'SV',
    monthNames     : ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
    dayNames       : ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'],
    shortDayNames  : ['Sö', 'Må', 'Ti', 'On', 'To', 'Fr', 'Lö'],
    yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'År' : 'År') },
    monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Månad' : 'Månader') },
    daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Dag' : 'Dagar') },
    hoursLabel     : function(hours, minutes) {
      var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
      return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Minut' : 'Minuter')
    },
    shortDateFormat: 'j.n.Y',
    weekDateFormat : 'D j.n.Y',
    dateTimeFormat : 'D j.n.Y k\\lo G:i',
    firstWeekday   : DateTime.MONDAY
  }

  DateLocale.fromArgument = function(stringOrObject) {
    if(typeof stringOrObject == 'string')
      return DateLocale[stringOrObject.toUpperCase()]
    else return stringOrObject
  }

  return DateLocale
})
<commit_msg>Move date locales into object<commit_after>;
(function(root, factory) {
  if(typeof define === "function" && define.amd) {
    define(["./DateTime", "./DateFormat"], factory)
  } else {
    root.DateLocale = factory(root.DateTime, root.DateFormat)
  }
})(this, function(DateTime, DateFormat) {
  var DateLocale = {
    FI: {
      id             : 'FI',
      monthNames     : ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],
      dayNames       : ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],
      shortDayNames  : ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'vuosi' : 'vuotta') },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'kuukausi' : 'kuukautta') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'päivä' : 'päivää') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'tunti' : 'tuntia')
      },
      shortDateFormat: 'j.n.Y',
      weekDateFormat : 'D j.n.Y',
      dateTimeFormat : 'D j.n.Y k\\lo G:i',
      firstWeekday   : DateTime.MONDAY
    },
    EN: {
      id             : 'EN',
      monthNames     : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      dayNames       : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
      shortDayNames  : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Year' : 'Years'); },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Months' : 'Months') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Day' : 'Days') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes)
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Hour' : 'Hours')
      },
      shortDateFormat: 'n/j/Y',
      weekDateFormat : 'D n/j/Y',
      dateTimeFormat : 'D n/j/Y G:i',
      firstWeekday   : DateTime.SUNDAY
    },
    AU: {
      id             : 'AU',
      monthNames     : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      dayNames       : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
      shortDayNames  : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Year' : 'Years'); },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Months' : 'Months') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Day' : 'Days') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes)
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Hour' : 'Hours')
      },
      shortDateFormat: 'j/n/Y',
      weekDateFormat : 'D j/n/Y',
      dateTimeFormat : 'D j/n/Y G:i',
      firstWeekday   : DateTime.SUNDAY
    },
    ET: {
      id             : 'ET',
      monthNames     : [ 'Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember'],
      dayNames       : ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
      shortDayNames  : ['Pü', 'Es', 'Te', 'Ko', 'Ne', 'Re', 'La'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Aasta' : 'Aastat') },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Kuu' : 'Kuud') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Päev' : 'Päeva') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Tund' : 'Tundi')
      },
      shortDateFormat: 'j.n.Y',
      weekDateFormat : 'D j.n.Y',
      dateTimeFormat : 'D j.n.Y k\\lo G:i',
      firstWeekday   : DateTime.MONDAY
    },
    RU: {
      id             : 'RU',
      monthNames     : [ 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
      dayNames       : ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
      shortDayNames  : ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'Год' : 'Года') },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Месяц' : 'Месяца') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'День' : 'Дня') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Минута' : 'Минуты')
      },
      shortDateFormat: 'j.n.Y',
      weekDateFormat : 'D j.n.Y',
      dateTimeFormat : 'D j.n.Y k\\lo G:i',
      firstWeekday   : DateTime.MONDAY
    },
    SV: {
      id             : 'SV',
      monthNames     : ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
      dayNames       : ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'],
      shortDayNames  : ['Sö', 'Må', 'Ti', 'On', 'To', 'Fr', 'Lö'],
      yearsLabel     : function(years) { return years + ' ' + (years == '1' ? 'År' : 'År') },
      monthsLabel    : function(months) { return months + ' ' + (months == '1' ? 'Månad' : 'Månader') },
      daysLabel      : function(days) { return days + ' ' + (days == '1' ? 'Dag' : 'Dagar') },
      hoursLabel     : function(hours, minutes) {
        var hoursAndMinutes = DateFormat.hoursAndMinutes(hours, minutes).replace('.', ',')
        return hoursAndMinutes + ' ' + (hoursAndMinutes == '1' ? 'Minut' : 'Minuter')
      },
      shortDateFormat: 'j.n.Y',
      weekDateFormat : 'D j.n.Y',
      dateTimeFormat : 'D j.n.Y k\\lo G:i',
      firstWeekday   : DateTime.MONDAY
    }
  }

  DateLocale.fromArgument = function(stringOrObject) {
    if(typeof stringOrObject == 'string')
      return DateLocale[stringOrObject.toUpperCase()]
    else return stringOrObject
  }

  return DateLocale
})
<|endoftext|>


<commit_before>export default function Caching(config) {
    const storage = {
        dummyItem: {
            timestamp: 1212
        }
    };
    const collectionQueries = {
        dummyItem: {
            timestamp: 1212
        }
    };
    const temporaryIds = {

    };

    return {
        preRead,
        postRead,
        preWrite,
        postWrite,
        postDelete,
        preDelete
    };

    function preRead(next, apiName, methodName, methodMeta, args) {
        const typeConfig = getTypeConfig(apiName, methodMeta.entity);
        const key = createKey(apiName, methodName, methodMeta.multipleEntities, args, methodMeta.entity);

        let fromCache;
        if (typeConfig && (fromCache = getFromCache(typeConfig, key))) {
            return new Promise(
                resolve => resolve(fromCache)
            );
        } else {
            return next(args);
        }
    }

    function postRead(apiName, methodName, methodMeta, args, promise) {
        const type = methodMeta.entity;

        promise.then((result) => {
            saveToCache(createKey(apiName, methodName, methodMeta.multipleEntities, args, type),
                        { data: result.data });
        });
    }

    function preWrite(next, apiName, methodName, methodMeta, jobId, args) {
        const methodType = methodMeta.entity;
        const key = createKey(apiName,
                              methodName,
                              methodMeta.multipleEntities,
                              args,
                              methodType,
                              jobId);
        saveToCache(key, {
            data: args[0]
        }, 'WRITE');
        return next(args);
    }

    function postWrite(apiName, methodName, methodMeta, jobId, args, promise) {
        if (temporaryIds[jobId] !== undefined) {
            temporaryIds[jobId].promise = promise;
        }

        const config = getTypeConfig(apiName, methodMeta.entity);

        promise.then(replaceTemporaryWithFinalId(methodMeta, jobId))
               .then(invalidateCacheIfDesired(config, methodMeta.entity, args));

        return promise;
    }

    function preDelete(next, apiName, methodName, methodMeta, jobId, args) {
        if (methodMeta.multipleEntities) {
            args[0].map(deleteFromCache(methodMeta.entity));
        } else {
            deleteFromCache(methodMeta.entity)(args[0]);
        }

        return next(args);
    }

    function deleteFromCache(type) {
        return entity => {
            delete storage[type][entity.id];
        };
    }

    function postDelete(promise) {
        return promise;
    }

    function invalidateCacheIfDesired(config, entityType, args) {
        if (newEntityWasCreated(args[0]) && config.invalidateOnCreate) {
            collectionQueries[entityType] = {};
        }
    }

    function newEntityWasCreated(entity) {
        return entity.id === undefined;
    }

    function replaceTemporaryWithFinalId(methodMeta, jobId) {
        return realEntity => {
            const tempId = temporaryIds[jobId].id;
            const entityWithTempId = storage[methodMeta.entity][tempId];
            delete storage[methodMeta.entity][tempId];
            storage[methodMeta.entity][realEntity.data.id] = entityWithTempId;
        }
    }

    function createKey(apiName, methodName, multipleEntities, args, type, jobId) {
        if (multipleEntities) {
            return {
                type: 'COLLECTION_KEY',
                value: [apiName, methodName, multipleEntities, args].join('-'),
                entityType: type
            };
        } else {
            return {
                type: 'ENTITY_KEY',
                entityType: type,
                id: args[0].id || createTemporaryId(jobId)
            };
        }
    }

    function createTemporaryId(jobId) {
        const id = generateEntityIdFromJobId(jobId);
        temporaryIds[jobId] = {
            id
        };
        return id;
    }

    function generateEntityIdFromJobId(jobId) {
        return 'TEMPORARY_ID_' + jobId;
    }

    function getTypeConfig(apiName, typeName) {
        if (config[typeName]) {
            return config[typeName];
        } else {
            return {};
        }
    }

    function getFromCache(methodConfig, key) {
        let value;

        if (key.type === 'COLLECTION_KEY') {
            value = getCollectionFromCache(key);
        } else {
            value = getEntityFromCache(key);
        }

        if (value && isValid(value, methodConfig, key)) {
            return value;
        } else {
            return false;
        }
    }

    function getCollectionFromCache(key) {
        if (collectionQueries[key.entityType] &&
            collectionQueries[key.entityType][key.value]) {
            return {
                data: collectionQueries[key.entityType][key.value].ids
                    .map((x) => getEntityDataIfExist(storage[key.entityType][x]))
                    .filter((x) => x !== null)
            };
        } else {
            return false;
        }
    }

    function getEntityDataIfExist(entity) {
        if (entity) {
            return entity.data;
        } else {
            return null;
        }
    }

    function getEntityFromCache(key) {
        if (storage[key.entityType][key.id]) {
            return storage[key.entityType][key.id];
        } else {
            return false;
        }
    }

    function isValid(item, methodConfig, key) {
        if (key.type === 'COLLECTION_KEY') {
            return collectionQueries[key.entityType][key.value].timestamp + methodConfig.ttl * 1000 >= Date.now();
        } else {
            return item.timestamp + methodConfig.ttl * 1000 >= Date.now();
        }
    }

    function saveToCache(key, val, operation) {
        const type = key.entityType;
        if (!storage[type]) {
            storage[type] = {};
        }

        if (key.type === 'COLLECTION_KEY') {
            saveCollection(key, type, val.data, operation);
        } else {
            saveEntity(key, type, val.data);
        }
    }

    function saveCollection(key, type, val, operation) {
        val.forEach((x) => {
            storage[type][x.id] = {
                data: x,
                timestamp: Date.now()
            };
        });

        if (operation !== 'WRITE') {
            const ids = val.map((x) => x.id);

            if (!collectionQueries[key.entityType]) {
                collectionQueries[key.entityType] = {};
            }

            collectionQueries[key.entityType][key.value] = {
                timestamp: Date.now(),
                ids
            };
        }
    }

    function saveEntity(key, type, val) {
        storage[type][key.id] = {
            data: val,
            timestamp: Date.now()
        };
    }
}
<commit_msg>invalidate cache both on pre and post write<commit_after>export default function Caching(config) {
    const storage = {
        dummyItem: {
            timestamp: 1212
        }
    };
    const collectionQueries = {
        dummyItem: {
            timestamp: 1212
        }
    };
    const temporaryIds = {

    };

    return {
        preRead,
        postRead,
        preWrite,
        postWrite,
        postDelete,
        preDelete
    };

    function preRead(next, apiName, methodName, methodMeta, args) {
        const typeConfig = getTypeConfig(apiName, methodMeta.entity);
        const key = createKey(apiName, methodName, methodMeta.multipleEntities, args, methodMeta.entity);

        let fromCache;
        if (typeConfig && (fromCache = getFromCache(typeConfig, key))) {
            return new Promise(
                resolve => resolve(fromCache)
            );
        } else {
            return next(args);
        }
    }

    function postRead(apiName, methodName, methodMeta, args, promise) {
        const type = methodMeta.entity;

        promise.then((result) => {
            saveToCache(createKey(apiName, methodName, methodMeta.multipleEntities, args, type),
                        { data: result.data });
        });
    }

    function preWrite(next, apiName, methodName, methodMeta, jobId, args) {
        const methodType = methodMeta.entity;
        const key = createKey(apiName,
                              methodName,
                              methodMeta.multipleEntities,
                              args,
                              methodType,
                              jobId);
        saveToCache(key, {
            data: args[0]
        }, 'WRITE');

        const typeConfig = getTypeConfig(apiName, methodMeta.entity);
        invalidateCacheIfDesired(typeConfig, methodMeta.entity, args);

        return next(args);
    }

    function postWrite(apiName, methodName, methodMeta, jobId, args, promise) {
        if (temporaryIds[jobId] !== undefined) {
            temporaryIds[jobId].promise = promise;
        }

        const typeConfig = getTypeConfig(apiName, methodMeta.entity);
        promise.then(replaceTemporaryWithFinalId(methodMeta, jobId))
               .then(invalidateCacheIfDesired(typeConfig, methodMeta.entity, args));

        return promise;
    }

    function preDelete(next, apiName, methodName, methodMeta, jobId, args) {
        if (methodMeta.multipleEntities) {
            args[0].map(deleteFromCache(methodMeta.entity));
        } else {
            deleteFromCache(methodMeta.entity)(args[0]);
        }

        return next(args);
    }

    function deleteFromCache(type) {
        return entity => {
            delete storage[type][entity.id];
        };
    }

    function postDelete(promise) {
        return promise;
    }

    function invalidateCacheIfDesired(config, entityType, args) {
        if (newEntityWasCreated(args[0]) && config.invalidateOnCreate) {
            collectionQueries[entityType] = {};
        }
    }

    function newEntityWasCreated(entity) {
        return entity.id === undefined;
    }

    function replaceTemporaryWithFinalId(methodMeta, jobId) {
        return realEntity => {
            const tempId = temporaryIds[jobId].id;
            const entityWithTempId = storage[methodMeta.entity][tempId];
            delete storage[methodMeta.entity][tempId];
            storage[methodMeta.entity][realEntity.data.id] = entityWithTempId;
        }
    }

    function createKey(apiName, methodName, multipleEntities, args, type, jobId) {
        if (multipleEntities) {
            return {
                type: 'COLLECTION_KEY',
                value: [apiName, methodName, multipleEntities, args].join('-'),
                entityType: type
            };
        } else {
            return {
                type: 'ENTITY_KEY',
                entityType: type,
                id: args[0].id || createTemporaryId(jobId)
            };
        }
    }

    function createTemporaryId(jobId) {
        const id = generateEntityIdFromJobId(jobId);
        temporaryIds[jobId] = {
            id
        };
        return id;
    }

    function generateEntityIdFromJobId(jobId) {
        return 'TEMPORARY_ID_' + jobId;
    }

    function getTypeConfig(apiName, typeName) {
        if (config[typeName]) {
            return config[typeName];
        } else {
            return {};
        }
    }

    function getFromCache(methodConfig, key) {
        let value;

        if (key.type === 'COLLECTION_KEY') {
            value = getCollectionFromCache(key);
        } else {
            value = getEntityFromCache(key);
        }

        if (value && isValid(value, methodConfig, key)) {
            return value;
        } else {
            return false;
        }
    }

    function getCollectionFromCache(key) {
        if (collectionQueries[key.entityType] &&
            collectionQueries[key.entityType][key.value]) {
            return {
                data: collectionQueries[key.entityType][key.value].ids
                    .map((x) => getEntityDataIfExist(storage[key.entityType][x]))
                    .filter((x) => x !== null)
            };
        } else {
            return false;
        }
    }

    function getEntityDataIfExist(entity) {
        if (entity) {
            return entity.data;
        } else {
            return null;
        }
    }

    function getEntityFromCache(key) {
        if (storage[key.entityType][key.id]) {
            return storage[key.entityType][key.id];
        } else {
            return false;
        }
    }

    function isValid(item, methodConfig, key) {
        if (key.type === 'COLLECTION_KEY') {
            return collectionQueries[key.entityType][key.value].timestamp + methodConfig.ttl * 1000 >= Date.now();
        } else {
            return item.timestamp + methodConfig.ttl * 1000 >= Date.now();
        }
    }

    function saveToCache(key, val, operation) {
        const type = key.entityType;
        if (!storage[type]) {
            storage[type] = {};
        }

        if (key.type === 'COLLECTION_KEY') {
            saveCollection(key, type, val.data, operation);
        } else {
            saveEntity(key, type, val.data);
        }
    }

    function saveCollection(key, type, val, operation) {
        val.forEach((x) => {
            storage[type][x.id] = {
                data: x,
                timestamp: Date.now()
            };
        });

        if (operation !== 'WRITE') {
            const ids = val.map((x) => x.id);

            if (!collectionQueries[key.entityType]) {
                collectionQueries[key.entityType] = {};
            }

            collectionQueries[key.entityType][key.value] = {
                timestamp: Date.now(),
                ids
            };
        }
    }

    function saveEntity(key, type, val) {
        storage[type][key.id] = {
            data: val,
            timestamp: Date.now()
        };
    }
}
<|endoftext|>