<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import gql from 'graphql-tag'
import JsonDom from '../components/JsonDom'
import config from 'gen/config'
import {ApolloClient} from 'apollo-client'
import Util from 'client/util'
import DomUtil from 'client/util/dom'
import {getType} from 'util/types'
import {isEditMode, getSlugVersion, getGqlVariables, urlSensitivMap, gqlQuery} from '../util/cmsView'
import withCms from './withCms'

class CmsViewContainer extends React.Component {
    oriTitle = document.title
    registeredSubscriptions = {}

    constructor(props) {
        super(props)

        if (!props.dynamic && props.slug)
            document.title = props.slug

        this.setUpSubsciptions(props)
        this.addResources(props)
    }

    shouldComponentUpdate(props) {

        const {cmsPage} = props
        const cmsPageOld = this.props.cmsPage
        if (cmsPage) {
            if (!cmsPageOld || (cmsPage.subscriptions !== cmsPageOld.subscriptions)) {
                this.removeSubscriptions()
                this.setUpSubsciptions(props)
            }

            if (!cmsPageOld || cmsPage.resources !== cmsPageOld.resources) {
                this.addResources(props)
            }
        }

        if (!cmsPage && props.loading && this.props.loading) {
            // if there is still no cmsPage and it is still loading
            // there is no need to update
            return false
        }

        // only update if it is needed
        return !cmsPage ||
            !cmsPageOld ||
            cmsPage.slug !== cmsPageOld.slug ||
            cmsPage.modifiedAt !== cmsPageOld.modifiedAt ||
            cmsPage.resolvedData !== cmsPageOld.resolvedData ||
            (!props.renewing && this.props.renewing) ||
            (
                cmsPage.urlSensitiv && (
                    props.location.search !== this.props.location.search ||
                    props.location.hash !== this.props.location.hash)
            ) ||
            props.user !== this.props.user ||
            props.children != this.props.children ||
            Util.shallowCompare(props._props, this.props._props) ||
            /* only if in edit mode */
            (!props.dynamic && isEditMode(props) && (
                cmsPage.template !== cmsPageOld.template ||
                cmsPage.script !== cmsPageOld.script ||
                cmsPage.style !== cmsPageOld.style ||
                props.cmsEditData !== this.props.cmsEditData ||
                /* becuase it is passed to the JsonDom */
                this.props.settings.inlineEditor !== props.settings.inlineEditor))

    }

    componentDidMount() {
        this.setUpSubsciptions(this.props)
    }

    componentWillUnmount() {
        if (!this.props.dynamic) {
            document.title = this.oriTitle
        }
        this.removeSubscriptions()
    }

    render() {
        const {slug, cmsPage, children, dynamic, fetchMore, settings, setKeyValue, ...props} = this.props
        const editMode = isEditMode(this.props)
        if (!cmsPage) {
            // show a loader here
            return null //

        } else {
            // set page title
            if (!dynamic && cmsPage.name)
                document.title = cmsPage.name[_app_.lang]
        }

        if (cmsPage.ssr && !editMode) {
            // it was already rendered on the server side
            return
        }
        const startTime = new Date()
        const content = <JsonDom
            clientQuery={this.clientQuery.bind(this)}
            serverMethod={this.serverMethod.bind(this)}
            setKeyValue={setKeyValue}
            template={cmsPage.template}
            script={cmsPage.script}
            style={cmsPage.style}
            resolvedData={cmsPage.resolvedData}
            parseResolvedData={cmsPage.parseResolvedData}
            resources={cmsPage.resources}
            editMode={editMode}
            inlineEditor={settings && !!settings.inlineEditor}
            slug={slug}
            dynamic={dynamic}
            subscriptionCallback={cb => {
                this._subscriptionCallback = cb
            }}
            onFetchMore={(query, cb) => {
                fetchMore({
                    variables: {
                        query
                    },
                    updateQuery: (prev, {fetchMoreResult}) => {
                        cb(fetchMoreResult)
                    }
                })
            }}
            {...props}>{children}</JsonDom>

        console.info(`render ${this.constructor.name} for ${slug} (loading=${this.props.loading}) in ${new Date() - startTime}ms / time since index.html loaded ${(new Date()).getTime() - _app_.start.getTime()}ms`)
        return content
    }

    addResources(props) {
        const {dynamic, cmsPage} = props

        if (cmsPage && (!dynamic || cmsPage.alwaysLoadAssets)) {
            const {resources} = cmsPage

            DomUtil.removeElements(`[data-cms-view]`)
            if (resources) {
                console.log('refresh resources', props.slug)

                try {
                    const a = JSON.parse(resources)
                    for (let i = 0; i < a.length; i++) {
                        let r = a[i].replace('${build}', ''), ext, params

                        if (r.startsWith('[')) {
                            params = r.substring(1, r.indexOf(']'))
                            r = r.substring(r.indexOf(']') + 1)
                            ext = params
                        }

                        if (!ext) {
                            ext = r.substring(r.lastIndexOf('.') + 1)
                        }

                        if (!params) {
                            if (r.indexOf('?') >= 0) {
                                r += '&'
                            } else {
                                r += '?'
                            }
                            r += 'v=' + config.BUILD_NUMBER
                        }

                        if (ext.indexOf('css') === 0) {
                            DomUtil.addStyle(r, {
                                data: {cmsView: true}
                            })
                        } else if (ext.indexOf('js') === 0) {
                            DomUtil.addScript(r, {
                                crossOrigin:'anonymous',
                                data: {cmsView: true}
                            })
                        }
                    }
                } catch (e) {
                    console.error('Error in resources', e)
                }
            }
        }
    }

    removeSubscriptions() {
        // remove all subscriptions
        Object.keys(this.registeredSubscriptions).forEach(key => {
            this.registeredSubscriptions[key].unsubscribe()
            delete this.registeredSubscriptions[key]
        })
    }

    setUpSubsciptions(props) {
        if (!props.cmsPage) return

        const {cmsPage: {subscriptions}, client, slug} = props
        if (!subscriptions) return

        // remove unsed subscriptions
        Object.keys(this.registeredSubscriptions).forEach(key => {
            if (subscriptions.indexOf(key) < 0) {
                this.registeredSubscriptions[key].unsubscribe()
                delete this.registeredSubscriptions[key]
            }
        })

        const _this = this

        // register new supscriptions
        subscriptions.forEach(subs => {

            if (!this.registeredSubscriptions[subs]) {
                let query = '', subscriptionName = '', isTypeSubscription = false
                if (subs.indexOf('{') === 0) {
                    const obj = JSON.parse(subs)
                    subscriptionName = Object.keys(obj)[0]
                    query = `${obj[subscriptionName]}`

                } else {
                    isTypeSubscription = true
                    const type = getType(subs)
                    subscriptionName = `subscribe${subs}`
                    if (type) {
                        query += 'action data{_id'
                        type.fields.map(({name, required, multi, reference, localized}) => {

                            if (reference) {
                                // todo: field name might be different than name
                                //query += ' ' + name + '{_id name}'
                            } else {
                                if (localized) {
                                    query += ' ' + name + '{' + _app_.lang + '}'
                                } else {
                                    query += ' ' + name
                                }
                            }
                        })
                        query += '}'
                    }
                }

                if (!query) return

                const qqlSubscribe = gql`subscription{${subscriptionName}{${query}}}`
                this.registeredSubscriptions[subs] = client.subscribe({
                    query: qqlSubscribe,
                    variables: {}
                }).subscribe({
                    next(supscriptionData) {

                        if (!isTypeSubscription) {
                            // this kind of subscription is handle by the JsonDom Script
                            _this._subscriptionCallback(supscriptionData)
                            return
                        }
                        if (!supscriptionData.data) {
                            //console.warn('subscription data missing')
                            return
                        }
                        const {action, data} = supscriptionData.data['subscribe' + subs]
                        if (data) {

                            const storedData = client.readQuery({
                                query: gqlQuery(),
                                variables: _this.props.cmsPageVariables
                            })

                            // upadate data in resolvedData string
                            if (storedData.cmsPage && storedData.cmsPage.resolvedData) {

                                const resolvedDataJson = JSON.parse(storedData.cmsPage.resolvedData)
                                if (resolvedDataJson[subs] && resolvedDataJson[subs].results) {

                                    const refResults = resolvedDataJson[subs].results

                                    // remove null values from new data
                                    const noNullData = Util.removeNullValues(data)
                                    Object.keys(noNullData).map(k => {
                                        // check for localized values
                                        if (noNullData[k].constructor === Object && noNullData[k].__typename === 'LocalizedString') {
                                            const v = noNullData[k][_app_.lang]
                                            if (v) {
                                                noNullData[k] = v
                                            }
                                        }
                                    })

                                    if (['update', 'delete'].indexOf(action) >= 0) {

                                        // find data to update
                                        const idx = refResults.findIndex(o => o._id === data._id)

                                        if (idx > -1) {
                                            if (action === 'update') {
                                                // update data
                                                refResults[idx] = Object.assign({}, refResults[idx], noNullData)
                                            } else {
                                                // delete data
                                                refResults.splice(idx, 1)
                                            }
                                        } else {
                                            console.warn(`Data ${data._id} does not exist.`)
                                        }

                                    } else {
                                        //create
                                        refResults.unshift(noNullData)

                                    }

                                    // back to string data
                                    const newStoreData = Object.assign({}, storedData)
                                    newStoreData.cmsPage = Object.assign({}, storedData.cmsPage)
                                    newStoreData.cmsPage.resolvedData = JSON.stringify(resolvedDataJson)

                                    // save new data
                                    client.writeQuery({
                                        query: gqlQuery(),
                                        variables: _this.props.cmsPageVariables,
                                        data: newStoreData
                                    })
                                }
                            }
                        }
                    },
                    error(err) {
                        console.error('err', err)
                    },
                })
            }
        })
    }

    clientQuery(query, options) {
        const {client} = this.props
        if (!query || query.constructor !== String) return

        const {success, error, ...rest} = options

        if (query.startsWith('mutation')) {
            client.mutate({
                mutation: gql(query),
                ...rest
            }).then(success).catch(error)
        } else {
            client.query({
                fetchPolicy: 'network-only',
                forceFetch: true,
                query: gql(query),
                ...rest
            }).then(success).catch(error)
        }
    }

