<commit_before>'use strict';

define([
        'src/util/api',
        'src/util/ui',
        'superagent',
        'uri/URI',
        'lodash',
        'src/util/couchdbAttachments'
    ],
    function (API, ui, superagent, URI, _, CDB) {

        const defaultOptions = {
            messages: {}
        };

        const viewSearch = ['key', 'startkey', 'endkey'];
        const mandatoryOptions = ['url', 'database'];

        class Roc {
            constructor(opts) {
                for (var key in opts) {
                    if(opts.hasOwnProperty(key)) {
                        this[key] = opts[key];
                    }
                }

                for (let i=0; i<mandatoryOptions.length; i++) {
                    if(!this[mandatoryOptions[i]]) {
                        throw new Error(`${mandatoryOptions[i]} is a mandatory option`);
                    }
                }
                this.messages = this.messages || {};
                this.variables = {};

                this.requestUrl = new URI(opts.url);
                this.databaseUrl = this.requestUrl.directory(`${this.requestUrl.directory()}/db/${this.database}`).normalize().href();
                this.entryUrl = `${this.databaseUrl}entry`;
                this.__ready = Promise.resolve();
            }

            view(viewName, options) {
                options = createOptions(options);
                let requestUrl = new URI(`${this.databaseUrl}_view/${viewName}`);

                for (let i = 0; i < viewSearch.length; i++) {
                    if (options[viewSearch[i]]) {
                        requestUrl.addSearch(viewSearch[i], JSON.stringify(options[viewSearch[i]]));
                    }
                }

                requestUrl = requestUrl.normalize().href();

                return superagent.get(requestUrl)
                    .withCredentials()
                    .then(res => {
                        if (res && res.body && res.status == 200) {
                            if (options.varName) {
                                this.variables[options.varName] = {
                                    type: 'view',
                                    requestUrl,
                                    data: res.body
                                };
                                API.createData(options.varName, res.body);
                            }
                        }
                        return res.body;
                    })
                    .then(handleSuccess(this, options))
                    .catch(handleError(this, options));
            }

            document(uuid, options) {
                return this.get(uuid).then(doc => {
                    if (!doc) return;
                    if (options.varName) {
                        this.variables[options.varName] = {
                            type: 'document',
                            data: doc
                        };
                        API.createData(options.varName, doc);
                        return doc;
                    }
                });
            }

            get(entry, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options);
                    if (options.fromCache) {
                        return this._findByUuid(uuid);
                    } else {
                        return superagent.get(`${this.entryUrl}/${uuid}`)
                            .withCredentials()
                            .end()
                            .then(res => {
                                if (res.body && res.status == 200) {
                                    this._updateByUuid(uuid, res.body);
                                    return res.body;
                                }
                            }).catch(handleError(this, options));
                    }
                });
            }

            getById(id, options) {
                return this.__ready.then(() => {
                    options = createOptions(options);
                    var entry = this._findById(id);
                    if (!entry || options.fromCache) {
                        return entry;
                    }
                    return this.get(entry);
                }).catch(handleError(this, options));
            }

            create(entry, options) {
                options = createOptions(options);
                return this.__ready
                    .then(() => {
                        return superagent.post(this.entryUrl)
                            .withCredentials()
                            .send(entry)
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && (res.status == 200 || res.status == 201)) {
                            return this.get(res.body.id);
                        }
                    })
                    .then(entry => {
                        if (!entry) return;
                        for (var key in this.variables) {
                            this.variables[key].data.push(_.cloneDeep(entry));
                            this.variables[key].data.triggerChange();
                        }
                        return entry;
                    }).catch(handleError(this, options));
            }

            update(entry, options) {
                options = createOptions(options);
                // Todo force
                return this.__ready.then(() => {
                        return superagent.put(`${this.entryUrl}/${String(entry._id)}`)
                            .withCredentials()
                            .send(entry)
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && res.status == 200) {
                            entry._rev = res.body.rev;
                            this._updateByUuid(entry._id, entry);
                        }
                        return res.body;
                    }).catch(handleError(this, options));
            }

            removeAttachment(entry, attachments, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options);
                    if (Array.isArray(attachments) && attachments.length === 0) return this.getAttachmentList(entry);
                    const cdb = this._getCdb(uuid);
                    return cdb.remove(attachments)
                        .then(attachments => {
                            return this.get(uuid).then(data => {
                                console.log('got doc', data);
                                this._updateByUuid(uuid, data);
                                return attachments;
                            });
                        });
                }).catch(handleError(this, options));
            }

            getAttachment(entry, name) {
                return this.__ready.then(() => {
                    const uuid = getUuid(entry);
                    const cdb = this._getCdb(uuid);
                    return cdb.get(name);
                });
            }

            getAttachmentList(entry) {
                return this.__ready.then(() => {
                    const uuid = getUuid(entry);
                    const cdb = this._getCdb(uuid);
                    return cdb.list();
                });
            }

            addAttachment(entry, attachments, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options);
                    const cdb = this._getCdb(uuid);
                    return cdb.inlineUploads(attachments)
                        .then(attachments => {
                            return this.get(uuid).then(data => {
                                console.log('got doc add att', data);
                                this._updateByUuid(uuid, data);
                                return attachments;
                            });
                        });
                }).catch(handleError(this, options));
            }

            addAttachmentById(id, attachment, options) {
                options = createOptions(options);
                return this.__ready.then(() => {
                    var doc = this._findById(id);
                    if (!doc) return;
                    return this.addAttachment(doc._id, attachment);
                }).catch(handleError(this, options));
            }

            delete(entry, options) {
                return this.__ready.then(() => {
                        const uuid = getUuid(entry);
                        options = createOptions(options);
                        return superagent.del(`${this.entryUrl}/${uuid}`)
                            .withCredentials()
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && res.status == 200) {
                            for (let key in this.variables) {
                                const idx = this._findIndexByUuid(uuid, key);
                                if (idx !== -1) {
                                    this.variables[key].data.splice(idx, 1);
                                    this.variables[key].data.triggerChange();
                                }
                            }

                        }
                        return res.body;
                    }).catch(handleError(this, options));
            }

            remove(entry, options) {
                return this.delete(entry, options);
            }

            // Private
            _getCdb(uuid) {
                const docUrl = `${this.entryUrl}/${String(uuid)}`;
                return new CDB(docUrl);
            }

            _findByUuid(uuid, key) {
                if (key === undefined) {
                    var result;
                    // Return the first one found (they are all supposed to be the same...)
                    for (let key in this.variables) {
                        result = this._findByUuid(uuid, key);
                        if (result) return result;
                    }
                    return null;
                }

                if (!this.variables[key]) return null;
                return this.variables[key].data.find(entry => String(entry._id) === String(uuid));
            }

            _findById(id, key) {
                if (key === undefined) {
                    var result;
                    for (let key in this.variables) {
                        result = this._findById(id, key);
                        if (result) return result;
                    }
                    return null;
                }
                if (!this.variables[key]) return null;
                id = DataObject.resurrect(id);
                if (this.variables[key].type === 'document' && _.isEqual(DataObject.resurrect(this.variables[key].data.$id), id)) {
                    return this.variables[key].data;
                } else if (this.variables[key.type === 'view']) {
                    return this.variables[key].data.find(entry => _.isEqual(id, DataObject.resurrect(entry.$id)));
                }
                return null;
            }

            _findIndexByUuid(uuid, key) {
                if (!this.variables[key]) return -1;
                if (this.variables[key].type === 'document') {
                    return -1;
                }
                return this.variables[key].data.findIndex(entry => String(entry._id) === String(uuid));
            }

            _updateByUuid(uuid, data) {
                for (let key in this.variables) {
                    if (this.variables[key].type === 'view') {
                        const idx = this._findIndexByUuid(uuid, key);
                        if (idx !== -1) {
                            this.variables[key].data.setChildSync([idx], _.cloneDeep(DataObject.resurrect(data)));
                        }
                    } else if (this.variables[key].type === 'document') {
                        uuid = String(uuid);
                        const _id = this.variables[key].data._id;
                        if (uuid === _id) {
                            var newData = _.cloneDeep(DataObject.resurrect(data));
                            this.variables[key].data = newData;
                            API.createData(key, newData);
                        }
                    }
                }

            }
        }

        function createOptions(options) {
            if (options && options.message) {
                var messages = Object.assign({}, defaultOptions.message, options.messages);
            }
            options = Object.assign({}, defaultOptions, options);
            if (messages) options.messages = messages;
            return options;
        }

        function handleError(ctx, options) {
            return function (err) {
                if (err.status || err.timeout) { // error comes from superagent
                    handleSuperagentError(err, ctx, options);
                }
                // Propagate error
                throw err;
            };
        }

        function handleSuccess(ctx, options) {
            return function (data) {
                if (data.status) {
                    handleSuperagentSuccess(data, ctx, options);
                }
                return data;
            };
        }

        function handleSuperagentSuccess(data, ctx, options) {
            if (ctx.showNotifications) {
                const message = options.messages[data.status] || ctx.messages[data.status];
                if (message) {
                    ui.showNotification(message, 'success');
                }
            }
        }

        function handleSuperagentError(err, ctx, options) {
            if (ctx.showNotifications) {
                const message = options.messages[err.status] || ctx.messages[err.status];
                if (message) {
                    ui.showNotification(message, 'error');
                }
            }
        }

        function getUuid(entry) {
            var uuid;
            var type = DataObject.getType(entry);
            if (type === 'string') {
                uuid = entry;
            } else if (type === 'object') {
                uuid = entry._id;
            } else {
                throw new Error('Bad arguments');
            }
            return String(uuid);
        }

        return Roc;
    });

