import {PolymerElement, html} from '@polymer/polymer/polymer-element.js'; import '../channelstream-connection/channelstream-connection.js'; import '../rhodecode-toast/rhodecode-toast.js'; import '../rhodecode-favicon/rhodecode-favicon.js'; var ccLog = Logger.get('RhodeCodeApp'); ccLog.setLevel(Logger.OFF); export class RhodecodeApp extends PolymerElement { static get is() { return 'rhodecode-app'; } static get template(){ return html` <channelstream-connection id="channelstream-connection" on-channelstream-listen-message="receivedMessage" on-channelstream-connected="handleConnected" on-channelstream-subscribed="handleSubscribed"> </channelstream-connection> <rhodecode-favicon></rhodecode-favicon> ` } connectedCallback() { super.connectedCallback(); ccLog.debug('rhodeCodeApp created'); $.Topic('/notifications').subscribe(this.handleNotifications.bind(this)); $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this)); $.Topic('/connection_controller/subscribe').subscribe( this.subscribeToChannelTopic.bind(this)); // this event can be used to coordinate plugins to do their // initialization before channelstream is kicked off $.Topic('/__MAIN_APP__').publish({}); for (var i = 0; i < alertMessagePayloads.length; i++) { $.Topic('/notifications').publish(alertMessagePayloads[i]); } this.initPlugins(); // after rest of application loads and topics get fired, launch connection $(document).ready(function () { this.kickoffChannelstreamPlugin(); }.bind(this)); } initPlugins() { for (var i = 0; i < window.APPLICATION_PLUGINS.length; i++) { var pluginDef = window.APPLICATION_PLUGINS[i]; if (pluginDef.component) { var pluginElem = document.createElement(pluginDef.component); this.shadowRoot.appendChild(pluginElem); if (typeof pluginElem.init !== 'undefined') { pluginElem.init(); } } } } /** proxy to channelstream connection */ getChannelStreamConnection() { return this.$['channelstream-connection']; } handleNotifications(data) { var elem = document.getElementById('notifications'); if (elem) { elem.handleNotification(data); } } faviconUpdate(data) { this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count; } /** opens connection to ws server */ kickoffChannelstreamPlugin(data) { ccLog.debug('kickoffChannelstreamPlugin'); var channels = ['broadcast']; var addChannels = this.checkViewChannels(); for (var i = 0; i < addChannels.length; i++) { channels.push(addChannels[i]); } if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled) { var channelstreamConnection = this.getChannelStreamConnection(); channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect; channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe; channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + '/ws'; channelstreamConnection.longPollUrl = CHANNELSTREAM_URLS.longpoll + '/listen'; // some channels might already be registered by topic for (var i = 0; i < channels.length; i++) { channelstreamConnection.push('channels', channels[i]); } // append any additional channels registered in other plugins $.Topic('/connection_controller/subscribe').processPrepared(); channelstreamConnection.connect(); } } checkViewChannels() { // subscribe to different channels data is sent. var channels = []; // subscribe to PR repo channel for PR's' if (templateContext.pull_request_data.pull_request_id) { var channelName = '/repo$' + templateContext.repo_name + '$/pr/' + String(templateContext.pull_request_data.pull_request_id); channels.push(channelName); } if (templateContext.commit_data.commit_id) { var channelName = '/repo$' + templateContext.repo_name + '$/commit/' + String(templateContext.commit_data.commit_id); channels.push(channelName); } return channels; } /** subscribes users from channels in channelstream */ subscribeToChannelTopic(channels) { var channelstreamConnection = this.getChannelStreamConnection(); var toSubscribe = channelstreamConnection.calculateSubscribe(channels); ccLog.debug('subscribeToChannelTopic', toSubscribe); if (toSubscribe.length > 0) { // if we are connected then subscribe if (channelstreamConnection.connected) { channelstreamConnection.subscribe(toSubscribe); } // not connected? just push channels onto the stack else { for (var i = 0; i < toSubscribe.length; i++) { channelstreamConnection.push('channels', toSubscribe[i]); } } } } /** publish received messages into correct topic */ receivedMessage(event) { for (var i = 0; i < event.detail.length; i++) { var message = event.detail[i]; if (message.message.topic) { ccLog.debug('publishing', message.message.topic); $.Topic(message.message.topic).publish(message); } else if (message.type === 'presence') { $.Topic('/connection_controller/presence').publish(message); } else { ccLog.warn('unhandled message', message); } } } handleConnected(event) { var channelstreamConnection = this.getChannelStreamConnection(); channelstreamConnection.set('channelsState', event.detail.channels_info); channelstreamConnection.set('userState', event.detail.state); channelstreamConnection.set('channels', event.detail.channels); this.propagageChannelsState(); } handleSubscribed(event) { var channelstreamConnection = this.getChannelStreamConnection(); var channelInfo = event.detail.channels_info; var channelKeys = Object.keys(event.detail.channels_info); for (var i = 0; i < channelKeys.length; i++) { var key = channelKeys[i]; channelstreamConnection.set(['channelsState', key], channelInfo[key]); } channelstreamConnection.set('channels', event.detail.channels); this.propagageChannelsState(); } /** propagates channel states on topics */ propagageChannelsState(event) { var channelstreamConnection = this.getChannelStreamConnection(); var channel_data = channelstreamConnection.channelsState; var channels = channelstreamConnection.channels; for (var i = 0; i < channels.length; i++) { var key = channels[i]; $.Topic('/connection_controller/channel_update').publish( {channel: key, state: channel_data[key]} ); } } } customElements.define(RhodecodeApp.is, RhodecodeApp);