    serverMethod(methodName, args, cb) {
        const {slug, _version} = getSlugVersion(this.props.slug)
        this.props.client.query({
            fetchPolicy: 'network-only',
            forceFetch: true,
            query: gql('query cmsServerMethod($slug:String!,$methodName:String!,$args:String,$_version:String){cmsServerMethod(slug:$slug,methodName:$methodName,args:$args,_version:$_version){result}}'),
            variables: {
                _version,
                slug,
                methodName,
                args: args && (args.constructor === Object || args.constructor === Array) ? JSON.stringify(args) : args
            }
        }).then(cb).catch(cb)
    }

}

CmsViewContainer.propTypes = {
    client: PropTypes.instanceOf(ApolloClient).isRequired,
    loading: PropTypes.bool,
    renewing: PropTypes.bool,
    aboutToChange: PropTypes.bool,
    fetchMore: PropTypes.func,
    children: PropTypes.any,
    cmsPageVariables: PropTypes.object,
    cmsPage: PropTypes.object,
    cmsPages: PropTypes.object,
    keyValue: PropTypes.object,
    setKeyValue: PropTypes.func.isRequired,
    slug: PropTypes.string.isRequired,
    user: PropTypes.object.isRequired,
    /* with Router */
    history: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    match: PropTypes.object.isRequired,
    /* Object is passed to JsonDom */
    _props: PropTypes.object,
    /* if dynamic is set to true that means it is a child of another CmsViewContainer */
    dynamic: PropTypes.bool,
    /* if true data gets refetched with query on url change*/
    urlSensitiv: PropTypes.bool,
    inEditor: PropTypes.bool
}

export default withCms(CmsViewContainer)
<commit_msg>Small improvements<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import gql from 'graphql-tag'
import JsonDom from '../components/JsonDom'
import config from 'gen/config'
import {ApolloClient} from 'apollo-client'
import Util from 'client/util'
import DomUtil from 'client/util/dom'
import {getType} from 'util/types'
import {isEditMode, getSlugVersion, getGqlVariables, urlSensitivMap, gqlQuery} from '../util/cmsView'
import withCms from './withCms'

class CmsViewContainer extends React.Component {
    oriTitle = document.title
    registeredSubscriptions = {}

    constructor(props) {
        super(props)

        if (!props.dynamic && props.slug)
            document.title = props.slug

        this.setUpSubsciptions(props)
        this.addResources(props)
    }

    shouldComponentUpdate(props) {

        const {cmsPage} = props
        const cmsPageOld = this.props.cmsPage
        if (cmsPage) {
            if (!cmsPageOld || (cmsPage.subscriptions !== cmsPageOld.subscriptions)) {
                this.removeSubscriptions()
                this.setUpSubsciptions(props)
            }

            if (!cmsPageOld || cmsPage.resources !== cmsPageOld.resources) {
                this.addResources(props)
            }
        }

        if (!cmsPage && props.loading && this.props.loading) {
            // if there is still no cmsPage and it is still loading
            // there is no need to update
            return false
        }

        // only update if it is needed
        return !cmsPage ||
            !cmsPageOld ||
            cmsPage.slug !== cmsPageOld.slug ||
            cmsPage.modifiedAt !== cmsPageOld.modifiedAt ||
            cmsPage.resolvedData !== cmsPageOld.resolvedData ||
            (!props.renewing && this.props.renewing) ||
            (
                cmsPage.urlSensitiv && (
                    props.location.search !== this.props.location.search ||
                    props.location.hash !== this.props.location.hash)
            ) ||
            props.user !== this.props.user ||
            props.children != this.props.children ||
            Util.shallowCompare(props._props, this.props._props) ||
            /* only if in edit mode */
            (!props.dynamic && isEditMode(props) && (
                cmsPage.template !== cmsPageOld.template ||
                cmsPage.script !== cmsPageOld.script ||
                cmsPage.style !== cmsPageOld.style ||
                props.cmsEditData !== this.props.cmsEditData ||
                /* becuase it is passed to the JsonDom */
                this.props.settings.inlineEditor !== props.settings.inlineEditor))

    }

    componentDidMount() {
        this.setUpSubsciptions(this.props)
    }

    componentWillUnmount() {
        if (!this.props.dynamic) {
            document.title = this.oriTitle
        }
        this.removeSubscriptions()
    }

    render() {
        const {slug, cmsPage, children, dynamic, fetchMore, settings, setKeyValue, ...props} = this.props
        const editMode = isEditMode(this.props)
        if (!cmsPage) {
            // show a loader here
            return null //

        } else {
            // set page title
            if (!dynamic && cmsPage.name)
                document.title = cmsPage.name[_app_.lang]
        }

        if (cmsPage.ssr && !editMode) {
            // it was already rendered on the server side
            return
        }
        const startTime = new Date()
        const content = <JsonDom
            clientQuery={this.clientQuery.bind(this)}
            serverMethod={this.serverMethod.bind(this)}
            setKeyValue={setKeyValue}
            template={cmsPage.template}
            script={cmsPage.script}
            style={cmsPage.style}
            resolvedData={cmsPage.resolvedData}
            parseResolvedData={cmsPage.parseResolvedData}
            resources={cmsPage.resources}
            editMode={editMode}
            inlineEditor={settings && !!settings.inlineEditor}
            slug={slug}
            dynamic={dynamic}
            subscriptionCallback={cb => {
                this._subscriptionCallback = cb
            }}
            onFetchMore={(query, cb) => {
                fetchMore({
                    variables: {
                        query
                    },
                    updateQuery: (prev, {fetchMoreResult}) => {
                        cb(fetchMoreResult)
                    }
                })
            }}
            {...props}>{children}</JsonDom>

        console.info(`render ${this.constructor.name} for ${slug} (loading=${this.props.loading}) in ${new Date() - startTime}ms / time since index.html loaded ${(new Date()).getTime() - _app_.start.getTime()}ms`)
        return content
    }

    addResources(props) {
        const {dynamic, cmsPage} = props

        if (cmsPage && (!dynamic || cmsPage.alwaysLoadAssets)) {
            const {resources} = cmsPage

            DomUtil.removeElements(`[data-cms-view]`)
            if (resources) {
                console.log('refresh resources', props.slug)

                try {
                    const a = JSON.parse(resources)
                    for (let i = 0; i < a.length; i++) {
                        let r = a[i].replace('${build}', ''), ext, params

                        if (r.startsWith('[')) {
                            params = r.substring(1, r.indexOf(']'))
                            r = r.substring(r.indexOf(']') + 1)
                            ext = params
                        }

                        if (!ext) {
                            ext = r.substring(r.lastIndexOf('.') + 1)
                        }

                        if (!params) {
                            if (r.indexOf('?') >= 0) {
                                r += '&'
                            } else {
                                r += '?'
                            }
                            r += 'v=' + config.BUILD_NUMBER
                        }

                        if (ext.indexOf('css') === 0) {
                            DomUtil.addStyle(r, {
                                data: {cmsView: true}
                            })
                        } else if (ext.indexOf('js') === 0) {
                            DomUtil.addScript(r, {
                                data: {cmsView: true}
                            })
                        }
                    }
                } catch (e) {
                    console.error('Error in resources', e)
                }
            }
        }
    }

    removeSubscriptions() {
        // remove all subscriptions
        Object.keys(this.registeredSubscriptions).forEach(key => {
            this.registeredSubscriptions[key].unsubscribe()
            delete this.registeredSubscriptions[key]
        })
    }

    setUpSubsciptions(props) {
        if (!props.cmsPage) return

        const {cmsPage: {subscriptions}, client, slug} = props
        if (!subscriptions) return

        // remove unsed subscriptions
        Object.keys(this.registeredSubscriptions).forEach(key => {
            if (subscriptions.indexOf(key) < 0) {
                this.registeredSubscriptions[key].unsubscribe()
                delete this.registeredSubscriptions[key]
            }
        })

        const _this = this

        // register new supscriptions
        subscriptions.forEach(subs => {

            if (!this.registeredSubscriptions[subs]) {
                let query = '', subscriptionName = '', isTypeSubscription = false
                if (subs.indexOf('{') === 0) {
                    const obj = JSON.parse(subs)
                    subscriptionName = Object.keys(obj)[0]
                    query = `${obj[subscriptionName]}`

                } else {
                    isTypeSubscription = true
                    const type = getType(subs)
                    subscriptionName = `subscribe${subs}`
                    if (type) {
                        query += 'action data{_id'
                        type.fields.map(({name, required, multi, reference, localized}) => {

                            if (reference) {
                                // todo: field name might be different than name
                                //query += ' ' + name + '{_id name}'
                            } else {
                                if (localized) {
                                    query += ' ' + name + '{' + _app_.lang + '}'
                                } else {
                                    query += ' ' + name
                                }
                            }
                        })
                        query += '}'
                    }
                }

                if (!query) return

                const qqlSubscribe = gql`subscription{${subscriptionName}{${query}}}`
                this.registeredSubscriptions[subs] = client.subscribe({
                    query: qqlSubscribe,
                    variables: {}
                }).subscribe({
                    next(supscriptionData) {

                        if (!isTypeSubscription) {
                            // this kind of subscription is handle by the JsonDom Script
                            _this._subscriptionCallback(supscriptionData)
                            return
                        }
                        if (!supscriptionData.data) {
                            //console.warn('subscription data missing')
                            return
                        }
                        const {action, data} = supscriptionData.data['subscribe' + subs]
                        if (data) {

                            const storedData = client.readQuery({
                                query: gqlQuery(),
                                variables: _this.props.cmsPageVariables
                            })

                            // upadate data in resolvedData string
                            if (storedData.cmsPage && storedData.cmsPage.resolvedData) {

                                const resolvedDataJson = JSON.parse(storedData.cmsPage.resolvedData)
                                if (resolvedDataJson[subs] && resolvedDataJson[subs].results) {

                                    const refResults = resolvedDataJson[subs].results

                                    // remove null values from new data
                                    const noNullData = Util.removeNullValues(data)
                                    Object.keys(noNullData).map(k => {
                                        // check for localized values
                                        if (noNullData[k].constructor === Object && noNullData[k].__typename === 'LocalizedString') {
                                            const v = noNullData[k][_app_.lang]
                                            if (v) {
                                                noNullData[k] = v
                                            }
                                        }
                                    })

                                    if (['update', 'delete'].indexOf(action) >= 0) {

                                        // find data to update
                                        const idx = refResults.findIndex(o => o._id === data._id)

                                        if (idx > -1) {
                                            if (action === 'update') {
                                                // update data
                                                refResults[idx] = Object.assign({}, refResults[idx], noNullData)
                                            } else {
                                                // delete data
                                                refResults.splice(idx, 1)
                                            }
                                        } else {
                                            console.warn(`Data ${data._id} does not exist.`)
                                        }

                                    } else {
                                        //create
                                        refResults.unshift(noNullData)

                                    }

                                    // back to string data
                                    const newStoreData = Object.assign({}, storedData)
                                    newStoreData.cmsPage = Object.assign({}, storedData.cmsPage)
                                    newStoreData.cmsPage.resolvedData = JSON.stringify(resolvedDataJson)

                                    // save new data
                                    client.writeQuery({
                                        query: gqlQuery(),
                                        variables: _this.props.cmsPageVariables,
                                        data: newStoreData
                                    })
                                }
                            }
                        }
                    },
                    error(err) {
                        console.error('err', err)
                    },
                })
            }
        })
    }