<commit_msg>Add default message by type<commit_after>'use strict';

define([
        'src/util/api',
        'src/util/ui',
        'superagent',
        'uri/URI',
        'lodash',
        'src/util/couchdbAttachments'
    ],
    function (API, ui, superagent, URI, _, CDB) {

        const defaultOptions = {
            messages: {
                200: 'OK',
                201: 'Created',
                202: 'Accepted',
                204: 'No content',
                400: 'Bad request',
                401: 'Unauthorized',
                409: 'Conflict',
                403: 'Forbidden',
                408: 'Request timeout',
                500: 'Internal server error',
                502: 'Bad gateway'
            }
        };

        const getTypes = ['get', 'getAttachment', 'getView'];

        const messagesByType = {
            get: {
                401: 'Unauthorized to get entry'
            },
            create: {
                200: 'Entry created',
                201: 'Entry created',
                401: 'Unauthorized to create entry'
            },
            update: {
                200: 'Entry updated',
                401: 'Unauthorized to update entry'
            },
            delete: {
                200: 'Entry deleted',
                401: 'Unauthorized to delete entry'
            },
            addAttachment: {
                200: 'Added attachment',
                401: 'Unauthorized to add attachment'
            },
            deleteAttachment: {
                200: 'Attachment deleted',
                401: 'Unauthorized to delete attachment'
            },
            getAttachment: {
                401: 'Unauthorized to get attachment'
            },
            getView: {
                401: 'Unauthorized to get view'
            }
        };

        for(let key in defaultOptions.messages) {
            // For get requests default is not to show any messages
            if(key < '300') {
                for(let i=0; i<getTypes.length; i++) {
                    messagesByType[getTypes[i]][key] = '';
                }
            }
        }

        const viewSearch = ['key', 'startkey', 'endkey'];
        const mandatoryOptions = ['url', 'database'];

        class Roc {
            constructor(opts) {
                for (var key in opts) {
                    if (opts.hasOwnProperty(key)) {
                        this[key] = opts[key];
                    }
                }

                for (let i = 0; i < mandatoryOptions.length; i++) {
                    if (!this[mandatoryOptions[i]]) {
                        throw new Error(`${mandatoryOptions[i]} is a mandatory option`);
                    }
                }
                this.messages = this.messages || {};
                this.variables = {};

                this.requestUrl = new URI(opts.url);
                this.databaseUrl = this.requestUrl.directory(`${this.requestUrl.directory()}/db/${this.database}`).normalize().href();
                this.entryUrl = `${this.databaseUrl}entry`;
                this.__ready = Promise.resolve();
            }

            view(viewName, options) {
                options = createOptions(options, 'getView');
                let requestUrl = new URI(`${this.databaseUrl}_view/${viewName}`);

                for (let i = 0; i < viewSearch.length; i++) {
                    if (options[viewSearch[i]]) {
                        requestUrl.addSearch(viewSearch[i], JSON.stringify(options[viewSearch[i]]));
                    }
                }

                requestUrl = requestUrl.normalize().href();

                return superagent.get(requestUrl)
                    .withCredentials()
                    .then(res => {
                        if (res && res.body && res.status == 200) {
                            if (options.varName) {
                                this.variables[options.varName] = {
                                    type: 'view',
                                    requestUrl,
                                    data: res.body
                                };
                                API.createData(options.varName, res.body);
                            }
                        }
                        return res.body;
                    })
                    .then(handleSuccess(this, options))
                    .catch(handleError(this, options));
            }

            document(uuid, options) {
                return this.get(uuid).then(doc => {
                    if (!doc) return;
                    if (options.varName) {
                        this.variables[options.varName] = {
                            type: 'document',
                            data: doc
                        };
                        API.createData(options.varName, doc);
                        return doc;
                    }
                });
            }

            get(entry, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options, 'get');
                    if (options.fromCache) {
                        return this._findByUuid(uuid);
                    } else {
                        return superagent.get(`${this.entryUrl}/${uuid}`)
                            .withCredentials()
                            .end()
                            .then(res => {
                                if (res.body && res.status == 200) {
                                    this._updateByUuid(uuid, res.body);
                                    return res.body;
                                }
                            }).catch(handleError(this, options));
                    }
                });
            }

            getById(id, options) {
                return this.__ready.then(() => {
                    options = createOptions(options, 'get');
                    var entry = this._findById(id);
                    if (!entry || options.fromCache) {
                        return entry;
                    }
                    return this.get(entry);
                }).catch(handleError(this, options));
            }

            create(entry, options) {
                options = createOptions(options, 'create');
                return this.__ready
                    .then(() => {
                        return superagent.post(this.entryUrl)
                            .withCredentials()
                            .send(entry)
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && (res.status == 200 || res.status == 201)) {
                            return this.get(res.body.id);
                        }
                    })
                    .then(entry => {
                        if (!entry) return;
                        for (var key in this.variables) {
                            this.variables[key].data.push(_.cloneDeep(entry));
                            this.variables[key].data.triggerChange();
                        }
                        return entry;
                    }).catch(handleError(this, options));
            }

            update(entry, options) {
                options = createOptions(options, 'update');
                return this.__ready.then(() => {
                        return superagent.put(`${this.entryUrl}/${String(entry._id)}`)
                            .withCredentials()
                            .send(entry)
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && res.status == 200) {
                            entry._rev = res.body.rev;
                            this._updateByUuid(entry._id, entry);
                        }
                        return res.body;
                    }).catch(handleError(this, options));
            }

            deleteAttachment(entry, attachments, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options, 'deleteAttachment');
                    if (Array.isArray(attachments) && attachments.length === 0) return this.getAttachmentList(entry);
                    const cdb = this._getCdb(uuid);
                    return cdb.remove(attachments)
                        .then(attachments => {
                            return this.get(uuid).then(data => {
                                console.log('got doc', data);
                                this._updateByUuid(uuid, data);
                                return attachments;
                            });
                        });
                }).catch(handleError(this, options));
            }

            removeAttachment(entry, attachments, options) {
                return this.deleteAttachment(entry, attachments, options);
            }

            getAttachment(entry, name, options) {
                return this.__ready.then(() => {
                    const uuid = getUuid(entry);
                    options = createOptions(options, 'getAttachment');
                    const cdb = this._getCdb(uuid);
                    return cdb.get(name);
                });
            }

            getAttachmentList(entry) {
                return this.__ready.then(() => {
                    const uuid = getUuid(entry);
                    const cdb = this._getCdb(uuid);
                    return cdb.list();
                });
            }

            addAttachment(entry, attachments, options) {
                return this.__ready.then(() => {
                    var uuid = getUuid(entry);
                    options = createOptions(options, 'addAttachment');
                    const cdb = this._getCdb(uuid);
                    return cdb.inlineUploads(attachments)
                        .then(attachments => {
                            return this.get(uuid).then(data => {
                                console.log('got doc add att', data);
                                this._updateByUuid(uuid, data);
                                return attachments;
                            });
                        });
                }).catch(handleError(this, options));
            }

            addAttachmentById(id, attachment, options) {
                options = createOptions(options, 'addAttachment');
                return this.__ready.then(() => {
                    var doc = this._findById(id);
                    if (!doc) return;
                    return this.addAttachment(doc._id, attachment);
                }).catch(handleError(this, options));
            }

            delete(entry, options) {
                return this.__ready.then(() => {
                        const uuid = getUuid(entry);
                        options = createOptions(options, 'delete');
                        return superagent.del(`${this.entryUrl}/${uuid}`)
                            .withCredentials()
                            .end();
                    })
                    .then(handleSuccess(this, options))
                    .then(res => {
                        if (res.body && res.status == 200) {
                            for (let key in this.variables) {
                                const idx = this._findIndexByUuid(uuid, key);
                                if (idx !== -1) {
                                    this.variables[key].data.splice(idx, 1);
                                    this.variables[key].data.triggerChange();
                                }
                            }

                        }
                        return res.body;
                    }).catch(handleError(this, options));
            }

            remove(entry, options) {
                return this.delete(entry, options);
            }

            // Private
            _getCdb(uuid) {
                const docUrl = `${this.entryUrl}/${String(uuid)}`;
                return new CDB(docUrl);
            }

            _findByUuid(uuid, key) {
                if (key === undefined) {
                    var result;
                    // Return the first one found (they are all supposed to be the same...)
                    for (let key in this.variables) {
                        result = this._findByUuid(uuid, key);
                        if (result) return result;
                    }
                    return null;
                }

                if (!this.variables[key]) return null;
                return this.variables[key].data.find(entry => String(entry._id) === String(uuid));
            }

            _findById(id, key) {
                if (key === undefined) {
                    var result;
                    for (let key in this.variables) {
                        result = this._findById(id, key);
                        if (result) return result;
                    }
                    return null;
                }
                if (!this.variables[key]) return null;
                id = DataObject.resurrect(id);
                if (this.variables[key].type === 'document' && _.isEqual(DataObject.resurrect(this.variables[key].data.$id), id)) {
                    return this.variables[key].data;
                } else if (this.variables[key.type === 'view']) {
                    return this.variables[key].data.find(entry => _.isEqual(id, DataObject.resurrect(entry.$id)));
                }
                return null;
            }

            _findIndexByUuid(uuid, key) {
                if (!this.variables[key]) return -1;
                if (this.variables[key].type === 'document') {
                    return -1;
                }
                return this.variables[key].data.findIndex(entry => String(entry._id) === String(uuid));
            }

            _updateByUuid(uuid, data) {
                for (let key in this.variables) {
                    if (this.variables[key].type === 'view') {
                        const idx = this._findIndexByUuid(uuid, key);
                        if (idx !== -1) {
                            this.variables[key].data.setChildSync([idx], _.cloneDeep(DataObject.resurrect(data)));
                        }
                    } else if (this.variables[key].type === 'document') {
                        uuid = String(uuid);
                        const _id = this.variables[key].data._id;
                        if (uuid === _id) {
                            var newData = _.cloneDeep(DataObject.resurrect(data));
                            this.variables[key].data = newData;
                            API.createData(key, newData);
                        }
                    }
                }

            }
        }

        function createOptions(options, type) {
            if (options && options.message) {
                var messages = Object.assign({}, defaultOptions.messages, messagesByType[type], options.messages);
            }
            options = Object.assign({}, defaultOptions, options);
            if (messages) options.messages = messages;
            return options;
        }

        function handleError(ctx, options) {
            return function (err) {
                if (err.status || err.timeout) { // error comes from superagent
                    handleSuperagentError(err, ctx, options);
                }
                // Propagate error
                throw err;
            };
        }

        function handleSuccess(ctx, options) {
            return function (data) {
                if (data.status) {
                    handleSuperagentSuccess(data, ctx, options);
                }
                return data;
            };
        }

        function handleSuperagentSuccess(data, ctx, options) {
            const message = options.messages[data.status] || ctx.messages[data.status];
            if (message && !options.disableNotification) {
                ui.showNotification(message, 'success');
            }
        }

        function handleSuperagentError(err, ctx, options) {
            const message = options.messages[err.status] || ctx.messages[err.status];
            if (message && !options.disableNotification) {
                ui.showNotification(message, 'error');
            }
        }

        function getUuid(entry) {
            var uuid;
            var type = DataObject.getType(entry);
            if (type === 'string') {
                uuid = entry;
            } else if (type === 'object') {
                uuid = entry._id;
            } else {
                throw new Error('Bad arguments');
            }
            return String(uuid);
        }

        return Roc;
    });