    clientQuery(query, options) {
        const {client} = this.props
        if (!query || query.constructor !== String) return

        const {success, error, ...rest} = options

        if (query.startsWith('mutation')) {
            client.mutate({
                mutation: gql(query),
                ...rest
            }).then(success).catch(error)
        } else {
            client.query({
                fetchPolicy: 'network-only',
                forceFetch: true,
                query: gql(query),
                ...rest
            }).then(success).catch(error)
        }
    }

    serverMethod(methodName, args, cb) {
        const {slug, _version} = getSlugVersion(this.props.slug)
        this.props.client.query({
            fetchPolicy: 'network-only',
            forceFetch: true,
            query: gql('query cmsServerMethod($slug:String!,$methodName:String!,$args:String,$_version:String){cmsServerMethod(slug:$slug,methodName:$methodName,args:$args,_version:$_version){result}}'),
            variables: {
                _version,
                slug,
                methodName,
                args: args && (args.constructor === Object || args.constructor === Array) ? JSON.stringify(args) : args
            }
        }).then(cb).catch(cb)
    }

}

CmsViewContainer.propTypes = {
    client: PropTypes.instanceOf(ApolloClient).isRequired,
    loading: PropTypes.bool,
    renewing: PropTypes.bool,
    aboutToChange: PropTypes.bool,
    fetchMore: PropTypes.func,
    children: PropTypes.any,
    cmsPageVariables: PropTypes.object,
    cmsPage: PropTypes.object,
    cmsPages: PropTypes.object,
    keyValue: PropTypes.object,
    setKeyValue: PropTypes.func.isRequired,
    slug: PropTypes.string.isRequired,
    user: PropTypes.object.isRequired,
    /* with Router */
    history: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    match: PropTypes.object.isRequired,
    /* Object is passed to JsonDom */
    _props: PropTypes.object,
    /* if dynamic is set to true that means it is a child of another CmsViewContainer */
    dynamic: PropTypes.bool,
    /* if true data gets refetched with query on url change*/
    urlSensitiv: PropTypes.bool,
    inEditor: PropTypes.bool
}

export default withCms(CmsViewContainer)
<|endoftext|>


<commit_before>/**
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

(function () {
    this.LivePlayerSupportLevelUnseekableTest = AsyncTestCase("LivePlayerSupportLevelUnseekableTest");

    this.LivePlayerSupportLevelUnseekableTest.prototype.setUp = function () {
        this.sandbox = sinon.sandbox.create();
    };

    this.LivePlayerSupportLevelUnseekableTest.prototype.tearDown = function () {
        this.sandbox.restore();
    };

    var config = {"modules":{"base":"antie/devices/browserdevice","modifiers":["antie/devices/mediaplayer/html5"]}, "input":{"map":{}},"layouts":[{"width":960,"height":540,"module":"fixtures/layouts/default","classes":["browserdevice540p"]}],"deviceConfigurationKey":"devices-html5-1"};

    this.LivePlayerSupportLevelUnseekableTest.prototype.testGetLiveSupportReturnsUnseekableWithSupportLevelUnseekable = function (queue) {
        expectAsserts(1);

        queuedApplicationInit(queue, 'lib/mockapplication', ["antie/devices/mediaplayer/mediaplayer", "antie/devices/device", "antie/devices/mediaplayer/live/unseekable"], function(application, MediaPlayer, Device) {

            var device = new Device(antie.framework.deviceConfiguration);
            var liveSupportLevel = device.getLiveSupport();

            assertEquals("unseekable", liveSupportLevel);
        });
    };

    this.LivePlayerSupportLevelUnseekableTest.prototype.testLivePlayerBeginPlaybackCallsFunctionInMediaElement = function (queue) {
        expectAsserts(1);

        queuedApplicationInit(queue, 'lib/mockapplication', ["antie/devices/mediaplayer/mediaplayer", "antie/devices/device", "antie/devices/mediaplayer/live/unseekable"], function(application, MediaPlayer, Device) {

            var device = new Device(antie.framework.deviceConfiguration);
            var livePlayer = device.getLivePlayer();

            device.getMediaPlayer().beginPlayback = this.sandbox.stub();
            livePlayer.beginPlayback();

            assert(device.getMediaPlayer().beginPlayback.calledOnce);
        }, config);
    };

})();
<commit_msg>Refactored out testFunctionsInLivePlayerCallMediaPlayerFunctions so we can use it for other tests<commit_after>/**
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

(function () {
    this.LivePlayerSupportLevelUnseekableTest = AsyncTestCase("LivePlayerSupportLevelUnseekableTest");

    this.LivePlayerSupportLevelUnseekableTest.prototype.setUp = function () {
        this.sandbox = sinon.sandbox.create();
    };

    this.LivePlayerSupportLevelUnseekableTest.prototype.tearDown = function () {
        this.sandbox.restore();
    };

    var config = {"modules":{"base":"antie/devices/browserdevice","modifiers":["antie/devices/mediaplayer/html5"]}, "input":{"map":{}},"layouts":[{"width":960,"height":540,"module":"fixtures/layouts/default","classes":["browserdevice540p"]}],"deviceConfigurationKey":"devices-html5-1"};

    this.LivePlayerSupportLevelUnseekableTest.prototype.testGetLiveSupportReturnsUnseekableWithSupportLevelUnseekable = function (queue) {
        expectAsserts(1);

        queuedApplicationInit(queue, 'lib/mockapplication', ["antie/devices/mediaplayer/mediaplayer", "antie/devices/device", "antie/devices/mediaplayer/live/unseekable"], function(application, MediaPlayer, Device) {

            var device = new Device(antie.framework.deviceConfiguration);
            var liveSupportLevel = device.getLiveSupport();

            assertEquals("unseekable", liveSupportLevel);
        });
    };

    var testFunctionsInLivePlayerCallMediaPlayerFunctions = function(action) {
        return function (queue) {
            expectAsserts(1);
            queuedApplicationInit(queue, 'lib/mockapplication', ["antie/devices/mediaplayer/mediaplayer", "antie/devices/device", "antie/devices/mediaplayer/live/unseekable"], function(application, MediaPlayer, Device) {
                var device = new Device(antie.framework.deviceConfiguration);
                var livePlayer = device.getLivePlayer();
                device.getMediaPlayer()[action] = this.sandbox.stub();
                livePlayer[action]();
                assert(device.getMediaPlayer()[action].calledOnce);
            }, config);
        }
    };

    this.LivePlayerSupportLevelUnseekableTest.prototype.testLivePlayerBeginPlaybackCallsFunctionInMediaElement = testFunctionsInLivePlayerCallMediaPlayerFunctions('beginPlayback');
})();
<|endoftext|>


<commit_before>"use strict"

// Module dependencies
var winston = require("winston");
var openVeoAPI = require("openveo-api");
var PropertyProvider = openVeoAPI.PropertyProvider;
var applicationStorage = openVeoAPI.applicationStorage;

// Retrieve logger
var logger = winston.loggers.get("openveo");

var propertyProvider = new PropertyProvider(applicationStorage.getDatabase());

/**
 * Gets the list of properties and return it as a JSON object.
 * Returns a JSON object as :
 * {
 *   properties : [
 *     {
 *       "name" : "Name of the property",
 *       "description" : "Description of the property",
 *       "type" : "Type of the property"
 *     }
 *     ...
 *   ]
 * }
 */
module.exports.getPropertiesAction = function(request, response, next){
  propertyProvider.getProperties(function(error, properties){
    if(error){
      logger.error(error && error.message);
      response.status(500);
    }
    else
      response.send({ properties : properties });
  });
};

/**
 * Adds a new property.
 * Expects the following body :
 * {
 *   "name" : "Name of the property",
 *   "description" : "Description of the property",
 *   "type" : "Type of the property"
 * }
 * Returns the property as a JSON object :
 * {
 *   property : {
 *    "name" : "Name of the property",
 *    "description" : "Description of the property",
 *    "type" : "Type of the property"
 *   }
 * }
 */
module.exports.addPropertyAction = function(request, response, next){
  if(request.body && request.body.name && request.body.description && request.body.type){

    var property = {
      id : Date.now(),
      name : request.body.name,
      description : request.body.description,
      type : request.body.type
    };

    propertyProvider.addProperty(property, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500);
      }
      else
        response.send({property  : property});
    });
  }
  else
    response.status(400);
};

/**
 * Updates a property.
 * Expects one GET parameter :
 *  - id The id of the property to update
 * Expects the following body :
 * {
 *   "name" : "Name of the property",
 *   "description" : "Description of the property",
 *   "type" : "Type of the property"
 * }
 * with name, description and type optional.
 * Returns either an HTTP code 500 if a server error occured, 400
 * if id parameter is not set or 200 if success.
 */
module.exports.updatePropertyAction = function(request, response, next){
  if(request.params.id && request.body){
    var property = {};
    if(request.body.name) property["name"] = request.body.name;
    if(request.body.description) property["description"] = request.body.description;
    if(request.body.type) property["type"] = request.body.type;

    propertyProvider.updateProperty(request.params.id, property, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500).send();
      }
      else
        response.send();
    });
  }
  else
    response.status(400).send();
};