<|endoftext|>


<commit_before>var IS_AUTO_UPDATE = true;
var INTERVAL_ID;
var CHECK_INTERVAL = 15000;
var TO_CLIPBOARD = '';

/*
clickUpdateButton():
* click update button.
*/
function clickUpdateButton() {
  let wk_elm;
  wk_elm = document.getElementsByClassName('new-tweets-bar');
  if(wk_elm && wk_elm.length > 0) {
    wk_elm[0].click();
  }
}

function setTextForCopy() {
  console.log('setTextForCopy');
  let wk_elm;
  wk_elm = document.getElementById('permalink-overlay');
  console.log('setTextForCopy1');
  if(wk_elm &&
    (wk_elm.style === undefined
      || (wk_elm.style !== undefined && wk_elm.style.display === undefined)
      || wk_elm.style.display === 'block')) {
    console.log('go permalink0');
    wk_elm = wk_elm.getElementsByClassName('permalink-tweet-container');
    if(wk_elm && wk_elm.length > 0) {
      console.log('go permalink1');
      copyFromOverlay(wk_elm[0]);
    }
    return;
  }
  console.log('setTextForCopy2');
  wk_elm = document.getElementsByClassName('selected-stream-item');
  console.log('setTextForCopy3');
  if(wk_elm && wk_elm.length > 0) {
    console.log('go stream-item');
    copyFromOverlay(wk_elm[0]);
    return;
  }
}

function getQuoteTweetText(tgt_elm) {
  let ret = '';
  let wk_elm;
  wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-link');
  if(wk_elm && wk_elm.length > 0) {
    console.log('scrape1');
    let wk = ' ';
    wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-fullname');
    if(wk_elm && wk_elm.length > 0) {
      wk += wk_elm[0].textContent.trim() + ': ';
    }
    wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-text');
    if(wk_elm && wk_elm.length > 0) {
      wk += wk_elm[0].textContent.trim() + '';
    }
    ret += wk;
  }
  return ret;
}