/**
 * Removes a property.
 * Expects one GET parameter :
 *  - id The id of the property to remove
 * Returns either an HTTP code 500 if a server error occured, 400
 * if id parameter is not set or 200 if success.
 * TODO Also remove this property from all videos ??
 */
module.exports.removePropertyAction = function(request, response, next){
  if(request.params.id){
    propertyProvider.removeProperty(request.params.id, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500);
      }
      else
        response.send();
    });
  }
  else
    response.status(400).send();
};<commit_msg>Correct bug while trying to add a new custom property<commit_after>"use strict"

// Module dependencies
var winston = require("winston");
var openVeoAPI = require("openveo-api");
var PropertyProvider = openVeoAPI.PropertyProvider;
var applicationStorage = openVeoAPI.applicationStorage;

// Retrieve logger
var logger = winston.loggers.get("openveo");

var propertyProvider = new PropertyProvider(applicationStorage.getDatabase());

/**
 * Gets the list of properties and return it as a JSON object.
 * Returns a JSON object as :
 * {
 *   properties : [
 *     {
 *       "name" : "Name of the property",
 *       "description" : "Description of the property",
 *       "type" : "Type of the property"
 *     }
 *     ...
 *   ]
 * }
 */
module.exports.getPropertiesAction = function(request, response, next){
  propertyProvider.getProperties(function(error, properties){
    if(error){
      logger.error(error && error.message);
      response.status(500);
    }
    else
      response.send({ properties : properties });
  });
};

/**
 * Adds a new property.
 * Expects the following body :
 * {
 *   "name" : "Name of the property",
 *   "description" : "Description of the property",
 *   "type" : "Type of the property"
 * }
 * Returns the property as a JSON object :
 * {
 *   property : {
 *    "name" : "Name of the property",
 *    "description" : "Description of the property",
 *    "type" : "Type of the property"
 *   }
 * }
 */
module.exports.addPropertyAction = function(request, response, next){
  if(request.body && request.body.name && request.body.description && request.body.type){

    var property = {
      id : Date.now(),
      name : request.body.name,
      description : request.body.description,
      type : request.body.type
    };

    propertyProvider.addProperty(property, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500);
      }
      else
        response.send({property  : property});
    });
  }
  else
    response.status(400).send();
};

/**
 * Updates a property.
 * Expects one GET parameter :
 *  - id The id of the property to update
 * Expects the following body :
 * {
 *   "name" : "Name of the property",
 *   "description" : "Description of the property",
 *   "type" : "Type of the property"
 * }
 * with name, description and type optional.
 * Returns either an HTTP code 500 if a server error occured, 400
 * if id parameter is not set or 200 if success.
 */
module.exports.updatePropertyAction = function(request, response, next){
  if(request.params.id && request.body){
    var property = {};
    if(request.body.name) property["name"] = request.body.name;
    if(request.body.description) property["description"] = request.body.description;
    if(request.body.type) property["type"] = request.body.type;

    propertyProvider.updateProperty(request.params.id, property, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500).send();
      }
      else
        response.send();
    });
  }
  else
    response.status(400).send();
};

/**
 * Removes a property.
 * Expects one GET parameter :
 *  - id The id of the property to remove
 * Returns either an HTTP code 500 if a server error occured, 400
 * if id parameter is not set or 200 if success.
 * TODO Also remove this property from all videos ??
 */
module.exports.removePropertyAction = function(request, response, next){
  if(request.params.id){
    propertyProvider.removeProperty(request.params.id, function(error){
      if(error){
        logger.error(error && error.message);
        response.status(500);
      }
      else
        response.send();
    });
  }
  else
    response.status(400).send();
};<|endoftext|>


<commit_before>function onPageLoad() {
    searchTimerID = -1;
    lastQuery = null;
    lastSearchString = inputBox.value;

    inputBox.focus();

    inputBox.onkeyup = function () {
        if (event && event.keyCode == 13) {
            onSearchChange();
        }
    };

    inputBox.oninput = function () {
        onSearchChange();
    };

    var query = document.location.search;
    if (query) {
        query = query.slice(1);
        if (query) {
            query = decodeURIComponent(query);
            inputBox.value = query;
            inputBox.oninput();
        }
    }
}

function onSearchChange() {
    if (inputBox.value == lastSearchString) {
        return;
    }

    lastSearchString = inputBox.value;

    if (inputBox.value.length > 0) {
        if (searchTimerID == -1) {
            searchTimerID = setTimeout(runSearch, 600);
        }
    } else {
        loadResults("");
    }
}

function runSearch() {
    searchTimerID = -1;
    if (typeof lastQuery === "object" && lastQuery !== null) {
        lastQuery.abort();
        lastQuery = null;
    }

    search();
}

function search() {
    var query = "api/answers/?query=" + encodeURIComponent(inputBox.value);

    lastQuery = getUrl(query, loadResults);
}

function getUrl(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.setRequestHeader("Accept", "text/html");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            var data = xhr.responseText;
            if (typeof data === "string" && data.length > 0) {
                callback(data);
            }
        }
    };
    xhr.send();
    return xhr;
}

function loadResults(data) {
    var container = document.getElementById("outputDiv");
    if (container) {
        container.innerHTML = data;
        if (data) {
            updateUrl();
        }
    }
}

function updateUrl() {
    var query = inputBox.value;
    if (query) {
        query = "?" + encodeURIComponent(query);
        if (document.location.search !== query) {
            top.history.replaceState(null, top.document.title, query);
        }
    }
}<commit_msg>Another fix to script.<commit_after>function onPageLoad() {
    searchTimerID = -1;
    lastQuery = null;
    lastSearchString = inputBox.value;

    inputBox.focus();

    inputBox.onkeyup = function () {
        if (event && event.keyCode == 13) {
            onSearchChange();
        }
    };

    inputBox.oninput = function () {
        onSearchChange();
    };

    var query = document.location.search;
    if (query) {
        query = query.slice(1);
        if (query) {
            query = decodeURIComponent(query);
            inputBox.value = query;
            lastSearchString = query;
            search();
        }
    }
}

function onSearchChange() {
    if (inputBox.value == lastSearchString) {
        return;
    }

    lastSearchString = inputBox.value;

    if (inputBox.value.length > 0) {
        if (searchTimerID == -1) {
            searchTimerID = setTimeout(runSearch, 600);
        }
    } else {
        loadResults("");
    }
}

function runSearch() {
    searchTimerID = -1;
    if (typeof lastQuery === "object" && lastQuery !== null) {
        lastQuery.abort();
        lastQuery = null;
    }

    search();
}

function search() {
    var query = "api/answers/?query=" + encodeURIComponent(inputBox.value);

    lastQuery = getUrl(query, loadResults);
}

function getUrl(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.setRequestHeader("Accept", "text/html");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            var data = xhr.responseText;
            if (typeof data === "string" && data.length > 0) {
                callback(data);
            }
        }
    };
    xhr.send();
    return xhr;
}

function loadResults(data) {
    var container = document.getElementById("outputDiv");
    if (container) {
        container.innerHTML = data;
        if (data) {
            updateUrl();
        }
    }
}

function updateUrl() {
    var query = inputBox.value;
    if (query) {
        query = "?" + encodeURIComponent(query);
        if (document.location.search !== query) {
            top.history.replaceState(null, top.document.title, query);
        }
    }
}<|endoftext|>


<commit_before>var assert = require("assert"),
    moment           = require('moment'),
    events   = require ('events'),
    util     = require ('util'),
    exec   = require('child_process').exec,
    mvcp_server      = require('../drivers/mvcp/mvcp-driver'),
    mosto  = require('../mosto'),
    melted  = require('../api/Melted'),
    Playlist  = require('../api/Playlist'),
    Media  = require('../api/Media');

// SILENCE LOG OUTPUT
var util = require('util');
var fs = require('fs');
var log = fs.createWriteStream('./stdout.log');

console.log = console.info = function(t) {
  var out;
  if (t && ~t.indexOf('%')) {
    out = util.format.apply(util, arguments);
    process.stdout.write(out + '\n');
    return;
  } else {
    out = Array.prototype.join.call(arguments, ' ');
  }
  out && log.write(out + '\n');
};
// END SILENCE LOG OUTPUT

silence = function(callback) {
	var ori_console_log = console.log;
	var ori_console_error = console.error;
	console.log = function() { };
	console.error = function() { };
	var r = callback();
	console.log = ori_console_log;
	console.error = ori_console_error;
	return r;
}

describe('Mosto [FETCH/Database] section tests', function(done) {
    var mosto_server = undefined;
    var server = undefined;

    this.timeout(15000);

    melted.take(function() {
	    before(function(done) {
		    melted.stop(function(){
		        done();
		    });
	    });

	    describe('#[FETCH] start mosto', function() {
		    it('-- starting mosto shouldnt throw error', function() {
		        mosto_server = silence(function(){ return new mosto(); });
		        assert.notEqual(mosto_server, undefined);
		    });
		    it('-- mvcp server connected should return false', function() {
		        var r = silence(function(){ return mosto_server.server_started; });
		        assert.equal(r, false);
		    });
	    });

        function test_pl_driver() {
            events.EventEmitter.call (this);
            this.window = {};
        };

        util.inherits ( test_pl_driver, events.EventEmitter);

        test_pl_driver.prototype.getPlaylists = function( ops, callback ) {
            var playlists = [];

            var playlist = undefined;
            var files =  {  0: "../videos/SMPTE_Color_Bars_01.mp4",
                            1: "../videos/SMPTE_Color_Bars_02.mp4",
                            2: "../videos/SMPTE_Color_Bars_03.mp4" };
            var medias = [];

            for( var i=0; i<3; i++ ) {
                var clip = new Media(  files[i].substring(files[i].lastIndexOf("/") + 1)+"_id", 0, undefined, 1, files[i].substring(files[i].lastIndexOf("/") + 1), "default", files[i], "00:00:30.00", 25 );
                medias.push(clip);
            }

            var startDate = moment().toDate();
            var endDate = moment( startDate ).add( moment.duration({seconds:90})).toDate();
            playlist = new Playlist( "test_pl_1_id", "test_pl_1_name", startDate, medias, endDate, "snap", false );

            playlists.push(playlist);

            callback(playlists);
        };

        test_pl_driver.prototype.getWindow = function( from, to) {
            var window = {
                from: moment(from),
                to: moment(to),
            };
            window.timeSpan = window.to.diff(window.from);
            return window;
        };

        test_pl_driver.prototype.setWindow = function(from, to) {
            var self = this;
            self.window = self.getWindow(from, to);
            return self.window;
        };

        function TestPlaylist() {
            var playlist = undefined;
            var files =  {  0: "../videos/SMPTE_Color_Bars_01.mp4",
                            1: "../videos/SMPTE_Color_Bars_02.mp4",
                            2: "../videos/SMPTE_Color_Bars_03.mp4" };
            var medias = [];

            for( var i=0; i<3; i++ ) {
                var clip = new Media(  files[i].substring(files[i].lastIndexOf("/") + 1)+"_id", 0, undefined, 1, files[i].substring(files[i].lastIndexOf("/") + 1), "default", files[i], "00:00:30.00", 25 );
                medias.push(clip);
            }

            var startDate = moment().toDate();
            var endDate = moment( startDate ).add( moment.duration({seconds:90})).toDate();
            playlist = new Playlist( "test_pl_1_id", "test_pl_1_name", startDate, medias, endDate, "snap", false );
            return playlist;
        }

        describe("#[FETCH] Checking no playlists", function() {
            it("--should return black_id", function(done) {
                assert.equal( mosto_server.playlists.length, 0 );
                assert.equal( mosto_server.scheduled_clips.length, 0 );
                done();
            });
        });

        describe("#[FETCH] Adding playlist", function() {

            var playlist = new TestPlaylist();

            before(function(done){
                mosto_server.addPlaylist( playlist );
                done();
            });
            it("--should return same playlist ", function(done) {
                var result = true;
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, playlist.id );
                assert.equal( mosto_server.playlists[0].name, playlist.name );
                assert.equal( mosto_server.playlists[0].startDate, playlist.startDate );
                assert.equal( mosto_server.playlists[0].medias.length, playlist.medias.length );
                assert.equal( mosto_server.playlists[0].endDate, playlist.endDate );
                assert.equal( mosto_server.playlists[0].mode, playlist.mode );
                assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });

        });

        describe("#[FETCH] Updating playlist", function() {

            var playlist = new TestPlaylist();

            before(function(done){
                mosto_server.updatePlaylist( playlist );
                done();
            });
            it("--should return the same playlist updated", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, playlist.id );
                assert.equal( mosto_server.playlists[0].name, playlist.name );
                assert.equal( mosto_server.playlists[0].startDate, playlist.startDate );
                assert.equal( mosto_server.playlists[0].medias.length, playlist.medias.length );
                assert.equal( mosto_server.playlists[0].endDate, playlist.endDate );
                assert.equal( mosto_server.playlists[0].mode, playlist.mode );
                assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });
        });

        describe("#[FETCH] Remove playlist", function() {
            before(function(done){
                mosto_server.removePlaylist( "test_pl_1_id" );
                done();
            });
            it("--should return only the blank black_id", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, "black_id" );
                //assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });

        });

        describe("#[FETCH] Doing a checkoutPlaylists()", function() {
            var driver_playlists = undefined;

            before(function(done){
                mosto_server.driver = new test_pl_driver();
                mosto_server.driver.getPlaylists( { from: mosto_server.time_window_from, to: mosto_server.time_window_to, setWindow: false }, function(playlists) {
                    driver_playlists = playlists
                    mosto_server.playlists = [];
                    mosto_server.checkoutPlaylists();
                    done();
                });
            });
            it("--should return the same playlist", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.notEqual( mosto_server.playlists[0].id, "black_id" );
                assert.equal( mosto_server.playlists[0].id, driver_playlists[0].id );
                assert.equal( mosto_server.playlists[0].name, driver_playlists[0].name );
                //assert.equal( mosto_server.playlists[0].startDate, driver_playlists[0].startDate );
                assert.equal( mosto_server.playlists[0].medias.length, driver_playlists[0].medias.length );
                //assert.equal( mosto_server.playlists[0].endDate, driver_playlists[0].endDate );
                assert.equal( mosto_server.playlists[0].mode, driver_playlists[0].mode );
                done();
            });

        });

	    describe('#[FETCH] leave melted', function() {
		    it('-- leave melted', function(done) {
			    //mosto_server.stop();
			    mosto_server = null;
			    melted.stop(function(pid) {
				    melted.leave();
				    done();
			    });
		    });
	    });

    });
    describe('#last [FETCH] check ', function() {
        it("--should finish FETCH", function(done) {
            done();
        });
    });

});
<commit_msg>Added test-driver.js<commit_after>var assert = require("assert"),
    moment           = require('moment'),
    events   = require ('events'),
    util     = require ('util'),
    exec   = require('child_process').exec,
    mvcp_server      = require('../drivers/mvcp/mvcp-driver'),
    test_driver    = require('../drivers/playlists/test-driver'),
    mosto  = require('../mosto'),
    melted  = require('../api/Melted'),
    Playlist  = require('../api/Playlist'),
    Media  = require('../api/Media');

// SILENCE LOG OUTPUT
var util = require('util');
var fs = require('fs');
var log = fs.createWriteStream('./stdout.log');

console.log = console.info = function(t) {
  var out;
  if (t && ~t.indexOf('%')) {
    out = util.format.apply(util, arguments);
    process.stdout.write(out + '\n');
    return;
  } else {
    out = Array.prototype.join.call(arguments, ' ');
  }
  out && log.write(out + '\n');
};
// END SILENCE LOG OUTPUT

silence = function(callback) {
	var ori_console_log = console.log;
	var ori_console_error = console.error;
	console.log = function() { };
	console.error = function() { };
	var r = callback();
	console.log = ori_console_log;
	console.error = ori_console_error;
	return r;
}

describe('Mosto [FETCH/Database] section tests', function(done) {
    var mosto_server = undefined;
    var server = undefined;

    this.timeout(15000);

    melted.take(function() {

	    before(function(done) {
		    melted.stop(function(pid){
		        done();
		    });
	    });

	    describe('#[FETCH] start mosto', function() {
		    it('-- starting mosto shouldnt throw error', function() {
		        mosto_server = silence(function(){ return new mosto(); });
                mosto_server.driver = new test_driver();
		        assert.notEqual(mosto_server, undefined);
		    });
		    it('-- mvcp server connected should return false', function() {
		        var r = silence(function(){ return mosto_server.server_started; });
		        assert.equal(r, false);
		    });
	    });

        describe("#[FETCH] Checking no playlists", function() {
            it("--should return black_id", function(done) {
                assert.equal( mosto_server.playlists.length, 0 );
                assert.equal( mosto_server.scheduled_clips.length, 0 );
                done();
            });
        });

        describe("#[FETCH] Adding playlist", function() {

            var playlist = undefined;

            before(function(done){
                playlist =  mosto_server.driver.TestPlaylist();
                mosto_server.addPlaylist( playlist );
                done();
            });
            it("--should return same playlist ", function(done) {
                var result = true;
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, playlist.id );
                assert.equal( mosto_server.playlists[0].name, playlist.name );
                assert.equal( mosto_server.playlists[0].startDate, playlist.startDate );
                assert.equal( mosto_server.playlists[0].medias.length, playlist.medias.length );
                assert.equal( mosto_server.playlists[0].endDate, playlist.endDate );
                assert.equal( mosto_server.playlists[0].mode, playlist.mode );
                assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });

        });

        describe("#[FETCH] Updating playlist", function() {

            var playlist = undefined;

            before(function(done){
                playlist =  mosto_server.driver.TestPlaylist();
                mosto_server.updatePlaylist( playlist );
                done();
            });
            it("--should return the same playlist updated", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, playlist.id );
                assert.equal( mosto_server.playlists[0].name, playlist.name );
                assert.equal( mosto_server.playlists[0].startDate, playlist.startDate );
                assert.equal( mosto_server.playlists[0].medias.length, playlist.medias.length );
                assert.equal( mosto_server.playlists[0].endDate, playlist.endDate );
                assert.equal( mosto_server.playlists[0].mode, playlist.mode );
                assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });
        });

        describe("#[FETCH] Remove playlist", function() {
            before(function(done){
                mosto_server.removePlaylist( "test_playlist_1_id" );
                done();
            });
            it("--should return only the blank black_id", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.equal( mosto_server.playlists[0].id, "black_id" );
                //assert.notEqual( mosto_server.scheduled_clips.length, 0 );
                done();
            });

        });

        describe("#[FETCH] Doing a checkoutPlaylists()", function() {
            var driver_playlists = undefined;

            before(function(done){
                mosto_server.driver.setCheckoutMode(true);
                mosto_server.checkoutPlaylists( function(playlists) {
                    driver_playlists = playlists;
                    if (playlists.length==0) return done(new Error("test_driver->getPlaylists must return some playlists when called in co_mode:true"));
                    done();
                });
            });
            it("--should return the same playlist", function(done) {
                assert.equal( mosto_server.playlists.length, 1 );
                assert.notEqual( mosto_server.playlists[0].id, "black_id" );
                assert.equal( mosto_server.playlists[0].id, driver_playlists[0].id );
                assert.equal( mosto_server.playlists[0].name, driver_playlists[0].name );
                //assert.equal( mosto_server.playlists[0].startDate, driver_playlists[0].startDate );
                assert.equal( mosto_server.playlists[0].medias.length, driver_playlists[0].medias.length );
                //assert.equal( mosto_server.playlists[0].endDate, driver_playlists[0].endDate );
                assert.equal( mosto_server.playlists[0].mode, driver_playlists[0].mode );
                done();
            });

        });

	    describe('#[FETCH] leave melted', function() {
		    it('-- leave melted', function(done) {
			    //mosto_server.stop();
			    mosto_server = null;
			    melted.stop(function(pid) {
				    melted.leave();
				    done();
			    });
		    });
	    });

    });
    describe('#last [FETCH] check ', function() {
        it("--should finish FETCH", function(done) {
            done();
        });
    });

});
<|endoftext|>


<commit_before>/**
 * Change favicon to show Logux synchronization status.
 *
 * @param {CrossTabClient} client Observed Client instance.
 * @param {object} [links] Set favicon links.
 * @param {string} [links.normal] Default favicon link. By default,
 *                                it will be taken from current favicon.
 * @param {string} [links.offline] Offline favicon link.
 * @param {string} [links.error] Error favicon link.
 *
 * @return {Function} Unbind favicon listener.
 *
 * @example
 * import favicon from 'logux-status/favicon'
 * favicon(client, {
 *   normal: '/favicon.ico',
 *   offline: '/offline.ico',
 *   error: '/error.ico'
 * })
 */