function copyFromOverlay(tgt_elm) {
  let result = {};
  let wk_elm;
  wk_elm = tgt_elm.getElementsByClassName('tweet-timestamp');
  if(wk_elm && wk_elm.length > 0) {
    console.log(1);
    result.href = wk_elm[0].href.trim();
  }
  wk_elm = tgt_elm.getElementsByClassName('_timestamp');
  if(wk_elm && wk_elm.length > 0) {
    console.log(2);
    result.time = parseTweetTime(wk_elm[0].getAttribute('data-time-ms').trim());
  }
  wk_elm = tgt_elm.getElementsByClassName('fullname');
  if(wk_elm && wk_elm.length > 0) {
    console.log(3);
    result.fullname = wk_elm[0].textContent.trim();
  }
  wk_elm = tgt_elm.getElementsByClassName('tweet-text');
  if(wk_elm && wk_elm.length > 0) {
    console.log(4);
    result.text = wk_elm[0].textContent.trim();
    let quoteTweetText = getQuoteTweetText(tgt_elm);
    if(quoteTweetText !== '') {
      console.log('add quote');
      //result.text = result.text.replace(/(.+)(https:\/\/twitter\.com\/ … )$/, '$1');
      result.text = result.text.replace(/(.+)(https:\/\/twitter\.com\/.+)$/, '$1');
      result.text += quoteTweetText;
    }
  }
  //console.log(result);
  let result_text = '
' +
    result.time['year'] + '-' +
    result.time['month'] + '-' +
    result.time['day'] + ' ' +
    result.time['hour'] + ':' +
    result.time['minute'] + ' ' +
    result.fullname + ': ' +
    result.text + '
';
  TO_CLIPBOARD = result_text;
}

function parseTweetTime(milsec_txt) {
  let wk = new Date(parseInt(milsec_txt));
  let result = {};
  result.year = wk.getFullYear();
  result.month = ('00' + (wk.getMonth() + 1)).slice(-2);
  result.day = ('00' + wk.getDate()).slice(-2);
  result.hour = ('00' + wk.getHours()).slice(-2);
  result.minute = ('00' + wk.getMinutes()).slice(-2);
  return result;
}

function onCopy(ev) {
  console.log('onCopy start');
  console.log(TO_CLIPBOARD);
  if(window.getSelection().toString() === '') {
    setTextForCopy();
    console.log(TO_CLIPBOARD);
    if(TO_CLIPBOARD !== '') {
      ev.preventDefault();
      let transfer = ev.clipboardData;
      console.log('onCopy transfer');
      transfer.setData('text/plain', TO_CLIPBOARD);
      TO_CLIPBOARD = '';
    }
  }
}

function handleKeydown(ev) {
  var code = ev.keyCode;
  switch(code) {
    case 65: //0x41 A
      console.log(code + ':' + ev.ctrlKey);
      if(IS_AUTO_UPDATE === false) {
        INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
        browser.runtime.sendMessage({'badge':'on'});
        IS_AUTO_UPDATE = true;
      }
      break;
    case 81: //0x51 Q
      console.log(code + ':' + ev.ctrlKey);
      if(IS_AUTO_UPDATE) {
        clearInterval(INTERVAL_ID);
        browser.runtime.sendMessage({'badge':'off'});
        IS_AUTO_UPDATE = false;
      }
      break;
  }
};

function start() {
  console.log(window.location.href);
  document.addEventListener('keydown', handleKeydown);
  document.addEventListener('copy', onCopy);
  INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
};

start();

<commit_msg>failed to copy isolated tweet<commit_after>var IS_AUTO_UPDATE = true;
var INTERVAL_ID;
var CHECK_INTERVAL = 15000;
var TO_CLIPBOARD = '';

/*
clickUpdateButton():
* click update button.
*/
function clickUpdateButton() {
  let wk_elm;
  wk_elm = document.getElementsByClassName('new-tweets-bar');
  if(wk_elm && wk_elm.length > 0) {
    wk_elm[0].click();
  }
}

function setTextForCopy() {
  console.log('setTextForCopy');
  let wk_elm;
  wk_elm = document.getElementById('permalink-overlay');
  console.log('setTextForCopy1');
  if(wk_elm &&
    (wk_elm.style === undefined
      || (wk_elm.style !== undefined && wk_elm.style.display === undefined)
      || wk_elm.style.display === 'block'
      || wk_elm.style.opacity === 1)) {
    console.log('go permalink0');
    wk_elm = wk_elm.getElementsByClassName('permalink-tweet-container');
    if(wk_elm && wk_elm.length > 0) {
      console.log('go permalink1');
      copyFromOverlay(wk_elm[0]);
    }
    return;
  }
  console.log('setTextForCopy2');
  wk_elm = document.getElementsByClassName('selected-stream-item');
  console.log('setTextForCopy3');
  if(wk_elm && wk_elm.length > 0) {
    console.log('go stream-item');
    copyFromOverlay(wk_elm[0]);
    return;
  }
}

function getQuoteTweetText(tgt_elm) {
  let ret = '';
  let wk_elm;
  wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-link');
  if(wk_elm && wk_elm.length > 0) {
    console.log('scrape1');
    let wk = ' ';
    wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-fullname');
    if(wk_elm && wk_elm.length > 0) {
      wk += wk_elm[0].textContent.trim() + ': ';
    }
    wk_elm = tgt_elm.getElementsByClassName('QuoteTweet-text');
    if(wk_elm && wk_elm.length > 0) {
      wk += wk_elm[0].textContent.trim() + '';
    }
    ret += wk;
  }
  return ret;
}

function copyFromOverlay(tgt_elm) {
  let result = {};
  let wk_elm;
  wk_elm = tgt_elm.getElementsByClassName('tweet-timestamp');
  if(wk_elm && wk_elm.length > 0) {
    console.log(1);
    result.href = wk_elm[0].href.trim();
  }
  wk_elm = tgt_elm.getElementsByClassName('_timestamp');
  if(wk_elm && wk_elm.length > 0) {
    console.log(2);
    result.time = parseTweetTime(wk_elm[0].getAttribute('data-time-ms').trim());
  }
  wk_elm = tgt_elm.getElementsByClassName('fullname');
  if(wk_elm && wk_elm.length > 0) {
    console.log(3);
    result.fullname = wk_elm[0].textContent.trim();
  }
  wk_elm = tgt_elm.getElementsByClassName('tweet-text');
  if(wk_elm && wk_elm.length > 0) {
    console.log(4);
    result.text = wk_elm[0].textContent.trim();
    let quoteTweetText = getQuoteTweetText(tgt_elm);
    if(quoteTweetText !== '') {
      console.log('add quote');
      //result.text = result.text.replace(/(.+)(https:\/\/twitter\.com\/ … )$/, '$1');
      result.text = result.text.replace(/(.+)(https:\/\/twitter\.com\/.+)$/, '$1');
      result.text += quoteTweetText;
    }
  }
  //console.log(result);
  let result_text = '
' +
    result.time['year'] + '-' +
    result.time['month'] + '-' +
    result.time['day'] + ' ' +
    result.time['hour'] + ':' +
    result.time['minute'] + ' ' +
    result.fullname + ': ' +
    result.text + '
';
  TO_CLIPBOARD = result_text;
}

function parseTweetTime(milsec_txt) {
  let wk = new Date(parseInt(milsec_txt));
  let result = {};
  result.year = wk.getFullYear();
  result.month = ('00' + (wk.getMonth() + 1)).slice(-2);
  result.day = ('00' + wk.getDate()).slice(-2);
  result.hour = ('00' + wk.getHours()).slice(-2);
  result.minute = ('00' + wk.getMinutes()).slice(-2);
  return result;
}

function onCopy(ev) {
  console.log('onCopy start');
  console.log(TO_CLIPBOARD);
  if(window.getSelection().toString() === '') {
    setTextForCopy();
    console.log(TO_CLIPBOARD);
    if(TO_CLIPBOARD !== '') {
      ev.preventDefault();
      let transfer = ev.clipboardData;
      console.log('onCopy transfer');
      transfer.setData('text/plain', TO_CLIPBOARD);
      TO_CLIPBOARD = '';
    }
  }
}

function handleKeydown(ev) {
  var code = ev.keyCode;
  switch(code) {
    case 65: //0x41 A
      console.log(code + ':' + ev.ctrlKey);
      if(IS_AUTO_UPDATE === false) {
        INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
        browser.runtime.sendMessage({'badge':'on'});
        IS_AUTO_UPDATE = true;
      }
      break;
    case 81: //0x51 Q
      console.log(code + ':' + ev.ctrlKey);
      if(IS_AUTO_UPDATE) {
        clearInterval(INTERVAL_ID);
        browser.runtime.sendMessage({'badge':'off'});
        IS_AUTO_UPDATE = false;
      }
      break;
  }
};

function start() {
  console.log(window.location.href);
  document.addEventListener('keydown', handleKeydown);
  document.addEventListener('copy', onCopy);
  INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
};

start();

<|endoftext|>


<commit_before>$(document).ready(function(){
    var day_stats;
    var current_year_month = $('#date').html();

    var generate_stats_per_month = function(data){
        var chart_visits = new Array();
        var chart_page_impr = new Array();

        var path_stats = data["path_stats"];
        day_stats = data["day_stats"];

        var current_date = moment(current_year_month, "YYYYMM");
        var path_stats_html = "Stats for "+moment(current_date).format("MMMM YYYY")+":
";
        for (var i = 0; i < path_stats.length; i++) {
            path_stats_html+=path_stats[i]["num_visits"]+"x "+path_stats[i]["path"]+"
";
        }

        $("#month_stats").html(path_stats_html);

        for (var i = 0; i < day_stats.length; i++) {
            chart_visits.push([i+1, day_stats[i]["num_visits"]])
            chart_page_impr.push([i+1, day_stats[i]["num_page_impressions"]])
        }

        var dataset = [{
          label: "Page Impressions",
          data: chart_page_impr,
          lines: { show: false },
          color: "#8db9cc",
          bars: {
            show: true,
            barWidth: 0.8,
            align: "center",
            fill:1
          }
        },{
          label: "Visitors",
          data: chart_visits,
          lines: { show: false },
          color: "#14568a",
          bars: {
            show: true,
            barWidth: 0.4,
            align: "center",
            fill:1
          }
        }]

        var plot = $.plot(graph, dataset, {
          xaxis: {
            tickSize: 1
          },
          yaxis: {
            minTickSize: 5
          },
          grid: {
            clickable: true
          }
        });
    }

    var current_date = moment(current_year_month, "YYYYMM");
    $('#current_month').html(current_date.format("MMMM YYYY"));
    $('#prev').attr("href", "/stats/"+current_date.subtract("M", 1).format("YYYYMM"));
    $('#next').attr("href", "/stats/"+current_date.add("M", 2).format("YYYYMM"));

    $.getJSON( "/stats_per_month/"+current_year_month, generate_stats_per_month);

    $("#graph").bind("plotclick", function(event, pos, item){
      if (item){
        day = new Date(day_stats[item["dataIndex"]]["day"]["$date"]);

        $.getJSON("/stats_per_day/" + moment(day).format("YYYYMMDD"), function(data){
          var paths = "";
          for (i=0; i< data["path_stats"].length; i++){
            path_stats = data["path_stats"][i];
            paths+=path_stats["num_visits"]+"x "+path_stats["path"]+"
"
          }

          $("#day_stats").html("Stats for "+ moment(day).format("MMMM Do YYYY")+":
"+
            "Page Impressions: "+data["num_page_impressions"]+"
"+
            "Visitors: "+data["num_visits"]+"
"+
            "Raw Log Data

"+
            "Paths:
"+paths
          );
        })
      }
    })
});
<commit_msg>fix graph display for future months<commit_after>$(document).ready(function(){
    var day_stats;
    var current_year_month = $('#date').html();

    var generate_stats_per_month = function(data){
        var chart_visits = new Array();
        var chart_page_impr = new Array();
        var current_date = moment(current_year_month, "YYYYMM");
        day_stats = data["day_stats"];
        var path_stats = data["path_stats"];

        if(path_stats) {
            for (var i = 0; i < path_stats.length; i++) {
                path_stats_html+=path_stats[i]["num_visits"]+"x "+path_stats[i]["path"]+"
";
            }
            var path_stats_html = "Stats for "+moment(current_date).format("MMMM YYYY")+":
";
            $("#month_stats").html(path_stats_html);
        }

        for (var i = 0; i < day_stats.length; i++) {
            chart_visits.push([i+1, day_stats[i]["num_visits"]])
            chart_page_impr.push([i+1, day_stats[i]["num_page_impressions"]])
        }

        var dataset = [{
          label: "Page Impressions",
          data: chart_page_impr,
          lines: { show: false },
          color: "#8db9cc",
          bars: {
            show: true,
            barWidth: 0.8,
            align: "center",
            fill:1
          }
        },{
          label: "Visitors",
          data: chart_visits,
          lines: { show: false },
          color: "#14568a",
          bars: {
            show: true,
            barWidth: 0.4,
            align: "center",
            fill:1
          }
        }]

        var plot = $.plot(graph, dataset, {
          xaxis: {
            tickSize: 1
          },
          yaxis: {
            minTickSize: 5
          },
          grid: {
            clickable: true
          }
        });
    }

    var current_date = moment(current_year_month, "YYYYMM");
    $('#current_month').html(current_date.format("MMMM YYYY"));
    $('#prev').attr("href", "/stats/"+current_date.subtract("M", 1).format("YYYYMM"));
    $('#next').attr("href", "/stats/"+current_date.add("M", 2).format("YYYYMM"));

    $.getJSON( "/stats_per_month/"+current_year_month, generate_stats_per_month);

    $("#graph").bind("plotclick", function(event, pos, item){
      if (item){
        day = new Date(day_stats[item["dataIndex"]]["day"]["$date"]);

        $.getJSON("/stats_per_day/" + moment(day).format("YYYYMMDD"), function(data){
          var paths = "";
          for (i=0; i< data["path_stats"].length; i++){
            path_stats = data["path_stats"][i];
            paths+=path_stats["num_visits"]+"x "+path_stats["path"]+"
"
          }

          $("#day_stats").html("Stats for "+ moment(day).format("MMMM Do YYYY")+":
"+
            "Page Impressions: "+data["num_page_impressions"]+"
"+
            "Visitors: "+data["num_visits"]+"
"+
            "Raw Log Data

"+
            "Paths:
"+paths
          );
        })
      }
    })
});
<|endoftext|>


<commit_before>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * [-replace-name-] function
 *
 * [-replace-description-]
 *
 **************************************************************************************************************************************************************/

import React from 'react';

const AU[-replace-name-capital-] = () => (

		Yay!

);

export default AU[-replace-name-capital-];
<commit_msg>Update react template<commit_after>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * [-replace-name-] function
 *
 * [-replace-description-]
 *
 **************************************************************************************************************************************************************/

import React from 'react';
import PropTypes from 'prop-types';

const AU[-replace-name-capital-] = () => (

		Yay!

);

AU[-replace-name-capital-].propTypes = {
	dark: PropTypes.bool
};

AU[-replace-name-capital-].defaultProps = {};

export default AU[-replace-name-capital-];
<|endoftext|>


<commit_before>// NPM dependencies
var $ = require('jquery')
var remodal = require('remodal')
var Flickity = require('flickity')
var simpleBar = require('simplebar')
var A11yDialog = require('a11y-dialog')

// Custom JS
var Flatpickr = require('flatpickr')
var dateTimePicker = require('imports?Flatpickr=flatpickr!./dateTimePicker')
var a11y = require('imports?$=jquery!./a11y')
var nav = require('imports?$=jquery!./nav')
var articleNav = require('imports?$=jquery!./articleNav')
var smoothScroll = require('imports?$=jquery!./smoothScroll')
var gallery = require('./gallery')
var backToTopHandler = require('imports?$=jquery!./backToTop')
var search = require('imports?$=jquery!./search')
var swipers = require('imports?$=jquery!./swipers')
var wizard = require('imports?$=jquery,Flickity=flickity!./wizard')
var modals = require('imports?A11yDialog=a11y-dialog!./modals')<commit_msg>WIP Temporarily disable timepicker<commit_after>// NPM dependencies
var $ = require('jquery')
var remodal = require('remodal')
var Flickity = require('flickity')
var simpleBar = require('simplebar')
var A11yDialog = require('a11y-dialog')