function favicon (client, links) {
  links = links || {}

  var normal = links.normal
  var offline = links.offline
  var error = links.error

  var unbind = []
  var doc = document
  var fav = false
  var prevFav = false

  function update () {
    if (client.connected && prevFav !== normal) {
      fav.href = prevFav = normal
    } else if (!client.connected && offline &&
               prevFav !== offline && prevFav !== error) {
      fav.href = prevFav = offline
    }
  }

  function setError () {
    if (error && prevFav !== error) {
      fav.href = prevFav = error
    }
  }

  if (typeof doc !== 'undefined') {
    fav = doc.querySelector('link[rel~="icon"]')

    if (typeof normal === 'undefined') {
      if (fav) {
        normal = fav.href
      } else {
        normal = ''
      }
    }

    if (!fav) {
      fav = document.createElement('link')
      fav.rel = 'icon'
      fav.href = ''
      document.head.appendChild(fav)
    }

    unbind.push(client.on('state', update))
    update()

    unbind.push(client.log.on('add', function (action) {
      if (action.type === 'logux/undo' && action.reason) setError()
    }))

    unbind.push(client.sync.on('error', function (err) {
      if (err.type !== 'timeout') setError()
    }))
  }

  return function () {
    for (var i = 0; i < unbind.length; i++) {
      unbind[i]()
    }
  }
}

module.exports = favicon
<commit_msg>Always use document shortcut in favicon script<commit_after>/**
 * Change favicon to show Logux synchronization status.
 *
 * @param {CrossTabClient} client Observed Client instance.
 * @param {object} [links] Set favicon links.
 * @param {string} [links.normal] Default favicon link. By default,
 *                                it will be taken from current favicon.
 * @param {string} [links.offline] Offline favicon link.
 * @param {string} [links.error] Error favicon link.
 *
 * @return {Function} Unbind favicon listener.
 *
 * @example
 * import favicon from 'logux-status/favicon'
 * favicon(client, {
 *   normal: '/favicon.ico',
 *   offline: '/offline.ico',
 *   error: '/error.ico'
 * })
 */
function favicon (client, links) {
  links = links || {}

  var normal = links.normal
  var offline = links.offline
  var error = links.error

  var unbind = []
  var doc = document
  var fav = false
  var prevFav = false

  function update () {
    if (client.connected && prevFav !== normal) {
      fav.href = prevFav = normal
    } else if (!client.connected && offline &&
               prevFav !== offline && prevFav !== error) {
      fav.href = prevFav = offline
    }
  }

  function setError () {
    if (error && prevFav !== error) {
      fav.href = prevFav = error
    }
  }

  if (typeof doc !== 'undefined') {
    fav = doc.querySelector('link[rel~="icon"]')

    if (typeof normal === 'undefined') {
      if (fav) {
        normal = fav.href
      } else {
        normal = ''
      }
    }

    if (!fav) {
      fav = doc.createElement('link')
      fav.rel = 'icon'
      fav.href = ''
      doc.head.appendChild(fav)
    }

    unbind.push(client.on('state', update))
    update()

    unbind.push(client.log.on('add', function (action) {
      if (action.type === 'logux/undo' && action.reason) setError()
    }))

    unbind.push(client.sync.on('error', function (err) {
      if (err.type !== 'timeout') setError()
    }))
  }

  return function () {
    for (var i = 0; i < unbind.length; i++) {
      unbind[i]()
    }
  }
}

module.exports = favicon
<|endoftext|>


<commit_before>var expect = require('expect.js');
var request = require('request');
var express = require('express');

var host = "http://localhost";
var dom = require('express-dom');

dom.settings.stall = 5000;
dom.settings.allow = 'all';
dom.settings.timeout = 10000;
dom.settings.console = true;

var renderPlugins = [
	dom.plugins.hide,
	dom.plugins.nomedia,
	dom.plugins.redirect,
	dom.plugins.referrer,
	dom.plugins.html
];

describe("Two-phase rendering", function suite() {
	this.timeout(3000);
	var server, port;

	before(function(done) {
		var app = express();
		app.set('views', __dirname + '/public');
		app.get(/\.(json|js|css|png|templates)$/, express.static(app.get('views')));
		app.get(/\/templates\/.+\.html$/, express.static(app.get('views')));
		app.get(/\.html$/, dom().load());

		server = app.listen(function(err) {
			if (err) console.error(err);
			port = server.address().port;
			done();
		});
	});

	after(function(done) {
		server.close();
		done();
	});

	it("should run build then setup", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/build.html'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				done(err);
			});
		});
	});

	it("should run route and imports", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/route.html?template=import'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built0")).to.be.greaterThan(0);
			expect(body.indexOf("your body0")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				done(err);
			});
		});
	});

});

<commit_msg>Do not hide on render test<commit_after>var expect = require('expect.js');
var request = require('request');
var express = require('express');

var host = "http://localhost";
var dom = require('express-dom');

dom.settings.stall = 5000;
dom.settings.allow = 'all';
dom.settings.timeout = 10000;
dom.settings.console = true;

var renderPlugins = [
	dom.plugins.redirect,
	dom.plugins.referrer,
	dom.plugins.html
];

describe("Two-phase rendering", function suite() {
	this.timeout(3000);
	var server, port;

	before(function(done) {
		var app = express();
		app.set('views', __dirname + '/public');
		app.get(/\.(json|js|css|png|templates)$/, express.static(app.get('views')));
		app.get(/\/templates\/.+\.html$/, express.static(app.get('views')));
		app.get(/\.html$/, dom().load());

		server = app.listen(function(err) {
			if (err) console.error(err);
			port = server.address().port;
			done();
		});
	});

	after(function(done) {
		server.close();
		done();
	});

	it("should run build then setup", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/build.html'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				done(err);
			});
		});
	});

	it("should run route and imports", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/route.html?template=import'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built0")).to.be.greaterThan(0);
			expect(body.indexOf("your body0")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				done(err);
			});
		});
	});

});

<|endoftext|>


<commit_before>var ws = {};
ws.activeProjectId ="";
ws.activeTaskId = "";
ws.activeNodesId = new Array();

// -- init
$(document).ready(
   function(){
      initLoadingDialog();
      // override forms 'onsubmit' attribute, in order to call loadingShow() before than ajax call
      $("form").each(function() {
            var onSubmitVal = $(this).attr("onsubmit");
            $(this).attr("onsubmit", "loadingShow(); "+onSubmitVal);
            });
   }
);

// -- active/unfold nodes handling functions
function saveOpenNodes(activeProject){
    ws.activeNodesId.length=0;
    if (activeProject!=="") ws.activeNodesId.push('project_'+activeProject);
    $('.collapsable').each(function(){if(this.getAttribute('id')) ws.activeNodesId.push(this.getAttribute('id'));});
  }

function loadOpenNodes(){
 for (var key in ws.activeNodesId)
  {
    if (document.getElementById(ws.activeNodesId[key]))
        document.getElementById(ws.activeNodesId[key]).setAttribute('class', 'collapsable');
    else ws.activeNodesId.splice(key,1);
  }
  if (ws.activeProjectId){
      if (document.getElementById(ws.activeProjectId))
          document.getElementById(ws.activeProjectId).setAttribute('class', 'collapsable');
      else ws.activeProjectId = '';
  }
  if (ws.activeTaskId) {
      if (document.getElementById(ws.activeTaskId))
          document.getElementById(ws.activeTaskId).setAttribute('class', 'collapsable active');
      else ws.activeTaskId = '';
  }
}

// -- display functions
function addLeaf(leaf, parent, desc)
{
          if (leaf){
             var leaf_ul = document.createElement("ul");
                 $(parent).append(leaf_ul);
             var leaf_li = document.createElement("li");
                 $(leaf_ul).append(leaf_li);
             var leaf_span = document.createElement("span");
                 $(leaf_span).addClass('file')
                 .text(desc + leaf)
                 $(leaf_li).append(leaf_span);
          }
}

function addAction(type, label, desc, action, parent, activeProject, enabled)
{
    var icon = getIcon(type);
    var action_button = document.createElement("button");
    if (enabled){
            $(action_button).click(function() {
                saveOpenNodes(activeProject);
                eval(action);
            })
            .addClass("action")
            .button({
                icons: {
                    primary: icon
                },
                label: label
            })

    } else {
            $(action_button).addClass('ui-icon ui-state-disabled '+icon);
    }
    $(action_button).attr("title",desc);
    $(parent).append(action_button);
}

function addDataSource(jsonDataSource,projectNode,projectName)
{
    var ds_ul = document.createElement("ul");
        $(projectNode).append(ds_ul);
    var ds_li = document.createElement("li");
        $(ds_li).attr("id",'datasource_'+projectName+'_'+jsonDataSource.name)
        .addClass('closed');
        $(ds_ul).append(ds_li);
    var ds_span = document.createElement("span");
        $(ds_span).addClass('source');
        $(ds_li).append(ds_span);

    var ds_label= document.createElement("span");
        $(ds_label).addClass('label')
        .text(jsonDataSource.name);
        $(ds_span).append(ds_label);

    var ds_actions = document.createElement("div");
        $(ds_actions).addClass('actions');
        $(ds_span).append(ds_actions);
        addAction('ds_edit', 'Edit', "Edit data source ","editSourceTask('"+projectName+"','"+ jsonDataSource.name+"')",ds_actions,projectName,true);
        addAction('delete','Remove',"Remove data source ","confirmDelete('removeSourceTask','"+projectName+"','"+jsonDataSource.name+"')",ds_actions,projectName,true);

    for(var p in jsonDataSource.params) {
      var param = jsonDataSource.params[p];
      addLeaf(param.value,ds_li, param.key + ': ');
    }
}