// Custom JS
var a11y = require('imports?$=jquery!./a11y')
var nav = require('imports?$=jquery!./nav')
var articleNav = require('imports?$=jquery!./articleNav')
var smoothScroll = require('imports?$=jquery!./smoothScroll')
var gallery = require('./gallery')
var backToTopHandler = require('imports?$=jquery!./backToTop')
var search = require('imports?$=jquery!./search')
var swipers = require('imports?$=jquery!./swipers')
var wizard = require('imports?$=jquery,Flickity=flickity!./wizard')
var modals = require('imports?A11yDialog=a11y-dialog!./modals')
// var Flatpickr = require('flatpickr')
// var dateTimePicker = require('imports?Flatpickr=flatpickr!./dateTimePicker')<|endoftext|>


<commit_before>let IS_AUTO_UPDATE = true;
let INTERVAL_ID;
const CHECK_INTERVAL = 15000;

if(typeof browser === 'undefined') {
  window.browser = window.chrome;
}

const updatePageAction = () => {
  browser.runtime.sendMessage({task:'setIcon', icon: IS_AUTO_UPDATE});
};

/*
clickUpdateButton():
* click update button.
*/
const clickUpdateButton = () => {
  const wk_elm = document.getElementsByClassName('new-tweets-bar');
  if(wk_elm && wk_elm.length > 0) {
    wk_elm[0].click();
  }
};

const preventKeydown = (evt) => {
  if(evt.target.isContentEditable
    || evt.target.nodeName.toUpperCase() === 'INPUT'
    || evt.target.nodeName.toUpperCase() === 'TEXTAREA') {
    return;
  }
  evt.preventDefault();
};

const adjustScrollPos = () => {
  //#page-container > div.ProfileCanopy.ProfileCanopy--withNav.ProfileCanopy--large.js-variableHeightTopBar > div > div.ProfileCanopy-header.u-bgUserColor
  console.log('do');
  const header = document.querySelector('#page-container > div.ProfileCanopy.ProfileCanopy--withNav.ProfileCanopy--large.js-variableHeightTopBar > div > div.ProfileCanopy-header.u-bgUserColor');
  header.style.height = '280px';
  const selectedItem = document.getElementsByClassName('selected-stream-item');
  selectedItem[0].scrollIntoView();
};

const handleKeydown = (evt) => {
  switch(evt.key) {
    case 'a':
      if(IS_AUTO_UPDATE === false) {
        INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
        IS_AUTO_UPDATE = true;
        updatePageAction();
      }
      break;
    //case 'b':
    //  preventKeydown(evt);
    //  break;
    case 'k':
      adjustScrollPos();
      break;
    case 'q':
      if(IS_AUTO_UPDATE) {
        clearInterval(INTERVAL_ID);
        IS_AUTO_UPDATE = false;
        updatePageAction();
      }
      break;
    //case 'u':
    //  preventKeydown(evt);
    //  break;
  }
};

const start = () => {
  console.debug(window.location.href);
  updatePageAction();
  //DOMContentLoaded and load Event can be listend on capturing phase. not bubbling phase.
  document.addEventListener('keydown', handleKeydown);
  INTERVAL_ID = setInterval(clickUpdateButton, CHECK_INTERVAL);
};

start();

// vim:expandtab ff=dos fenc=utf-8 sw=2
<commit_msg>refactor: content script<commit_after>let IS_AUTO_UPDATE = true;
let INTERVAL_ID;
const CHECK_INTERVAL = 15000;

if(typeof browser === 'undefined') {
  window.browser = window.chrome;
}

const pptw = {

  adjustScrollPos : () => {
    //#page-container > div.ProfileCanopy.ProfileCanopy--withNav.ProfileCanopy--large.js-variableHeightTopBar > div > div.ProfileCanopy-header.u-bgUserColor
    console.log('do');
    const header = document.querySelector('#page-container > div.ProfileCanopy.ProfileCanopy--withNav.ProfileCanopy--large.js-variableHeightTopBar > div > div.ProfileCanopy-header.u-bgUserColor');
    header.style.height = '280px';
    const selectedItem = document.getElementsByClassName('selected-stream-item');
    selectedItem[0].scrollIntoView();
  },

  clickUpdateButton : () => {
    const wk_elm = document.getElementsByClassName('new-tweets-bar');
    if(wk_elm && wk_elm.length > 0) {
      wk_elm[0].click();
    }
  },

  handleKeydown : (evt) => {
    switch(evt.key) {
      case 'a':
        if(IS_AUTO_UPDATE === false) {
          INTERVAL_ID = setInterval(pptw.clickUpdateButton, CHECK_INTERVAL);
          IS_AUTO_UPDATE = true;
          pptw.updatePageAction();
        }
        break;
      case 'b':
        pptw.preventKeydown(evt);
        break;
      case 'k':
        pptw.adjustScrollPos();
        break;
      case 'q':
        if(IS_AUTO_UPDATE) {
          clearInterval(INTERVAL_ID);
          IS_AUTO_UPDATE = false;
          pptw.updatePageAction();
        }
        break;
      case 'u':
        pptw.preventKeydown(evt);
        break;
    }
  },

  preventKeydown : (evt) => {
    if(evt.target.isContentEditable
      || evt.target.nodeName.toUpperCase() === 'INPUT'
      || evt.target.nodeName.toUpperCase() === 'TEXTAREA') {
      return;
    }
    evt.preventDefault();
  },

  updatePageAction : () => {
    browser.runtime.sendMessage({task:'setIcon', icon: IS_AUTO_UPDATE});
  },

};

const start = () => {
  console.debug(window.location.href);
  pptw.updatePageAction();
  document.addEventListener('keydown', pptw.handleKeydown);
  INTERVAL_ID = setInterval(pptw.clickUpdateButton, CHECK_INTERVAL);
};

start();

// vim:expandtab ff=dos fenc=utf-8 sw=2
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

/* eslint-disable import/no-commonjs, import/unambiguous, import/newline-after-import */
/* global module:false */

const path = require('path');
const process = require('process');
const glob = require('glob');
const merge = require('webpack-merge');
const _ = require('lodash');

const config = require(path.join(process.env.INDICO_PLUGIN_ROOT, 'webpack-build-config'));
const bundles = require(path.join(process.env.INDICO_PLUGIN_ROOT, 'webpack-bundles'));
const base = require(path.join(config.build.indicoSourcePath, 'webpack'));

const entry = bundles.entry || {};
if (!_.isEmpty(config.themes)) {
    Object.assign(entry, base.getThemeEntryPoints(config, './themes/'));
}

function generateModuleAliases() {
    return glob.sync(path.join(config.indico.build.rootPath, 'modules/**/module.json')).map(file => {
        const mod = {produceBundle: true, partials: {}, ...require(file)};
        const dirName = path.join(path.dirname(file), 'client/js');
        const modulePath = path.join('indico/modules', mod.parent || '', mod.name);
        return {
            name: modulePath,
            alias: dirName,
            onlyModule: false
        };
    });
}

module.exports = (env) => {
    return merge.strategy({
        'resolve.alias': 'prepend'
    })(base.webpackDefaults(env, config, bundles), {
        entry,
        externals: {
            jquery: 'jQuery'
        },
        module: {
            rules: [
                {
                    test: /.*\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/,
                    use: {
                        loader: 'file-loader'
                    }
                }
            ]
        },
        resolve: {
            alias: generateModuleAliases()
        },
        output: {
            jsonpFunction: 'pluginJsonp'
        }
    });
};
<commit_msg>Blacklist plugin themes from webpack optimization<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

/* eslint-disable import/no-commonjs, import/unambiguous, import/newline-after-import */
/* global module:false */

const path = require('path');
const process = require('process');
const glob = require('glob');
const merge = require('webpack-merge');
const _ = require('lodash');

const config = require(path.join(process.env.INDICO_PLUGIN_ROOT, 'webpack-build-config'));
const bundles = require(path.join(process.env.INDICO_PLUGIN_ROOT, 'webpack-bundles'));
const base = require(path.join(config.build.indicoSourcePath, 'webpack'));

const entry = bundles.entry || {};
const allThemeFiles = [];

if (!_.isEmpty(config.themes)) {
    const themeFiles = base.getThemeEntryPoints(config, './themes/');
    Object.assign(entry, themeFiles);
    allThemeFiles.push(...Object.values(themeFiles).reduce((acc, current) => acc.concat(current)));
}

function generateModuleAliases() {
    return glob.sync(path.join(config.indico.build.rootPath, 'modules/**/module.json')).map(file => {
        const mod = {produceBundle: true, partials: {}, ...require(file)};
        const dirName = path.join(path.dirname(file), 'client/js');
        const modulePath = path.join('indico/modules', mod.parent || '', mod.name);
        return {
            name: modulePath,
            alias: dirName,
            onlyModule: false
        };
    });
}

module.exports = (env) => {
    return merge.strategy({
        'resolve.alias': 'prepend'
    })(base.webpackDefaults(env, config, bundles), {
        entry,
        externals: {
            jquery: 'jQuery'
        },
        module: {
            rules: [
                {
                    test: /.*\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/,
                    use: {
                        loader: 'file-loader'
                    }
                }
            ]
        },
        resolve: {
            alias: generateModuleAliases()
        },
        output: {
            jsonpFunction: 'pluginJsonp'
        },
        optimization: {
            splitChunks: {
                cacheGroups: {
                    common: module => {
                        return ({
                            name: 'common',
                            chunks: 'initial',
                            // exclude themes, like we do in the core webpack config
                            minChunks: allThemeFiles.includes(module.resource) ? 9999 : 2
                        });
                    }
                }
            }
        }
    });
};
<|endoftext|>


<commit_before>import { server as config } from './config';
import express from 'express';
import bodyParser from 'body-parser';
import serveStatic from 'serve-static';
import cors from 'cors';
import util from './lib/util';
import NotifyCondition from './lib/fiware/NotifyCondition';
import ContextBroker from './lib/fiware/ContextBroker';

// setup context broker
const contextBroker = new ContextBroker({
	url: config.brokerUrl
});

// create APP
const app = express();

// allow cors from all requests
app.use(cors());

// use json body parser
app.use(bodyParser.json());

// serve static files from apps
app.use(serveStatic('apps', {
	index: 'index.html'
}));

// provide some helpful information on default route
app.get('/', (req, res) => {
	logRequest(req);

	res.send(`

Fiware test server

Supported methods

				GET /
				- displays this help information

				GET /setup
				- setups test data for empty context broker

				PUT /update/:entity/:attribute
			- updates given entity attribute with value defined in body json "value"

				GET /info/:id
				- displays entity info

				POST /mirror
				- renders requested JSON request in response and in console

				POST /aggregate/:valueAttributeName/:historyAttributeName/:maxHistoryEntries
				- aggregates changed values to an array of last values

Examples

				GET /setup
				- creates the initial test entity or resets it if already exists

				PUT /update/lab/brightness {"value": 50}
				- updates lab brightness to 50 percent

				GET /info/lab
				- display lab information

Apps

				GET /chart
				- displays live brightness chart from FIWARE, updated by a wireless Arduino YUN device.

	`);
});

// sets up the test data
app.get('/setup', (req, res) => {
	logRequest(req);

	const id = 'lab';
	const type = 'room';
	const attributes = [{
		name: 'brightness',
		type: 'float',
		value: '0'
	}, {
		name: 'brightness-history',
		type: 'array',
		value: []
	}, {
		name: 'brightness-count',
		type: 'number',
		value: '0'
	}, {
		name: 'last-updated',
		type: 'date',
		value: util.getIsoDate()
	}];

	contextBroker
		.createEntity(id, type, attributes)
		.then(handleQueryResponse())

		.then(contextBroker.createSubscription({
			entities: [{
				type: type,
				isPattern: false,
				id: id
			}],
			attributes: [
				'brightness',
				'brightness-history',
				'brightness-count',
				'last-updated'
			],
			reference: 'http://localhost:1028/aggregate/brightness',
			duration: 'P1M',
			notifyConditions: [{
				type: NotifyCondition.ONCHANGE,
				condValues: ['brightness', 'last-updated']
			}],
			// throttling: 'PT60S'
			throttling: 'PT1S'
		}))
		.then(handleQueryResponse(req, res))

		.catch(handleQueryError(req, res));
});

// provide test method
app.get('/info/:id', (req, res) => {
	logRequest(req);

	const id = req.params.id;

	contextBroker.fetchEntity(id)
		.then(handleQueryResponse(req, res))
		.catch(handleQueryError(req, res));
});

// update given entity attribute
app.put('/update/:entity/:attribute', (req, res) => {
	logRequest(req);

	const entity = req.params.entity;
	const attribute = req.params.attribute;
	const value = req.body.value;

	// contextBroker.updateEntityAttribute(entity, attribute, value)
	contextBroker.updateEntityAttributes(entity, {
		[attribute]: value,
		['last-updated']: util.getIsoDate()
	})
		.then(handleQueryResponse(req, res))
		.catch(handleQueryError(req, res));
});

// aggregates entity values
app.post('/aggregate/:valueAttributeName', (req, res) => {
	logRequest(req);

	const valueAttributeName = req.params.valueAttributeName;
	const historyAttributeName = valueAttributeName + '-history';
	const countAttributeName = valueAttributeName + '-count';
	const maxHistoryEntries = 1080; // save one every 60 seconds for a 7 day long history

	const info = req.body;

	info.contextResponses.forEach((contextResponse) => {
		const contextElement = contextResponse.contextElement;
		const attributes = contextElement.attributes;
		const valueAttribute = findAttribute(valueAttributeName, attributes, true);
		const historyAttribute = findAttribute(historyAttributeName, attributes, true);
		const countAttribute = findAttribute(countAttributeName, attributes, true);

		// add new value
		historyAttribute.value.push([util.getIsoDate(), valueAttribute.value]);

		// increment counter
		countAttribute.value = Number.parseInt(countAttribute.value, 10) + 1;

		// limit to last maxHistoryEntries values
		while (historyAttribute.value.length > maxHistoryEntries) {
			historyAttribute.value.shift();
		}

		// update entity attributes
		contextBroker.updateEntityAttributes(contextElement.id, {
			[historyAttributeName]: historyAttribute.value,
			[countAttributeName]: countAttribute.value
		})
			.then(handleQueryResponse(req, res))
			.catch(handleQueryError(req, res));
	});
});

// accept POST request and just mirror the data back
app.post('/mirror', (req, res) => {
	logRequest(req);

	res.send(formatJsonResponse('got request', req.body));
});

// start the server
app.listen(config.port, () => {
	console.log('server started on port ' + config.port);
});

// logs the request info to console
function logRequest(req) {
	console.log(req.method + ' ' + req.url + '\n' + JSON.stringify(req.body, null, '  ') + '\n\n');
}

// handles query response
function handleQueryResponse(req, res) {
	return (response) => {
		if (res) {
			res.json(response);
		}

		return response;
	};
}

// handles query error
function handleQueryError(req, res) {
	return (response) => {
		if (res) {
			res.json(response);
		}

		return response;
	};
}

// formats JSON response to HTML
function formatJsonResponse(name, response) {
	const responseText = JSON.stringify(response, null, '\t');

	return `

${name}

${responseText}

	`;
}

// searches for an attribute from an array of attributes by name, returns null if not found
function findAttribute(name, attributes, isRequired = false) {
	const attribute = attributes.find((item) => item.name === name);

	if (!attribute) {
		if (isRequired) {
			throw new Error('Attribute called "' + name + '" could not be found in ' + JSON.stringify(attributes));
		}

		return null;
	}

	return parseAttribute(attribute);
}