function addLinkingTask(jsonLinkingTask,projectNode,projectName)
{
    var lt_ul = document.createElement("ul");
        $(projectNode).append(lt_ul);
    var lt_li = document.createElement("li");
        $(lt_li).attr("id",'linkingtask_'+projectName+'_'+jsonLinkingTask.name)
        .addClass('closed');
        $(lt_ul).append(lt_li);
    var lt_span = document.createElement("span");
        $(lt_span).addClass('link');
        $(lt_li).append(lt_span);

    var lt_label = document.createElement("span");
        $(lt_label).addClass('label')
        .text(jsonLinkingTask.name);
        $(lt_span).append(lt_label);

    var lt_actions = document.createElement("div");
        $(lt_actions).addClass('actions');
        $(lt_span).append(lt_actions);
    addAction('link_edit', 'Metadata', "Edit metadata","editLinkingTask('"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);
    addAction('link_spec', 'Open', "Edit linking task","openLinkingTask('"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);
    addAction('delete', 'Remove',"Remove task","confirmDelete('removeLinkingTask','"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);

    addLeaf(jsonLinkingTask.source,lt_li, 'source: ');
    addLeaf(jsonLinkingTask.target,lt_li, 'target: ');
    addLeaf(jsonLinkingTask.sourceDataset,lt_li, 'source dataset: ');
    addLeaf(jsonLinkingTask.targetDataset,lt_li, 'target dataset: ');
    addLeaf(jsonLinkingTask.linkType,lt_li, 'link type: ');
}

// -- display the workspace as treeview
function updateWorkspace(obj){
        //var obj = jQuery.parseJSON('{"workspace": {   "project": [ {"name": "Project_1", "dataSource":[ {"name":"KEGG","url":"http://kegg.us"},{"name":"Wiki","url":"http://aba.com"}  ],  "linkingTask":[ {"name":"Gene","source":"KEGG","target":"Wiki","targetDataset":"rdf:type Wiki:Gene","sourceDataset":"rdf:type KEGG:gene"},{"name":"linkTask2","source":"KEGG","target":"Wiki"} ] }, {"name": "Project_2", "dataSource":[ {"name":"ABA","url":"http://aba.com"} ] }     ] } }');

        removeNodeById("div_tree");

        // root folder
        if (!document.getElementById("root-folder")){
            var rootFolder = document.createElement("div");
            $(rootFolder).attr("id",'root-folder');
            $("#content").append(rootFolder);
        }

        var proj_actions = document.createElement("div");
            $(proj_actions).addClass('actions');
            $("#content").append(proj_actions);

        // new project button
        if (!document.getElementById("newproject")) {
            var newProj = document.createElement("div");
            $(newProj).attr("id",'newproject');
            addAction('add', 'Project','Create new project',"createProject()",newProj,"",true);
            $(proj_actions).append(newProj);
        }

        // import project button
        if (!document.getElementById("import")) {
            var importProj = document.createElement("div");
            $(importProj).attr("id",'import');
            addAction('import','Import','Import a project',"importProject()",importProj,"",true);
            $(proj_actions).append(importProj);
         }

        var tree = document.createElement("div");
            tree.id = "div_tree";

        var root = document.createElement("ul");
            $(root).attr("id", 'tree')
            .addClass('filetree');
            $(tree).append(root);

        // for each project
        for (var p in obj.workspace.project) {
            var project = obj.workspace.project[p];
            var  proj = document.createElement("li");
                $(proj).addClass('closed')
                .attr("id",'project_'+project.name);
                $(root).append(proj);
                var proj_span = document.createElement("span");
                    $(proj_span).addClass('folder');
                    $(proj).append(proj_span);

                var proj_label = document.createElement("span");
                    $(proj_label).addClass('label')
                    .text(project.name);
                    $(proj_span).append(proj_label);

                var proj_actions = document.createElement("div");
                    $(proj_actions).addClass('actions');
                    $(proj_span).append(proj_actions);
                addAction('edit_prefixes', 'Prefixes','Edit Prefixes',"editPrefixes('"+project.name+"')",proj_actions,project.name,true);
                addAction('ds_add', 'Source','Add data source',"createSourceTask('"+project.name+"')",proj_actions,project.name,true);
                addAction('link_add', 'Task','Add linking task',"createLinkingTask('"+project.name+"')",proj_actions,project.name,true);
                addAction('add_linkspec', 'Link Spec', 'Add link specification', "addLinkSpecification('"+project.name+"')",proj_actions,project.name,true);
                addAction('export', 'Export','Export project',"exportProject('"+project.name+"')",proj_actions,project.name,true);
                addAction('delete', 'Remove','Remove project',"confirmDelete('removeProject','"+project.name+"','')",proj_actions,'',true);

             // display dataSource
            for (var d in obj.workspace.project[p].dataSource)
            {
                addDataSource(project.dataSource[d],proj,project.name);
            }

            // display linkingTask
            for (var l in obj.workspace.project[p].linkingTask)
            {
                addLinkingTask(project.linkingTask[l],proj,project.name);
            }
        }

        $("#content").append(tree);

        // uncollapse active project/task
        if(obj.workspace.activeProject){
             ws.activeProjectId = "project_"+obj.workspace.activeProject;
        }
        if(obj.workspace.activeTask)
            {
             var idPrefix = (obj.workspace.activeTaskType === "LinkingTask") ?  'linkingtask_' : 'datasource_';
             ws.activeTaskId = idPrefix+obj.workspace.activeProject+"_"+obj.workspace.activeTask;
            }
        if (ws.activeNodesId.length>0 || ws.activeTaskId || ws.activeProjectId)  loadOpenNodes();

        $("#tree").treeview();

        loadingHide();
    }

// - dialogs

// display loading bar
function loadingShow(){
  $("#loading-dialog").dialog("open");
}

function loadingHide(){
  $("#loading-dialog").dialog("close");
}

// init loading dialog
function initLoadingDialog(){
    $("#loading-dialog").dialog({
      title: 'Loading...',
      width: 330, height: 85,
      modal: true,
      resizable: false,
      closable: false,
      autoOpen: false,
      closeOnEscape: false,
      open: function(event, ui) { $(".ui-dialog-titlebar-close", $(this).parent()).hide();}
      });
    $("#loading-progressbar").progressbar({value: 100});
}

// init and display the proper delete confirm dialog
function confirmDelete(action,proj,res){
     var confirmDialog = document.createElement("div");
         $(confirmDialog).attr("title",'Delete')
         .attr("id",'dialog');
     var dialogText = document.createElement("p");
         $(dialogText).text("Delete resource: "+proj+" "+res);
         $(confirmDialog).append(dialogText);

     $("#content").append(confirmDialog);

     $("#dialog").dialog({width: 400,
         modal: true,
         resizable: false,
         buttons: {
         "Yes, delete it": function() {
            callAction(action,proj,res);
            $(this).dialog("close");
            loadingShow()},
         "Cancel": function() {$(this).dialog("close");}
        }
        });
}

// -- utils
function removeNodeById(nodeId)
{
   var node = document.getElementById(nodeId);
   if (node) node.parentNode.removeChild(node);
}

function getIcon(type){
    var icon;
    switch (type)
    {
        case 'add' : icon = "ui-icon-plus";  break;
        case 'edit_prefixes' : icon = "ui-icon-wrench";  break;
        case 'ds_add' : icon = "ui-icon-plus";  break;
        case 'ds_edit' : icon = "ui-icon-wrench";  break;
        case 'link_add' : icon = "ui-icon-plus";  break;
        case 'add_linkspec' : icon = "ui-icon-arrowthickstop-1-s";  break;
        case 'link_edit' : icon = "ui-icon-wrench";  break;
        case 'link_spec': icon = "ui-icon-shuffle"; break;
        case 'delete' : icon = "ui-icon-trash";  break;
        case 'import': icon = "ui-icon-arrowthickstop-1-s"; break;
        case 'export': icon = "ui-icon-arrowthick-1-ne"; break;
    }
    return icon;
}

function callAction(action,proj,res){
    // work-around : passing the action as string parameter -> the action would be invoked anyway
    switch (action)
        {
        case 'removeProject' :  removeProject(proj);  break;
        case 'removeSourceTask' :  removeSourceTask(proj,res);  break;
        case 'removeLinkingTask' : removeLinkingTask(proj,res); break;
        default : alert("Error: Action \'"+action+"\' not defined!");
        }
}
<commit_msg>Treeview cleanup<commit_after>var ws = {};
ws.activeProjectId ="";
ws.activeTaskId = "";
ws.activeNodesId = new Array();

// -- init
$(document).ready(
   function(){
      initLoadingDialog();
      // override forms 'onsubmit' attribute, in order to call loadingShow() before than ajax call
      $("form").each(function() {
            var onSubmitVal = $(this).attr("onsubmit");
            $(this).attr("onsubmit", "loadingShow(); "+onSubmitVal);
            });
   }
);

// -- active/unfold nodes handling functions
function saveOpenNodes(activeProject){
    ws.activeNodesId.length=0;
    if (activeProject!=="") ws.activeNodesId.push('project_'+activeProject);
    $('.collapsable').each(function(){if(this.getAttribute('id')) ws.activeNodesId.push(this.getAttribute('id'));});
  }

function loadOpenNodes(){
 for (var key in ws.activeNodesId)
  {
    if (document.getElementById(ws.activeNodesId[key]))
        document.getElementById(ws.activeNodesId[key]).setAttribute('class', 'collapsable');
    else ws.activeNodesId.splice(key,1);
  }
  if (ws.activeProjectId){
      if (document.getElementById(ws.activeProjectId))
          document.getElementById(ws.activeProjectId).setAttribute('class', 'collapsable');
      else ws.activeProjectId = '';
  }
  if (ws.activeTaskId) {
      if (document.getElementById(ws.activeTaskId))
          document.getElementById(ws.activeTaskId).setAttribute('class', 'collapsable active');
      else ws.activeTaskId = '';
  }
}

// -- display functions
function addLeaf(leaf, parent, desc)
{
          if (leaf){
             var leaf_ul = document.createElement("ul");
                 $(parent).append(leaf_ul);
             var leaf_li = document.createElement("li");
                 $(leaf_ul).append(leaf_li);
             var leaf_span = document.createElement("span");
                 $(leaf_span).addClass('file')
                 .text(desc + leaf)
                 $(leaf_li).append(leaf_span);
          }
}