// parses attribute value by type
function parseAttribute(attribute) {
	switch (attribute.type) {
		case 'integer':
			attribute.value = Number.parseInt(attribute.value, 10);

			if (Number.isNaN(attribute.value)) {
				console.error('parsing "' + attribute.value + '" as an integer failed, using zero');

				attribute.value = 0;
			}

			break;

		case 'float':
			attribute.value = Number.parseFloat(attribute.value);

			if (Number.isNaN(attribute.value)) {
				console.error('parsing "' + attribute.value + '" as a float failed, using zero');

				attribute.value = 0;
			}

			break;

		case 'array':
			if (typeof attribute.value === 'string') {
				try {
					attribute.value = JSON.parse(attribute.value);
				} catch (e) {
					console.error('parsing "' + attribute.value + '" as an array failed, using empty array');

					attribute.value = [];
				}
			} else if (Array.isArray(attribute.value)) {
				// don't change anything if already an array
			} else {
				console.error('attribute "' + attribute.value + '" is not a string to parse, using empty array');

				attribute.value = [];
			}
			break;

		default:
			// do not change anything
	}

	return attribute;
}<commit_msg>Providing initial value for brightness history.<commit_after>import { server as config } from './config';
import express from 'express';
import bodyParser from 'body-parser';
import serveStatic from 'serve-static';
import cors from 'cors';
import util from './lib/util';
import NotifyCondition from './lib/fiware/NotifyCondition';
import ContextBroker from './lib/fiware/ContextBroker';

// setup context broker
const contextBroker = new ContextBroker({
	url: config.brokerUrl
});

// create APP
const app = express();

// allow cors from all requests
app.use(cors());

// use json body parser
app.use(bodyParser.json());

// serve static files from apps
app.use(serveStatic('apps', {
	index: 'index.html'
}));

// provide some helpful information on default route
app.get('/', (req, res) => {
	logRequest(req);

	res.send(`

Fiware test server

Supported methods

				GET /
				- displays this help information

				GET /setup
				- setups test data for empty context broker

				PUT /update/:entity/:attribute
			- updates given entity attribute with value defined in body json "value"

				GET /info/:id
				- displays entity info

				POST /mirror
				- renders requested JSON request in response and in console

				POST /aggregate/:valueAttributeName/:historyAttributeName/:maxHistoryEntries
				- aggregates changed values to an array of last values

Examples

				GET /setup
				- creates the initial test entity or resets it if already exists

				PUT /update/lab/brightness {"value": 50}
				- updates lab brightness to 50 percent

				GET /info/lab
				- display lab information

Apps

				GET /chart
				- displays live brightness chart from FIWARE, updated by a wireless Arduino YUN device.

	`);
});

// sets up the test data
app.get('/setup', (req, res) => {
	logRequest(req);

	const id = 'lab';
	const type = 'room';
	const attributes = [{
		name: 'brightness',
		type: 'float',
		value: '0'
	}, {
		name: 'brightness-history',
		type: 'array',
		value: [0]
	}, {
		name: 'brightness-count',
		type: 'number',
		value: '0'
	}, {
		name: 'last-updated',
		type: 'date',
		value: util.getIsoDate()
	}];

	contextBroker
		.createEntity(id, type, attributes)
		.then(handleQueryResponse())

		.then(contextBroker.createSubscription({
			entities: [{
				type: type,
				isPattern: false,
				id: id
			}],
			attributes: [
				'brightness',
				'brightness-history',
				'brightness-count',
				'last-updated'
			],
			reference: 'http://localhost:1028/aggregate/brightness',
			duration: 'P1M',
			notifyConditions: [{
				type: NotifyCondition.ONCHANGE,
				condValues: ['brightness', 'last-updated']
			}],
			// throttling: 'PT60S'
			throttling: 'PT1S'
		}))
		.then(handleQueryResponse(req, res))

		.catch(handleQueryError(req, res));
});

// provide test method
app.get('/info/:id', (req, res) => {
	logRequest(req);

	const id = req.params.id;

	contextBroker.fetchEntity(id)
		.then(handleQueryResponse(req, res))
		.catch(handleQueryError(req, res));
});

// update given entity attribute
app.put('/update/:entity/:attribute', (req, res) => {
	logRequest(req);

	const entity = req.params.entity;
	const attribute = req.params.attribute;
	const value = req.body.value;

	// contextBroker.updateEntityAttribute(entity, attribute, value)
	contextBroker.updateEntityAttributes(entity, {
		[attribute]: value,
		['last-updated']: util.getIsoDate()
	})
		.then(handleQueryResponse(req, res))
		.catch(handleQueryError(req, res));
});

// aggregates entity values
app.post('/aggregate/:valueAttributeName', (req, res) => {
	logRequest(req);

	const valueAttributeName = req.params.valueAttributeName;
	const historyAttributeName = valueAttributeName + '-history';
	const countAttributeName = valueAttributeName + '-count';
	const maxHistoryEntries = 1080; // save one every 60 seconds for a 7 day long history

	const info = req.body;

	info.contextResponses.forEach((contextResponse) => {
		const contextElement = contextResponse.contextElement;
		const attributes = contextElement.attributes;
		const valueAttribute = findAttribute(valueAttributeName, attributes, true);
		const historyAttribute = findAttribute(historyAttributeName, attributes, true);
		const countAttribute = findAttribute(countAttributeName, attributes, true);

		// add new value
		historyAttribute.value.push([util.getIsoDate(), valueAttribute.value]);

		// increment counter
		countAttribute.value = Number.parseInt(countAttribute.value, 10) + 1;

		// limit to last maxHistoryEntries values
		while (historyAttribute.value.length > maxHistoryEntries) {
			historyAttribute.value.shift();
		}

		// update entity attributes
		contextBroker.updateEntityAttributes(contextElement.id, {
			[historyAttributeName]: historyAttribute.value,
			[countAttributeName]: countAttribute.value
		})
			.then(handleQueryResponse(req, res))
			.catch(handleQueryError(req, res));
	});
});

// accept POST request and just mirror the data back
app.post('/mirror', (req, res) => {
	logRequest(req);

	res.send(formatJsonResponse('got request', req.body));
});

// start the server
app.listen(config.port, () => {
	console.log('server started on port ' + config.port);
});

// logs the request info to console
function logRequest(req) {
	console.log(req.method + ' ' + req.url + '\n' + JSON.stringify(req.body, null, '  ') + '\n\n');
}

// handles query response
function handleQueryResponse(req, res) {
	return (response) => {
		if (res) {
			res.json(response);
		}

		return response;
	};
}

// handles query error
function handleQueryError(req, res) {
	return (response) => {
		if (res) {
			res.json(response);
		}

		return response;
	};
}

// formats JSON response to HTML
function formatJsonResponse(name, response) {
	const responseText = JSON.stringify(response, null, '\t');

	return `

${name}

${responseText}

	`;
}

// searches for an attribute from an array of attributes by name, returns null if not found
function findAttribute(name, attributes, isRequired = false) {
	const attribute = attributes.find((item) => item.name === name);

	if (!attribute) {
		if (isRequired) {
			throw new Error('Attribute called "' + name + '" could not be found in ' + JSON.stringify(attributes));
		}

		return null;
	}

	return parseAttribute(attribute);
}

// parses attribute value by type
function parseAttribute(attribute) {
	switch (attribute.type) {
		case 'integer':
			attribute.value = Number.parseInt(attribute.value, 10);

			if (Number.isNaN(attribute.value)) {
				console.error('parsing "' + attribute.value + '" as an integer failed, using zero');

				attribute.value = 0;
			}

			break;

		case 'float':
			attribute.value = Number.parseFloat(attribute.value);

			if (Number.isNaN(attribute.value)) {
				console.error('parsing "' + attribute.value + '" as a float failed, using zero');

				attribute.value = 0;
			}

			break;

		case 'array':
			if (typeof attribute.value === 'string') {
				try {
					attribute.value = JSON.parse(attribute.value);
				} catch (e) {
					console.error('parsing "' + attribute.value + '" as an array failed, using empty array');

					attribute.value = [];
				}
			} else if (Array.isArray(attribute.value)) {
				// don't change anything if already an array
			} else {
				console.error('attribute "' + attribute.value + '" is not a string to parse, using empty array');

				attribute.value = [];
			}
			break;

		default:
			// do not change anything
	}

	return attribute;
}<|endoftext|>