function addAction(type, label, desc, action, parent, activeProject, enabled)
{
    var icon = getIcon(type);
    var action_button = document.createElement("button");
    if (enabled){
            $(action_button).click(function() {
                saveOpenNodes(activeProject);
                eval(action);
            })
            .addClass("action")
            .button({
                icons: {
                    primary: icon
                },
                label: label
            })

    } else {
            $(action_button).addClass('ui-icon ui-state-disabled '+icon);
    }
    $(action_button).attr("title",desc);
    $(parent).append(action_button);
}

function addDataSource(jsonDataSource,projectNode,projectName)
{
    var ds_ul = document.createElement("ul");
        $(projectNode).append(ds_ul);
    var ds_li = document.createElement("li");
        $(ds_li).attr("id",'datasource_'+projectName+'_'+jsonDataSource.name)
        .addClass('closed');
        $(ds_ul).append(ds_li);
    var ds_span = document.createElement("span");
        $(ds_span).addClass('source');
        $(ds_li).append(ds_span);

    var ds_label= document.createElement("span");
        $(ds_label).addClass('label')
        .text(jsonDataSource.name);
        $(ds_span).append(ds_label);

    var ds_actions = document.createElement("div");
        $(ds_actions).addClass('actions');
        $(ds_span).append(ds_actions);
        addAction('ds_edit', 'Edit', "Edit data source","editSourceTask('"+projectName+"','"+ jsonDataSource.name+"')",ds_actions,projectName,true);
    /*  addAction('delete','Remove',"Remove DataSource "+jsonDataSource.name,"confirmDelete('removeSourceTask','"+projectName+"','"+jsonDataSource.name+"')",ds_actions,projectName,true); */

    for(var p in jsonDataSource.params) {
      var param = jsonDataSource.params[p];
      addLeaf(param.value,ds_li, param.key + ': ');
    }
}

function addLinkingTask(jsonLinkingTask,projectNode,projectName)
{
    var lt_ul = document.createElement("ul");
        $(projectNode).append(lt_ul);
    var lt_li = document.createElement("li");
        $(lt_li).attr("id",'linkingtask_'+projectName+'_'+jsonLinkingTask.name)
        .addClass('closed');
        $(lt_ul).append(lt_li);
    var lt_span = document.createElement("span");
        $(lt_span).addClass('link');
        $(lt_li).append(lt_span);

    var lt_label = document.createElement("span");
        $(lt_label).addClass('label')
        .text(jsonLinkingTask.name);
        $(lt_span).append(lt_label);

    var lt_actions = document.createElement("div");
        $(lt_actions).addClass('actions');
        $(lt_span).append(lt_actions);
    addAction('link_edit', 'Metadata', "Edit metadata","editLinkingTask('"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);
    addAction('link_spec', 'Open', "Edit linking task","openLinkingTask('"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);
    addAction('delete', 'Remove',"Remove task","confirmDelete('removeLinkingTask','"+projectName+"','"+ jsonLinkingTask.name+"')",lt_actions,projectName,true);

    addLeaf(jsonLinkingTask.source,lt_li, 'source: ');
    addLeaf(jsonLinkingTask.target,lt_li, 'target: ');
    addLeaf(jsonLinkingTask.sourceDataset,lt_li, 'source dataset: ');
    addLeaf(jsonLinkingTask.targetDataset,lt_li, 'target dataset: ');
    addLeaf(jsonLinkingTask.linkType,lt_li, 'link type: ');
}

// -- display the workspace as treeview
function updateWorkspace(obj){
        //var obj = jQuery.parseJSON('{"workspace": {   "project": [ {"name": "Project_1", "dataSource":[ {"name":"KEGG","url":"http://kegg.us"},{"name":"Wiki","url":"http://aba.com"}  ],  "linkingTask":[ {"name":"Gene","source":"KEGG","target":"Wiki","targetDataset":"rdf:type Wiki:Gene","sourceDataset":"rdf:type KEGG:gene"},{"name":"linkTask2","source":"KEGG","target":"Wiki"} ] }, {"name": "Project_2", "dataSource":[ {"name":"ABA","url":"http://aba.com"} ] }     ] } }');

        removeNodeById("div_tree");

        // root folder
        if (!document.getElementById("root-folder")){
            var rootFolder = document.createElement("div");
            $(rootFolder).attr("id",'root-folder');
            $("#content").append(rootFolder);
        }

        var proj_actions = document.createElement("div");
            $(proj_actions).addClass('actions');
            $("#content").append(proj_actions);

        // new project button
        if (!document.getElementById("newproject")) {
            var newProj = document.createElement("div");
            $(newProj).attr("id",'newproject');
            addAction('add', 'Project','Create new project',"createProject()",newProj,"",true);
            $(proj_actions).append(newProj);
        }

        // // import project button
        // if (!document.getElementById("import")) {
        //    var importProj = document.createElement("div");
        //    $(importProj).attr("id",'import');
        //    addAction('import','Import','Import a project',"importProject()",importProj,"",true);
        //    $(proj_actions).append(importProj);
        // }

        var tree = document.createElement("div");
            tree.id = "div_tree";

        var root = document.createElement("ul");
            $(root).attr("id", 'tree')
            .addClass('filetree');
            $(tree).append(root);

        // for each project
        for (var p in obj.workspace.project) {
            var project = obj.workspace.project[p];
            var  proj = document.createElement("li");
                $(proj).addClass('closed')
                .attr("id",'project_'+project.name);
                $(root).append(proj);
                var proj_span = document.createElement("span");
                    $(proj_span).addClass('folder');
                    $(proj).append(proj_span);

                var proj_label = document.createElement("span");
                    $(proj_label).addClass('label')
                    .text(project.name);
                    $(proj_span).append(proj_label);

                var proj_actions = document.createElement("div");
                    $(proj_actions).addClass('actions');
                    $(proj_span).append(proj_actions);
                addAction('edit_prefixes', 'Prefixes','Edit Prefixes',"editPrefixes('"+project.name+"')",proj_actions,project.name,true);
                if (project.dataSource.length == 1) addAction('ds_add', 'Source','Add data source',"createSourceTask('"+project.name+"')",proj_actions,project.name,true);
                //    else addAction('ds_add', 'Source','Action disabled: a project can contain max two sources',"",proj_actions,project.name,false);
                addAction('link_add', 'Task','Add linking task',"createLinkingTask('"+project.name+"')",proj_actions,project.name,true);
                addAction('add_linkspec', 'Link Spec', 'Add link specification', "addLinkSpecification('"+project.name+"')",proj_actions,project.name,true);
             // addAction('export', 'Export','Export Project '+project.name,"exportProject('"+project.name+"')",proj_actions,project.name,true);
                addAction('delete', 'Remove','Remove project',"confirmDelete('removeProject','"+project.name+"','')",proj_actions,'',true);

             // display dataSource
            for (var d in obj.workspace.project[p].dataSource)
            {
                if (project.dataSource[d].name != "TARGET") addDataSource(project.dataSource[d],proj,project.name);
            }

            // display linkingTask
            for (var l in obj.workspace.project[p].linkingTask)
            {
                addLinkingTask(project.linkingTask[l],proj,project.name);
            }
        }

        $("#content").append(tree);

        // uncollapse active project/task
        if(obj.workspace.activeProject){
             ws.activeProjectId = "project_"+obj.workspace.activeProject;
        }
        if(obj.workspace.activeTask)
            {
             var idPrefix = (obj.workspace.activeTaskType === "LinkingTask") ?  'linkingtask_' : 'datasource_';
             ws.activeTaskId = idPrefix+obj.workspace.activeProject+"_"+obj.workspace.activeTask;
            }
        if (ws.activeNodesId.length>0 || ws.activeTaskId || ws.activeProjectId)  loadOpenNodes();

        $("#tree").treeview({animated:"fast"});

        loadingHide();
    }

// - dialogs

// display loading bar
function loadingShow(){
  $("#loading-dialog").dialog("open");
}

function loadingHide(){
  $("#loading-dialog").dialog("close");
}

// init loading dialog
function initLoadingDialog(){
    $("#loading-dialog").dialog({
      title: 'Loading...',
      width: 330, height: 85,
      modal: true,
      resizable: false,
      closable: false,
      autoOpen: false,
      closeOnEscape: false,
      open: function(event, ui) { $(".ui-dialog-titlebar-close", $(this).parent()).hide();}
      });
    $("#loading-progressbar").progressbar({value: 100});
}

// init and display the proper delete confirm dialog
function confirmDelete(action,proj,res){
     var confirmDialog = document.createElement("div");
         $(confirmDialog).attr("title",'Delete')
         .attr("id",'dialog');
     var dialogText = document.createElement("p");
         $(dialogText).text("Delete resource: "+proj+" "+res);
         $(confirmDialog).append(dialogText);

     $("#content").append(confirmDialog);

     $("#dialog").dialog({width: 400,
         modal: true,
         resizable: false,
         buttons: {
         "Yes, delete it": function() {
            callAction(action,proj,res);
            $(this).dialog("close");
            loadingShow() },
         "Cancel": function() {$(this).dialog("close");}
        }
        });
}

// -- utils
function removeNodeById(nodeId)
{
   var node = document.getElementById(nodeId);
   if (node) node.parentNode.removeChild(node);
}

function getIcon(type){
    var icon;
    switch (type)
    {
        case 'add' : icon = "ui-icon-plus";  break;
        case 'edit_prefixes' : icon = "ui-icon-wrench";  break;
        case 'ds_add' : icon = "ui-icon-plus";  break;
        case 'ds_edit' : icon = "ui-icon-wrench";  break;
        case 'link_add' : icon = "ui-icon-plus";  break;
        case 'link_edit' : icon = "ui-icon-wrench";  break;
        case 'link_spec': icon = "ui-icon-shuffle"; break;
        case 'delete' : icon = "ui-icon-trash";  break;
        case 'import': icon = "ui-icon-arrowthickstop-1-s"; break;
        case 'export': icon = "ui-icon-arrowthick-1-ne"; break;
        case 'add_linkspec' : icon = "ui-icon-arrowthickstop-1-s";  break;
    }
    return icon;
}

function callAction(action,proj,res){
    // work-around : passing the action as string parameter -> the action would be invoked anyway
    switch (action)
        {
        case 'removeProject' :  removeProject(proj);  break;
        case 'removeSourceTask' :  removeSourceTask(proj,res);  break;
        case 'removeLinkingTask' : removeLinkingTask(proj,res); break;
        default : alert("Error: Action \'"+action+"\' not defined!");
        }
}<|endoftext|>