<commit_before>var self = require('sdk/self');
var {setInterval, clearInterval} = require('sdk/timers');
var {pluginState} = require('./pluginState');
exports.init = function () {
  var tabs = require('sdk/tabs');

  var { Toolbar } = require('sdk/ui/toolbar');
  var { Frame } = require('sdk/ui/frame');
  var frame = new Frame({
    url: './toolbarFrame.html',
    onMessage: (e)=> {
      var msg = e.data;
      switch (msg.action) {
        case 'page-loaded':
          pluginState.toolbarFrameSource = e.source;
          pluginState.toolbarFrameOrigin = e.origin;
          break;
        case 'login':
          //Aim a browser tab at our login screen
          tabs.open({
            url: pluginState.loginUrl
          });
          break;
        case 'logout':
          logoutSuccessfulHandler(false);
          //In case the login tab is open. Someday we may support multiple open
          //login tabs. Not today.
          pluginState.postEventToDatawakeDepotContentScript('logout-target-content-script');
          break;
        case 'toggle-panel':
          //var activeTabId = tabs.activeTab.id;
          //pluginState.panelActive = msg.data;
          //pluginState.postEventToContentScript(activeTabId, 'send-toggle-datawake-panel',{panelActive:msg.data});

          //show sidebar
          if(pluginState.panelActive){
              sidebar.show();
              //Get sidebar contents
              getExtractedEntities(tabs.activeTab.url);
          }else{
              sidebar.hide();
          }
          break;
        case 'toggle-dataitems':
          var activeTabId = tabs.activeTab.id;
          pluginState.dataItemsActive = msg.data;
          pluginState.postEventToContentScript(activeTabId, 'send-toggle-datawake-dataitems', {
            dataItemsActive:msg.data,
            dataItems:pluginState.currentDomainItems
          });
          break;
        case 'set-trailing-active':
          pluginState.trailingActive = msg.data;
          //Get the domain items in case they want to see them
          pluginState.getDomainItemsForCurrentDomain();
          break;
        case 'set-current-team-target-addin':
          pluginState.currentTeam = pluginState.currentTeamList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          pluginState.postEventToAddInModule('get-domains-for-current-team');
          break;
        case 'set-current-domain-target-addin':
          pluginState.currentDomain = pluginState.currentDomainList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');
          break;
        case 'set-current-trail-target-addin':
          pluginState.currentTrail = pluginState.currentTrailList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          break;
        case 'add-current-trail-to-domain-target-addin':
          var newTrail = msg.trailName;
          addTrail(newTrail);
          break;
        case 'open-new-tab-target-addin':
          var target = '';

            switch (msg.tabTarget){
                case 'dashboard':
                    target = pluginState.dashboard;
                    break;
                case 'dwForensic':
                    target = pluginState.dwForensic;
                    break;
                case 'dwTrails':
                    target = pluginState.dwTrails;
                    break;
                case 'dwDomains':
                    target = pluginState.dwDomains;
                    break;
                default:
                    target = '';
                    break;
            }
          tabs.open(pluginState.loginUrl + target);
          break;
      }
    }
  });
  var toolbar = Toolbar({
    title: 'Datawake',
    items: [frame]
  });

  var sidebarWorker = null;

  var sidebar = require("sdk/ui/sidebar").Sidebar({
      id: 'datawake-sidebar',
      title: 'Datawake Sidebar',
      url: require("sdk/self").data.url("sidebar.html"),
      onAttach: function (worker) {
          sidebarWorker = worker;

          //Listen for sidebar requests to refresh content
          worker.port.on("refreshSidebar", function(data) {
              pluginState.getExtractedEntities(data.pageUrl, function (divHtml){
                  if (divHtml) {
                       //send contents to sidebar
                      sidebarWorker.port.emit("sidebarContent",divHtml);
                  }
              });
          });

          //Listen for sidebar requests to create Domain Items
          worker.port.on('addDomainItem-target-addin', function(domainItem) {
              addDomainItem(domainItem, tabs.activeTab.id);
          });

          //Listen for sidebar requests to create Domain Types
          worker.port.on('addEntityType-target-addin', function(domainType) {
              addDomainEntityType(domainType);
          });
      }
  });

  tabs.on('ready', function (tab) {
    if (!pluginState.trailingActive) {
      return;
    }
  });
  //Here we listen for when the content scripts is fired up and ready.
  pluginState.onAddInModuleEvent('page-content-script-attached-target-addin', function (data) {
    //Send sidebar the current tab info
    sidebarWorker.port.emit("send-sidebar-current-tab",data);

    //Listen for when the content script loads a new page to tell sidebar to get extracted items
    pluginState.addContentScriptEventHandler(data.contentScriptKey,'requestPanelHtml-target-addin', function () {
        pluginState.getExtractedEntities(data.pageUrl, function (divHtml){
            if (divHtml) {
                //send contents to sidebar
                sidebarWorker.port.emit("sidebarContent",divHtml);
            }
        });
    });

    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'send-css-urls-target-addin', function (scriptData) {
      pluginState.postEventToContentScript(scriptData.contentScriptKey, 'load-css-urls-target-content-script',
        {
          cssUrls: [
            self.data.url('injectedPageCSS/datawake-analysis.css')
          ]
        });
    });

    //Listens for requests to get user trailing status
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'requestTrailingActive-target-addin', function (scriptData) {
        pluginState.postEventToContentScript(data.contentScriptKey, 'trailingStatus-target-content-script', {
            trailingActive: pluginState.trailingActive,
            panelActive:pluginState.panelActive,
            dataItemsActive:pluginState.dataItemsActive,
            dataItems:pluginState.currentDomainItems
        });
    });

    //Listens for requests to get user trailing status
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'requestPanelActive-target-addin', function (scriptData) {
        pluginState.postEventToContentScript(data.contentScriptKey, 'panelStatus-target-content-script', {panelActive: pluginState.panelActive});
    });

    //Create trail urls
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'zipped-html-body-target-addin', function (pageContents) {
      //TODO: Work out some scraper eventing so we don't do the DOM operation if we're not trailing.
      //This will work for now though.
      if (!pluginState.trailingActive) {
        return;
      }
      //pluginState.restPost(pluginState.textToHtmlUrl,
      // TODO: This still renders some pages multiple times but at least cleans up the ads.
      //if (pageContents.url === tabs.activeTab.url && tabs.activeTab.readyState === 'complete') {
      if (pageContents.url === tabs.activeTab.url) {
        pluginState.restPost(pluginState.trailsUrlsUrl,
            {
              dwTrailId: pluginState.currentTrail.id
              , url: pageContents.url
              , scrapedContent: pageContents.zippedHtmlBody
              , searchTerms: pageContents.searchTerms
            }, function (res) {
              //console.log(res.text);
            }
        );
      }
      //HowTo: decode (unzip) in addin
      /*      var JSZip = require('./vendor/jszip/jszip.min.js');
       var zip = new JSZip();
       zip.load(pageContents.zippedHtmlBody);
       var html = zip.file('zipped-html-body.zip').asText();*/
    });
  });

  //Here we listen for when the DD content script is fired up and ready.
  pluginState.onAddInModuleEvent('page-datawake-depot-content-script-attached-target-addin', function (data) {
    pluginState.addDatawakeDepotContentScriptEventHandler('logout-success-target-plugin', function (user) {
      logoutSuccessfulHandler(true);
    });
    pluginState.addDatawakeDepotContentScriptEventHandler('login-success-target-plugin', function (user) {
      loginSuccessfulHandler(user);
    });
  });
  //Here we listen for when to get Team/Domain/Trail info from the server
  pluginState.onAddInModuleEvent('get-teams-for-logged-in-user', function (data) {
    pluginState.getTeamsForLoggedInUser(function (teams) {
      if (!teams || !teams.length) {
        pluginState.currentTeamList = [];
        pluginState.currentTeam = null;
        pluginState.currentDomainList = [];
        pluginState.currentDomain = null;
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
        pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
      } else {
        pluginState.currentTeamList = teams;
        pluginState.currentTeam = teams[0];
        pluginState.postEventToAddInModule('get-domains-for-current-team');
      }
    });
  });
  pluginState.onAddInModuleEvent('get-domains-for-current-team', function (data) {
    pluginState.getDomainsForCurrentTeam(function (domains) {
      if (!domains || !domains.length) {
        pluginState.currentDomainList = [];
        pluginState.currentDomain = null;
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
        pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
      } else {
        pluginState.currentDomainList = domains;
        pluginState.currentDomain = domains[0];
        pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');
      }
    });
  });
  pluginState.onAddInModuleEvent('get-trails-for-current-team-and-domain', function (data) {
    pluginState.getTrailsForCurrentTeamAndDomain(function (trails) {
      if (!trails || !trails.length) {
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
      } else {
        pluginState.currentTrailList = trails;
        pluginState.currentTrail = trails[0];
      }
      pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
    });
  });
  pluginState.onAddInModuleEvent('post-plugin-state-to-toolbar', function (data) {
    postPluginStateToToolBar();
  });
};

function getExtractedEntities(url){
    //Get panel contents
    pluginState.getExtractedEntities(url, function (divHtml){
        if (divHtml) {
            //send contents to sidebar
            sidebarWorker.port.emit("sidebarContent",divHtml);
        }
    });
}

function logoutSuccessfulHandler(tellToolBar) {
  pluginState.reset();
  pluginState.postEventToAddInModule('logged-out-target-context-menu');
  pluginState.loggedInUser = null;
  if (!tellToolBar) {
    return;
  }
  var msg = {
    type: 'logout-success-target-toolbar-frame'
  };
  pluginState.postMessageToToolBar(msg);
}

function loginSuccessfulHandler(user) {
  pluginState.loggedInUser = user;
  pluginState.postEventToAddInModule('logged-in-target-context-menu');
  pluginState.postEventToAddInModule('get-teams-for-logged-in-user');
}

function postPluginStateToToolBar() {
  var semiPluginState = {
    loggedInUser: pluginState.loggedInUser,
    currentTeam: pluginState.currentTeam,
    currentTeamList: pluginState.currentTeamList,
    currentDomain: pluginState.currentDomain,
    currentDomainList: pluginState.currentDomainList,
    currentTrail: pluginState.currentTrail,
    currentTrailList: pluginState.currentTrailList
  };
  var msg = {
    type: 'login-success-target-toolbar-frame',
    pluginState: semiPluginState
  };
  pluginState.postMessageToToolBar(msg);
}

function addDomainEntityType(entType){
  var currentDomainId = pluginState.currentDomain.id;
  entType['dwDomainId'] = currentDomainId;

  pluginState.restPost(pluginState.createEntityType,
    entType, function (res) {
      console.log(res.text);
    }
  );
}

function addDomainItem(domItem, activeTabId){
  var currentDomainId = pluginState.currentDomain.id;
  domItem['dwDomainId'] = currentDomainId;
  var specificDomainInsertUrl =  pluginState.createDomainItem.replace("_domainId_",currentDomainId);
  pluginState.restPost(specificDomainInsertUrl,
      domItem, function (res) {
          console.log(res.text);
      }
  );
  //After creating the new item, make the plugin refresh its list
  pluginState.getDomainItemsForCurrentDomain();

  //Then tell the page to refresh its dataitems
  pluginState.postEventToContentScript(activeTabId, 'refresh-data-items-target-content-script', {
      dataItemsActive: pluginState.dataItemsActive,
      dataItems: pluginState.currentDomainItems
  });
}

function addTrail(trailName){
    //Create the trail
    var newTrail = {
      dwTeamId: pluginState.currentTeam.id,
      dwDomainId: pluginState.currentDomain.id,
      scrape: 'body',
      name: trailName,
      description: trailName
    };

    pluginState.restPost(pluginState.createTrail,
        newTrail, function (res) {
            console.log(res.text);
        }
    );

    //Reload the plugins trail list to get the new trail
    pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');

    //Tell the toolbar that all is well
    var msg = {
        type: 'create-trail-success-target-toolbar-frame',
        trailName: trailName
    };
    pluginState.postMessageToToolBar(msg);
}

<commit_msg>align toolbar sidebar toggle with trailing status<commit_after>var self = require('sdk/self');
var {setInterval, clearInterval} = require('sdk/timers');
var {pluginState} = require('./pluginState');
exports.init = function () {
  var tabs = require('sdk/tabs');

  var { Toolbar } = require('sdk/ui/toolbar');
  var { Frame } = require('sdk/ui/frame');
  var frame = new Frame({
    url: './toolbarFrame.html',
    onMessage: (e)=> {
      var msg = e.data;
      switch (msg.action) {
        case 'page-loaded':
          pluginState.toolbarFrameSource = e.source;
          pluginState.toolbarFrameOrigin = e.origin;
          break;
        case 'login':
          //Aim a browser tab at our login screen
          tabs.open({
            url: pluginState.loginUrl
          });
          break;
        case 'logout':
          logoutSuccessfulHandler(false);
          //In case the login tab is open. Someday we may support multiple open
          //login tabs. Not today.
          pluginState.postEventToDatawakeDepotContentScript('logout-target-content-script');
          break;
        case 'toggle-panel':
          //var activeTabId = tabs.activeTab.id;
          //pluginState.panelActive = msg.data;
          //pluginState.postEventToContentScript(activeTabId, 'send-toggle-datawake-panel',{panelActive:msg.data});

          //show sidebar
          if(!pluginState.panelActive){
              sidebar.show();
              pluginState.panelActive=true;
              //Get sidebar contents
              getExtractedEntities(tabs.activeTab.url);
          }else{
              pluginState.panelActive=false;
              sidebar.hide();
          }
          break;
        case 'toggle-dataitems':
          var activeTabId = tabs.activeTab.id;
          pluginState.dataItemsActive = msg.data;
          pluginState.postEventToContentScript(activeTabId, 'send-toggle-datawake-dataitems', {
            dataItemsActive:msg.data,
            dataItems:pluginState.currentDomainItems
          });
          break;
        case 'set-trailing-active':
          pluginState.trailingActive = msg.data;

          if(msg.data)  {
              //Show the sidebar
              sidebar.show();
              pluginState.panelActive=true;
              //Get the domain items in case they want to see them
              pluginState.getDomainItemsForCurrentDomain();
          }else{
              //Hide the sidebar
              sidebar.hide();
              pluginState.panelActive=false;
          }

          break;
        case 'set-current-team-target-addin':
          pluginState.currentTeam = pluginState.currentTeamList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          pluginState.postEventToAddInModule('get-domains-for-current-team');
          break;
        case 'set-current-domain-target-addin':
          pluginState.currentDomain = pluginState.currentDomainList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');
          break;
        case 'set-current-trail-target-addin':
          pluginState.currentTrail = pluginState.currentTrailList.filter(function (el) {
            return el.name == msg.value;
          })[0];
          break;
        case 'add-current-trail-to-domain-target-addin':
          var newTrail = msg.trailName;
          addTrail(newTrail);
          break;
        case 'open-new-tab-target-addin':
          var target = '';

            switch (msg.tabTarget){
                case 'dashboard':
                    target = pluginState.dashboard;
                    break;
                case 'dwForensic':
                    target = pluginState.dwForensic;
                    break;
                case 'dwTrails':
                    target = pluginState.dwTrails;
                    break;
                case 'dwDomains':
                    target = pluginState.dwDomains;
                    break;
                default:
                    target = '';
                    break;
            }
          tabs.open(pluginState.loginUrl + target);
          break;
      }
    }
  });
  var toolbar = Toolbar({
    title: 'Datawake',
    items: [frame]
  });

  var sidebarWorker = null;

  var sidebar = require("sdk/ui/sidebar").Sidebar({
      id: 'datawake-sidebar',
      title: 'Datawake Sidebar',
      url: require("sdk/self").data.url("sidebar.html"),
      onAttach: function (worker) {
          sidebarWorker = worker;

          //Listen for sidebar requests to refresh content
          worker.port.on("refreshSidebar", function(data) {
              pluginState.getExtractedEntities(data.pageUrl, function (divHtml){
                  if (divHtml) {
                       //send contents to sidebar
                      sidebarWorker.port.emit("sidebarContent",divHtml);
                  }
              });
          });

          //Listen for sidebar requests to create Domain Items
          worker.port.on('addDomainItem-target-addin', function(domainItem) {
              addDomainItem(domainItem, tabs.activeTab.id);
          });

          //Listen for sidebar requests to create Domain Types
          worker.port.on('addEntityType-target-addin', function(domainType) {
              addDomainEntityType(domainType);
          });
      }
  });

  tabs.on('ready', function (tab) {
    if (!pluginState.trailingActive) {
      return;
    }
  });
  //Here we listen for when the content scripts is fired up and ready.
  pluginState.onAddInModuleEvent('page-content-script-attached-target-addin', function (data) {
    //Send sidebar the current tab info
    sidebarWorker.port.emit("send-sidebar-current-tab",data);

    //Listen for when the content script loads a new page to tell sidebar to get extracted items
    pluginState.addContentScriptEventHandler(data.contentScriptKey,'requestPanelHtml-target-addin', function () {
        pluginState.getExtractedEntities(data.pageUrl, function (divHtml){
            if (divHtml) {
                //send contents to sidebar
                sidebarWorker.port.emit("sidebarContent",divHtml);
            }
        });
    });

    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'send-css-urls-target-addin', function (scriptData) {
      pluginState.postEventToContentScript(scriptData.contentScriptKey, 'load-css-urls-target-content-script',
        {
          cssUrls: [
            self.data.url('injectedPageCSS/datawake-analysis.css')
          ]
        });
    });

    //Listens for requests to get user trailing status
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'requestTrailingActive-target-addin', function (scriptData) {
        pluginState.postEventToContentScript(data.contentScriptKey, 'trailingStatus-target-content-script', {
            trailingActive: pluginState.trailingActive,
            panelActive:pluginState.panelActive,
            dataItemsActive:pluginState.dataItemsActive,
            dataItems:pluginState.currentDomainItems
        });
    });

    //Listens for requests to get user trailing status
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'requestPanelActive-target-addin', function (scriptData) {
        pluginState.postEventToContentScript(data.contentScriptKey, 'panelStatus-target-content-script', {panelActive: pluginState.panelActive});
    });

    //Create trail urls
    pluginState.addContentScriptEventHandler(data.contentScriptKey, 'zipped-html-body-target-addin', function (pageContents) {
      //TODO: Work out some scraper eventing so we don't do the DOM operation if we're not trailing.
      //This will work for now though.
      if (!pluginState.trailingActive) {
        return;
      }
      //pluginState.restPost(pluginState.textToHtmlUrl,
      // TODO: This still renders some pages multiple times but at least cleans up the ads.
      //if (pageContents.url === tabs.activeTab.url && tabs.activeTab.readyState === 'complete') {
      if (pageContents.url === tabs.activeTab.url) {
        pluginState.restPost(pluginState.trailsUrlsUrl,
            {
              dwTrailId: pluginState.currentTrail.id
              , url: pageContents.url
              , scrapedContent: pageContents.zippedHtmlBody
              , searchTerms: pageContents.searchTerms
            }, function (res) {
              //console.log(res.text);
            }
        );
      }
      //HowTo: decode (unzip) in addin
      /*      var JSZip = require('./vendor/jszip/jszip.min.js');
       var zip = new JSZip();
       zip.load(pageContents.zippedHtmlBody);
       var html = zip.file('zipped-html-body.zip').asText();*/
    });
  });

  //Here we listen for when the DD content script is fired up and ready.
  pluginState.onAddInModuleEvent('page-datawake-depot-content-script-attached-target-addin', function (data) {
    pluginState.addDatawakeDepotContentScriptEventHandler('logout-success-target-plugin', function (user) {
      logoutSuccessfulHandler(true);
    });
    pluginState.addDatawakeDepotContentScriptEventHandler('login-success-target-plugin', function (user) {
      loginSuccessfulHandler(user);
    });
  });
  //Here we listen for when to get Team/Domain/Trail info from the server
  pluginState.onAddInModuleEvent('get-teams-for-logged-in-user', function (data) {
    pluginState.getTeamsForLoggedInUser(function (teams) {
      if (!teams || !teams.length) {
        pluginState.currentTeamList = [];
        pluginState.currentTeam = null;
        pluginState.currentDomainList = [];
        pluginState.currentDomain = null;
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
        pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
      } else {
        pluginState.currentTeamList = teams;
        pluginState.currentTeam = teams[0];
        pluginState.postEventToAddInModule('get-domains-for-current-team');
      }
    });
  });
  pluginState.onAddInModuleEvent('get-domains-for-current-team', function (data) {
    pluginState.getDomainsForCurrentTeam(function (domains) {
      if (!domains || !domains.length) {
        pluginState.currentDomainList = [];
        pluginState.currentDomain = null;
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
        pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
      } else {
        pluginState.currentDomainList = domains;
        pluginState.currentDomain = domains[0];
        pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');
      }
    });
  });
  pluginState.onAddInModuleEvent('get-trails-for-current-team-and-domain', function (data) {
    pluginState.getTrailsForCurrentTeamAndDomain(function (trails) {
      if (!trails || !trails.length) {
        pluginState.currentTrailList = [];
        pluginState.currentTrail = null;
      } else {
        pluginState.currentTrailList = trails;
        pluginState.currentTrail = trails[0];
      }
      pluginState.postEventToAddInModule('post-plugin-state-to-toolbar');
    });
  });
  pluginState.onAddInModuleEvent('post-plugin-state-to-toolbar', function (data) {
    postPluginStateToToolBar();
  });
};

function getExtractedEntities(url){
    //Get panel contents
    pluginState.getExtractedEntities(url, function (divHtml){
        if (divHtml) {
            //send contents to sidebar
            sidebarWorker.port.emit("sidebarContent",divHtml);
        }
    });
}

function logoutSuccessfulHandler(tellToolBar) {
  pluginState.reset();
  pluginState.postEventToAddInModule('logged-out-target-context-menu');
  pluginState.loggedInUser = null;
  if (!tellToolBar) {
    return;
  }
  var msg = {
    type: 'logout-success-target-toolbar-frame'
  };
  pluginState.postMessageToToolBar(msg);
}

function loginSuccessfulHandler(user) {
  pluginState.loggedInUser = user;
  pluginState.postEventToAddInModule('logged-in-target-context-menu');
  pluginState.postEventToAddInModule('get-teams-for-logged-in-user');
}

function postPluginStateToToolBar() {
  var semiPluginState = {
    loggedInUser: pluginState.loggedInUser,
    currentTeam: pluginState.currentTeam,
    currentTeamList: pluginState.currentTeamList,
    currentDomain: pluginState.currentDomain,
    currentDomainList: pluginState.currentDomainList,
    currentTrail: pluginState.currentTrail,
    currentTrailList: pluginState.currentTrailList
  };
  var msg = {
    type: 'login-success-target-toolbar-frame',
    pluginState: semiPluginState
  };
  pluginState.postMessageToToolBar(msg);
}

function addDomainEntityType(entType){
  var currentDomainId = pluginState.currentDomain.id;
  entType['dwDomainId'] = currentDomainId;

  pluginState.restPost(pluginState.createEntityType,
    entType, function (res) {
      console.log(res.text);
    }
  );
}

function addDomainItem(domItem, activeTabId){
  var currentDomainId = pluginState.currentDomain.id;
  domItem['dwDomainId'] = currentDomainId;
  var specificDomainInsertUrl =  pluginState.createDomainItem.replace("_domainId_",currentDomainId);
  pluginState.restPost(specificDomainInsertUrl,
      domItem, function (res) {
          console.log(res.text);
      }
  );
  //After creating the new item, make the plugin refresh its list
  pluginState.getDomainItemsForCurrentDomain();

  //Then tell the page to refresh its dataitems
  pluginState.postEventToContentScript(activeTabId, 'refresh-data-items-target-content-script', {
      dataItemsActive: pluginState.dataItemsActive,
      dataItems: pluginState.currentDomainItems
  });
}

function addTrail(trailName){
    //Create the trail
    var newTrail = {
      dwTeamId: pluginState.currentTeam.id,
      dwDomainId: pluginState.currentDomain.id,
      scrape: 'body',
      name: trailName,
      description: trailName
    };

    pluginState.restPost(pluginState.createTrail,
        newTrail, function (res) {
            console.log(res.text);
        }
    );

    //Reload the plugins trail list to get the new trail
    pluginState.postEventToAddInModule('get-trails-for-current-team-and-domain');

    //Tell the toolbar that all is well
    var msg = {
        type: 'create-trail-success-target-toolbar-frame',
        trailName: trailName
    };
    pluginState.postMessageToToolBar(msg);
}

<|endoftext|>


<commit_before>"use strict";

var Cylon = require('cylon')
var tilted = false;
var talking = false;
var leds = {red:2,blue:3,green:4};
var color = "";
var whiteArray = {red:0,blue:0,green:0};
var blackArray = {red:0,blue:0,green:0};
var colorArray = {red:0,blue:0,green:0};
var avgArray = {red:0,blue:0,green:0};

require('shelljs/global');

Cylon.robot({
  connections: {
    edison: { adaptor: 'intel-iot' }
  },
  devices: {
    //outputs:
    laser: { driver: 'led', pin: 7 },
    redLed: { driver: 'led', pin: 4 },
    greenLed: { driver: 'led', pin: 5 },
    blueLed: { driver: 'led', pin: 6 },

    //inputs:
    tilt: { driver: 'button', pin: 3 },
    button: { driver: 'button', pin: 2 },
    ambient: { driver: 'analog-sensor', pin: 3, lowerLimit: 100, upperLimit: 900 },
    color_detector: { driver: 'analog-sensor', pin: 0, lowerLimit: 0, upperLimit: 1024 },

  },
  work: function(my) {
    my.button.on('push', function() {
      my.laser.toggle();
    console.log("laser toggled");

    });

    every((1).seconds(), function() {
    //   console.log("Hello, human!");
    });

    var output_sound= function(color) {
    console.log(color + " detected");
    if (!talking){
        if (color === "red"){
          exec('sh red.sh',{silent:true});
        }
        if (color === "green"){
            exec('sh green.sh',{silent:true});
        }
        if (color === "blue"){
            exec('sh blue.sh',{silent:true});
        }
    }
    };

      my.tilt.on('push', function() {
          console.log("Tilt Activated");
          tilted = true;
      });
      my.tilt.on('release', function() {
          console.log("Tilt Deactivated");
          tilted = false;
      });

      var setRed = function(){
          my.redLed.turnOn()
          my.greenLed.turnOff()
          my.blueLed.turnOff()
      };
      var setBlue = function(){
          my.redLed.turnOff()
          my.greenLed.turnOff()
          my.blueLed.turnOn()
      }
      var setGreen = function(){
          my.redLed.turnOff()
          my.greenLed.turnOn()
          my.blueLed.turnOff()
      }
      var setOff = function(){
          my.redLed.turnOff()
          my.greenLed.turnOff()
          my.blueLed.turnOff()
      }

    var calibrate = function(cb){
            setRed();
            after((0.1).seconds(), function() {
                getReading(5, function(avgRead){
                    whiteArray.red = avgRead;
                    console.log("Set white red to "+avgRead);
                    setBlue();
                    after((0.1).seconds(), function() {
                        getReading(5, function(avgRead){
                            whiteArray.blue = avgRead;
                            console.log("Set white blue to "+avgRead);
                            setGreen();
                            after((0.1).seconds(), function() {
                                getReading(5, function(avgRead){
                                    whiteArray.green = avgRead;
                                    console.log("Set white green to "+avgRead);
                                    setOff();
                                    after((5).seconds(), function() {
                                        setRed();
                                        after((0.1).seconds(), function() {
                                            getReading(5, function(avgRead){
                                                blackArray.red = avgRead;
                                                console.log("Set black red to "+avgRead);
                                                setBlue();
                                                after((0.1).seconds(), function() {
                                                    getReading(5, function(avgRead){
                                                        blackArray.blue = avgRead;
                                                        console.log("Set black blue to "+avgRead);
                                                        setGreen();
                                                        after((0.1).seconds(), function() {
                                                            getReading(5, function(avgRead){
                                                                blackArray.green = avgRead;
                                                                console.log("Set black green to "+avgRead);
                                                                after((1).seconds(), function() {
                                                                    cb();
                                                                });
                                                            });
                                                        });
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        };

    var getReading = function(times, cb, tally, count){
        if (count ===0){
            var avgRead = (tally) / times;
            return cb(avgRead);
        }
        if (!tally){
            tally=0;
        }
        if (!count){
            count=times;
        }

        var reading = my.ambient.analogRead();
        tally = reading + tally;
        after((0.01).seconds(), function() {
            getReading(times, cb, tally, count-1);
        });
    };

    after((5).seconds(), function() {
        calibrate(function(){
            every((1).seconds(), function() {
            //   console.log("Check color");
                    setRed();
                    after((0.01).seconds(), function() {
                        getReading(5, function(avgRead){
                            colorArray.red = avgRead;
                            console.log("Set colorArray red to "+avgRead);
                            var greyDiff = whiteArray.red - blackArray.red;
                            colorArray.red = (colorArray.red - blackArray.red) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                            //for the current reflectivity(for the color it is exposed to) of what is being scanned
                            avgArray.red = (avgArray.red + colorArray.red) / 2;

                            setBlue();
                            after((0.01).seconds(), function() {
                                getReading(5, function(avgRead){
                                    colorArray.blue = avgRead;
                                    console.log("Set colorArray blue to "+avgRead);
                                    var greyDiff = whiteArray.blue - blackArray.blue;
                                    colorArray.blue = (colorArray.blue - blackArray.blue) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                                    //for the current reflectivity(for the color it is exposed to) of what is being scanned
                                    avgArray.blue = (avgArray.blue + colorArray.blue) / 2;
                                    setGreen();
                                    after((0.01).seconds(), function() {
                                        getReading(5, function(avgRead){
                                            colorArray.green = avgRead;
                                            console.log("Set colorArray green to "+avgRead);
                                            var greyDiff = whiteArray.green - blackArray.green;
                                            colorArray.green = (colorArray.green - blackArray.green) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                                            //for the current reflectivity(for the color it is exposed to) of what is being scanned
                                            avgArray.green = (avgArray.green + colorArray.green) / 2;
                                            after((0.01).seconds(), function() {
                                                setOff();
                                                if(avgArray.red > avgArray.green && avgArray.red > avgArray.blue) {
                                                    console.log("Detected Red");
                                                    output_sound("red");
                                                }
                                                else if(avgArray.green > avgArray.red && avgArray.green > avgArray.blue) {
                                                    console.log("Detected Green");
                                                    output_sound("green");

                                                }
                                                else {
                                                    console.log("Detected Blue");
                                                    output_sound("blue");
                                                }

                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
              });
            });
        });

    } //end setup

}).start();
<commit_msg>setup<commit_after>"use strict";

var Cylon = require('cylon')
var tilted = false;
var talking = false;
var leds = {red:2,blue:3,green:4};
var color = "";
var whiteArray = {red:0,blue:0,green:0};
var blackArray = {red:0,blue:0,green:0};
var colorArray = {red:0,blue:0,green:0};
var avgArray = {red:0,blue:0,green:0};

require('shelljs/global');

Cylon.robot({
  connections: {
    edison: { adaptor: 'intel-iot' }
  },
  devices: {
    //outputs:
    laser: { driver: 'led', pin: 7 },
    redLed: { driver: 'led', pin: 4 },
    greenLed: { driver: 'led', pin: 5 },
    blueLed: { driver: 'led', pin: 6 },

    //inputs:
    tilt: { driver: 'button', pin: 3 },
    button: { driver: 'button', pin: 2 },
    ambient: { driver: 'analog-sensor', pin: 3 },
    color_detector: { driver: 'analog-sensor', pin: 0},

  },
  work: function(my) {
    my.button.on('push', function() {
      my.laser.toggle();
    console.log("laser toggled");

    });

    every((1).seconds(), function() {
    //   console.log("Hello, human!");
    });

    var output_sound= function(color) {
    console.log(color + " detected");
    if (!talking){
        if (color === "red"){
          exec('sh red.sh',{silent:true});
        }
        if (color === "green"){
            exec('sh green.sh',{silent:true});
        }
        if (color === "blue"){
            exec('sh blue.sh',{silent:true});
        }
    }
    };

      my.tilt.on('push', function() {
          console.log("Tilt Activated");
          tilted = true;
      });
      my.tilt.on('release', function() {
          console.log("Tilt Deactivated");
          tilted = false;
      });

      var setRed = function(){
          my.redLed.turnOn()
          my.greenLed.turnOff()
          my.blueLed.turnOff()
      };
      var setBlue = function(){
          my.redLed.turnOff()
          my.greenLed.turnOff()
          my.blueLed.turnOn()
      }
      var setGreen = function(){
          my.redLed.turnOff()
          my.greenLed.turnOn()
          my.blueLed.turnOff()
      }
      var setOff = function(){
          my.redLed.turnOff()
          my.greenLed.turnOff()
          my.blueLed.turnOff()
      }

    var calibrate = function(cb){
            setRed();
            after((0.1).seconds(), function() {
                getReading(5, function(avgRead){
                    whiteArray.red = avgRead;
                    console.log("Set white red to "+avgRead);
                    setBlue();
                    after((0.1).seconds(), function() {
                        getReading(5, function(avgRead){
                            whiteArray.blue = avgRead;
                            console.log("Set white blue to "+avgRead);
                            setGreen();
                            after((0.1).seconds(), function() {
                                getReading(5, function(avgRead){
                                    whiteArray.green = avgRead;
                                    console.log("Set white green to "+avgRead);
                                    setOff();
                                    after((5).seconds(), function() {
                                        setRed();
                                        after((0.1).seconds(), function() {
                                            getReading(5, function(avgRead){
                                                blackArray.red = avgRead;
                                                console.log("Set black red to "+avgRead);
                                                setBlue();
                                                after((0.1).seconds(), function() {
                                                    getReading(5, function(avgRead){
                                                        blackArray.blue = avgRead;
                                                        console.log("Set black blue to "+avgRead);
                                                        setGreen();
                                                        after((0.1).seconds(), function() {
                                                            getReading(5, function(avgRead){
                                                                blackArray.green = avgRead;
                                                                console.log("Set black green to "+avgRead);
                                                                after((1).seconds(), function() {
                                                                    cb();
                                                                });
                                                            });
                                                        });
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        };

    var getReading = function(times, cb, tally, count){
        if (count ===0){
            var avgRead = (tally) / times;
            return cb(avgRead);
        }
        if (!tally){
            tally=0;
        }
        if (!count){
            count=times;
        }

        var reading = my.ambient.analogRead();
        tally = reading + tally;
        after((0.01).seconds(), function() {
            getReading(times, cb, tally, count-1);
        });
    };

    after((5).seconds(), function() {
        calibrate(function(){
            every((1).seconds(), function() {
            //   console.log("Check color");
                    setRed();
                    after((0.01).seconds(), function() {
                        getReading(5, function(avgRead){
                            colorArray.red = avgRead;
                            console.log("Set colorArray red to "+avgRead);
                            var greyDiff = whiteArray.red - blackArray.red;
                            colorArray.red = (colorArray.red - blackArray.red) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                            //for the current reflectivity(for the color it is exposed to) of what is being scanned
                            avgArray.red = (avgArray.red + colorArray.red) / 2;

                            setBlue();
                            after((0.01).seconds(), function() {
                                getReading(5, function(avgRead){
                                    colorArray.blue = avgRead;
                                    console.log("Set colorArray blue to "+avgRead);
                                    var greyDiff = whiteArray.blue - blackArray.blue;
                                    colorArray.blue = (colorArray.blue - blackArray.blue) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                                    //for the current reflectivity(for the color it is exposed to) of what is being scanned
                                    avgArray.blue = (avgArray.blue + colorArray.blue) / 2;
                                    setGreen();
                                    after((0.01).seconds(), function() {
                                        getReading(5, function(avgRead){
                                            colorArray.green = avgRead;
                                            console.log("Set colorArray green to "+avgRead);
                                            var greyDiff = whiteArray.green - blackArray.green;
                                            colorArray.green = (colorArray.green - blackArray.green) / (greyDiff) * 1024;//the reading returned minus the lowest value divided by the possible range multiplied by 1024 is a value roughly between 0-1024 representing the value
                                            //for the current reflectivity(for the color it is exposed to) of what is being scanned
                                            avgArray.green = (avgArray.green + colorArray.green) / 2;
                                            after((0.01).seconds(), function() {
                                                setOff();
                                                if(avgArray.red > avgArray.green && avgArray.red > avgArray.blue) {
                                                    console.log("Detected Red");
                                                    output_sound("red");
                                                }
                                                else if(avgArray.green > avgArray.red && avgArray.green > avgArray.blue) {
                                                    console.log("Detected Green");
                                                    output_sound("green");

                                                }
                                                else {
                                                    console.log("Detected Blue");
                                                    output_sound("blue");
                                                }

                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
              });
            });
        });

    } //end setup

}).start();
<|endoftext|>


<commit_before>"use strict";

const debug = require('debug')('bus-eta-bot-sg:inline_query_handler');
const telegram = require('../telegram');
const eta_query_result = require('./eta-query-result');

/**
 * Handler for inline queries
 * @param {Bot} bot
 * @param {InlineQuery} ilq
 */
module.exports = function (bot, ilq) {
  // things to show:
  // user's saved queries
  // user's history

  // filter by inline query on
  // saved queries: argstr and label
  // history: argstr

  // then generate InputTextMessageContent s for each of the matches and send it as an answer

  // first we need to fetch the users history and saved queries
  const user_id = ilq.user_id;

  return Promise.all([bot.datastore.getUserHistory(user_id), bot.datastore.getUserFavourites(user_id)])
    .then(data => {
      let [history, favourites] = data;

      // debug('history and favourites before filtering');
      // debug(history);
      // debug(favourites);

      // filter out all the argstrs in the user's history which include the inline query
      history = history.filter(argstr => argstr.includes(ilq.query));

      // filter out all the saved queries in the user's history with either
      // 1. have an argstr which starts with the inline query
      // 2. has a label which contains the inline query
      favourites = favourites.filter(({query, label}) => {
        const argstr_match = query.includes(ilq.query);
        const label_match = label.toUpperCase().includes(ilq.query.toUpperCase());

        return argstr_match || label_match;
      });

      // limit the number of saved queries we return (naively for now)
      // 5 is arbitarily chosen
      // history length is already at most 5
      favourites = favourites.slice(0, 5);

      // debug('history and favourites after filtering');
      // debug(history);
      // debug(favourites);

      // populate the inline query results
      // since this will require a datamall api call per result, it would be good to do it in parallel
      // each result will need an inputtextmessagecontent as well as reply_markup
      const results = [];

      // cache the results from the favourites in case one of the favourites argtrs is also in history
      const favourites_argstr_cache = {};

      // start with the matched saved queries
      for (const fav of favourites) {
        // the id is just the argstr we are querying for
        const id = fav.query;
        const title = fav.label;
        const options = {
          description: 'Saved query',
        };

        // check the favourites_argstr_cache if this argstr has already been looked up
        if (favourites_argstr_cache[fav.query]) {
          const {text, parse_mode, reply_markup} = favourites_argstr_cache[fav.query];
          const input_txt_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
          options.reply_markup = reply_markup;
          const result = Promise.resolve(new telegram.InlineQueryResultArticle(id, title, input_txt_msg_content, options));

          results.push(result);
        } else {
          const result = eta_query_result(fav.query)
            .then(({text, parse_mode, reply_markup}) => {
              // cache this result with the argstr as the key
              favourites_argstr_cache[fav.query] = {text, parse_mode, reply_markup};

              const input_txt_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
              options.reply_markup = reply_markup;
              return new telegram.InlineQueryResultArticle(id, title, input_txt_msg_content, options);
            });

          results.push(result);
        }
      }

      // add in the matched history argstrs
      for (const argstr of history) {
        // the id is just the argstr we are querying for
        const id = argstr;
        const title = argstr;
        const options = {
          description: 'History'
        };

        // check the favourites_argstr_cache if this argstr has already been looked up
        if (favourites_argstr_cache[argstr]) {
          const {text, parse_mode, reply_markup} = favourites_argstr_cache[argstr];
          const input_text_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
          options.reply_markup = reply_markup;
          const result = Promise.resolve(new telegram.InlineQueryResultArticle(id, title, input_text_msg_content, options));

          results.push(result);
        } else {
          const result = eta_query_result(argstr)
            .then(({text, parse_mode, reply_markup}) => {
              const input_text_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
              options.reply_markup = reply_markup;
              return new telegram.InlineQueryResultArticle(id, title, input_text_msg_content, options);
            });

          results.push(result);
        }
      }

      // resolve all the InlineQueryResults in the results
      return Promise.all(results)
        .then(results => {
          // set cache_time to 10 seconds since bus etas are extremely time sensitive
          return ilq.answerInlineQuery(results, {cache_time: 10, is_personal: true}).do();
        });
    })

    // analytics
    .then(() => Promise.all([bot.analytics.logAction('inline_query'), bot.analytics.logUser('inline_query', ilq)]))

    .catch(err => {
      debug(err);
      return bot.analytics.logError(err, err.message);
    });
};
<commit_msg>Implement making new eta queries directly through an inline query<commit_after>"use strict";

const debug = require('debug')('bus-eta-bot-sg:inline_query_handler');
const telegram = require('../telegram');
const eta_query_result = require('./eta-query-result');

const argstr_regex = /^\d{5}(?: \S+)*/;

/**
 * Handler for inline queries
 * @param {Bot} bot
 * @param {InlineQuery} ilq
 */
module.exports = function (bot, ilq) {
  // things to show:
  // user's saved queries
  // user's history

  // filter by inline query on
  // saved queries: argstr and label
  // history: argstr

  // then generate InputTextMessageContent s for each of the matches and send it as an answer

  // first we need to fetch the users history and saved queries
  const user_id = ilq.user_id;

  return Promise.all([bot.datastore.getUserHistory(user_id), bot.datastore.getUserFavourites(user_id)])
    .then(data => {
      let [history, favourites] = data;

      // debug('history and favourites before filtering');
      // debug(history);
      // debug(favourites);

      // filter out all the argstrs in the user's history which include the inline query
      history = history.filter(argstr => argstr.includes(ilq.query));

      // filter out all the saved queries in the user's history with either
      // 1. have an argstr which starts with the inline query
      // 2. has a label which contains the inline query
      favourites = favourites.filter(({query, label}) => {
        const argstr_match = query.includes(ilq.query);
        const label_match = label.toUpperCase().includes(ilq.query.toUpperCase());

        return argstr_match || label_match;
      });

      // limit the number of saved queries we return (naively for now)
      // 5 is arbitarily chosen
      // history length is already at most 5
      favourites = favourites.slice(0, 5);

      // debug('history and favourites after filtering');
      // debug(history);
      // debug(favourites);

      // populate the inline query results
      // since this will require a datamall api call per result, it would be good to do it in parallel
      // each result will need an inputtextmessagecontent as well as reply_markup
      const results = [];

      // cache the results from the favourites in case one of the favourites argtrs is also in history
      const argstr_cache = {};

      // start with the matched saved queries
      for (const fav of favourites) {
        // the id is just the argstr we are querying for
        const id = 'saved' + fav.query.slice(0, 32);
        const title = fav.label;
        const options = {
          description: 'Saved query',
        };

        // check the favourites_argstr_cache if this argstr has already been looked up
        if (argstr_cache[fav.query]) {
          const {text, parse_mode, reply_markup} = argstr_cache[fav.query];
          const input_txt_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
          options.reply_markup = reply_markup;
          const result = Promise.resolve(new telegram.InlineQueryResultArticle(id, title, input_txt_msg_content, options));

          results.push(result);
        } else {
          const result = eta_query_result(fav.query)
            .then(({text, parse_mode, reply_markup}) => {
              // cache this result with the argstr as the key
              argstr_cache[fav.query] = {text, parse_mode, reply_markup};

              const input_txt_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
              options.reply_markup = reply_markup;
              return new telegram.InlineQueryResultArticle(id, title, input_txt_msg_content, options);
            });

          results.push(result);
        }
      }

      // add in the matched history argstrs
      for (const argstr of history) {
        // the id is just the argstr we are querying for
        const id = 'history' + argstr.slice(0, 32);
        const title = argstr;
        const options = {
          description: 'History'
        };

        // check the favourites_argstr_cache if this argstr has already been looked up
        if (argstr_cache[argstr]) {
          const {text, parse_mode, reply_markup} = argstr_cache[argstr];
          const input_text_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
          options.reply_markup = reply_markup;
          const result = Promise.resolve(new telegram.InlineQueryResultArticle(id, title, input_text_msg_content, options));

          results.push(result);
        } else {
          const result = eta_query_result(argstr)
            .then(({text, parse_mode, reply_markup}) => {
              argstr_cache[argstr] = {text, parse_mode, reply_markup};

              const input_text_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
              options.reply_markup = reply_markup;
              return new telegram.InlineQueryResultArticle(id, title, input_text_msg_content, options);
            });

          results.push(result);
        }
      }

      // check if the query is a new argstr
      if (argstr_regex.exec(ilq.query) !== null) {
        // if it is, we query it as well but we need to check later if it returned any etas
        const id = 'new_query' + ilq.query.slice(0, 32);
        const title = ilq.query;
        const options = {
          description: 'New query'
        };

        const result = Promise.resolve()
          .then(() => {
            if (argstr_cache[ilq.query]) {
              return argstr_cache[ilq.query];
            } else {
              return eta_query_result(ilq.query);
            }
          })
          .then(({text, parse_mode, reply_markup}) => {
            const input_text_msg_content = new telegram.InputTextMessageContent(text, {parse_mode});
            options.reply_markup = reply_markup;
            return new telegram.InlineQueryResultArticle(id, title, input_text_msg_content, options);
          })
          .catch(err => {
            if (err === 'no_etas') {
              return null;
            } else {
              throw err;
            }
          });

        results.unshift(result);
      }

      // resolve all the InlineQueryResults in the results
      return Promise.all(results)
        .then(results => {
          // shift the first element of results out if it is null
          if (results[0] === null) {
            results.shift();
          }

          // set cache_time to 10 seconds since bus etas are extremely time sensitive
          return ilq.answerInlineQuery(results, {cache_time: 10, is_personal: true}).do();
        })
        .catch(err => debug(err));
    })

    // analytics
    .then(() => Promise.all([bot.analytics.logAction('inline_query'), bot.analytics.logUser('inline_query', ilq)]))

    .catch(err => {
      debug(err);
      return bot.analytics.logError(err, err.message);
    });
};
<|endoftext|>


<commit_before>import React from 'react';
import GitHubCorner from 'react-github-corner';

const Header = () => (

    <GitHubCorner
      href="https://github.com/wKovacs64/meetup-raffle"
      octoColor="#f4f4f4"
      bannerColor="#111"
    />

            🤝
          {' '}
          meetup-raffle{' '}

            🎟

          Draw raffle winners at your Meetup event

);

Header.displayName = 'Header';

export default Header;
<commit_msg>fix(a11y): hide header emojis from screen readers (#131)<commit_after>import React from 'react';
import GitHubCorner from 'react-github-corner';

const Header = () => (

    <GitHubCorner
      href="https://github.com/wKovacs64/meetup-raffle"
      octoColor="#f4f4f4"
      bannerColor="#111"
    />

            🤝
          {' '}
          meetup-raffle{' '}

            🎟

          Draw raffle winners at your Meetup event

);

Header.displayName = 'Header';

export default Header;
<|endoftext|>


<commit_before>'use strict';

let _ = require('underscore');
let cli = require('heroku-cli-util');

let VERSION = "v0";
let DEFAULT_HOST = "postgres-api.heroku.com";

function HerokuKafkaClusters(heroku, env, context) {
  this.heroku = heroku;
  this.env = env;
  this.context = context;
  this.app = context.app;
}

HerokuKafkaClusters.prototype.info = function* (cluster) {
  var that = this;
  var addons = yield this.addonsForManyClusterCommand(cluster);
  var responses = yield _.map(addons, function(addon) {
    return that.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}`
    });
  });
  return responses;
};

HerokuKafkaClusters.prototype.topic = function* (cluster, topic) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    return yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topic}`
    });
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.topics = function* (cluster) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    return yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics`
    });
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.fail = function* (cluster, catastrophic, zk) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'POST',
      body: { catastrophic: catastrophic, zookeeper: zk },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/induce-failure`
    });
    return response;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addon.available.map(function (addon) { return addon.addon_service.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.waitStatus = function* (cluster) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/wait_status`
    });
    return response;
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.createTopic = function* (cluster, topicName, flags) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'POST',
      body: {
        topic:
          {
            name: topicName,
            retention_time_ms: flags['retention-time'],
            replication_factor: flags['replication-factor'],
            partition_count: flags['partitions'],
            compaction: flags['compaction'] || false
          }
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.configureTopic = function* (cluster, topicName, flags) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'PUT',
      body: {
        topic:
          _.extend({
            name: topicName,
            retention_time_ms: flags['retention-time']
          }, this.compactionSettingFromFlags(flags))
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topicName}`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.compactionSettingFromFlags = function* (flags) {
  if (flags['no-compaction']) {
    return { compaction: false };
  } else if (flags['compaction']) {
    return { compaction: true };
  } else {
    return {};
  }
};

HerokuKafkaClusters.prototype.deleteTopic = function* (cluster, topicName) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'DELETE',
      body: {
        topic: { name: topicName }
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topicName}`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.request = function (params) {
  cli.hush(`picked shogun host: ${this.host()}`);
  var defaultParams = {
    host: this.host(),
    auth: `${this.context.auth.username}:${this.context.auth.password}`,
    accept: 'application/json'
  };
  return this.heroku.request(_.extend(defaultParams, params));
};

HerokuKafkaClusters.prototype.handleResponse = function (response) {
  if (response.statusCode >= 400 || response.statusCode <= 499) {
    return response.body.message;
  } else if (response.statusCode == undefined || (response.statusCode < 300 && response.statusCode >= 200)) {
    return null;
  } else {
    cli.hush("Error connecting to backend API");
    return "Error, please try again later.";
  }
};

HerokuKafkaClusters.prototype.host = function () {
  if (this.env.SHOGUN) {
    return `shogun-${this.env.SHOGUN}.herokuapp.com`;
  } else if (this.env.DEPLOY) {
    return `shogun-${this.env.DEPLOY}.herokuapp.com`;
  } else {
    return DEFAULT_HOST;
  }
};

HerokuKafkaClusters.prototype.addonsForManyClusterCommand = function* (cluster) {
  var addons = yield this.addons();
  var filteredAddons;
  if (cluster === undefined) {
    filteredAddons = addons.kafkas;
  } else {
    filteredAddons = this.findByClusterName(addons, cluster);
  }
  if (filteredAddons.length !== 0) {
    return filteredAddons;
  } else if (cluster !== undefined) {
    cli.error(`couldn't find the kafka cluster ${cluster}, but found these addons instead: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.addonForSingleClusterCommand = function* (cluster) {
  var addons = yield this.addons();
  var addon;
  if (addons.kafkas.length === 1 && cluster === undefined) {
    addon = addons.kafkas[0];
  } else {
    addon = this.findByClusterName(addons, cluster)[0];
  }
  if (addon) {
    return addon;
  } else if (cluster !== undefined) {
    cli.error(`couldn't find the kafka cluster ${cluster}, but found these addons instead: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else if (addons.kafkas.length !== 1) {
    cli.error(`please specify a kafka cluster. Possible clusters: ${addons.kafkas.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.findByClusterName = function (addons, cluster) {
  return addons.kafkas.filter(function (addon) { return _.contains(addon.config_vars, cluster) || addon.name == cluster; });
};

HerokuKafkaClusters.prototype.addons = function* () {
  let allAddons = yield this.heroku.apps(this.app).addons().listByApp();
  let kafkaAddons = allAddons.filter(function (addon) { return addon.addon_service.name.startsWith('heroku-kafka'); });
  return {
    kafkas: kafkaAddons,
    allAddons: allAddons
  };
};

module.exports = {
  HerokuKafkaClusters: HerokuKafkaClusters
};
<commit_msg>use kafka api host<commit_after>'use strict';

let _ = require('underscore');
let cli = require('heroku-cli-util');

let VERSION = "v0";
let DEFAULT_HOST = "kafka-api.heroku.com";

function HerokuKafkaClusters(heroku, env, context) {
  this.heroku = heroku;
  this.env = env;
  this.context = context;
  this.app = context.app;
}

HerokuKafkaClusters.prototype.info = function* (cluster) {
  var that = this;
  var addons = yield this.addonsForManyClusterCommand(cluster);
  var responses = yield _.map(addons, function(addon) {
    return that.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}`
    });
  });
  return responses;
};

HerokuKafkaClusters.prototype.topic = function* (cluster, topic) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    return yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topic}`
    });
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.topics = function* (cluster) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    return yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics`
    });
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.fail = function* (cluster, catastrophic, zk) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'POST',
      body: { catastrophic: catastrophic, zookeeper: zk },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/induce-failure`
    });
    return response;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addon.available.map(function (addon) { return addon.addon_service.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.waitStatus = function* (cluster) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/wait_status`
    });
    return response;
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.createTopic = function* (cluster, topicName, flags) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'POST',
      body: {
        topic:
          {
            name: topicName,
            retention_time_ms: flags['retention-time'],
            replication_factor: flags['replication-factor'],
            partition_count: flags['partitions'],
            compaction: flags['compaction'] || false
          }
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.configureTopic = function* (cluster, topicName, flags) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'PUT',
      body: {
        topic:
          _.extend({
            name: topicName,
            retention_time_ms: flags['retention-time']
          }, this.compactionSettingFromFlags(flags))
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topicName}`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.compactionSettingFromFlags = function* (flags) {
  if (flags['no-compaction']) {
    return { compaction: false };
  } else if (flags['compaction']) {
    return { compaction: true };
  } else {
    return {};
  }
};

HerokuKafkaClusters.prototype.deleteTopic = function* (cluster, topicName) {
  var addon = yield this.addonForSingleClusterCommand(cluster);
  if (addon) {
    var response = yield this.request({
      method: 'DELETE',
      body: {
        topic: { name: topicName }
      },
      path: `/client/kafka/${VERSION}/clusters/${addon.name}/topics/${topicName}`
    }).catch(function (err) { return err; });
    return this.handleResponse(response);
  } else {
    return null;
  }
};

HerokuKafkaClusters.prototype.request = function (params) {
  cli.hush(`picked shogun host: ${this.host()}`);
  var defaultParams = {
    host: this.host(),
    auth: `${this.context.auth.username}:${this.context.auth.password}`,
    accept: 'application/json'
  };
  return this.heroku.request(_.extend(defaultParams, params));
};

HerokuKafkaClusters.prototype.handleResponse = function (response) {
  if (response.statusCode >= 400 || response.statusCode <= 499) {
    return response.body.message;
  } else if (response.statusCode == undefined || (response.statusCode < 300 && response.statusCode >= 200)) {
    return null;
  } else {
    cli.hush("Error connecting to backend API");
    return "Error, please try again later.";
  }
};

HerokuKafkaClusters.prototype.host = function () {
  if (this.env.SHOGUN) {
    return `shogun-${this.env.SHOGUN}.herokuapp.com`;
  } else if (this.env.DEPLOY) {
    return `shogun-${this.env.DEPLOY}.herokuapp.com`;
  } else {
    return DEFAULT_HOST;
  }
};

HerokuKafkaClusters.prototype.addonsForManyClusterCommand = function* (cluster) {
  var addons = yield this.addons();
  var filteredAddons;
  if (cluster === undefined) {
    filteredAddons = addons.kafkas;
  } else {
    filteredAddons = this.findByClusterName(addons, cluster);
  }
  if (filteredAddons.length !== 0) {
    return filteredAddons;
  } else if (cluster !== undefined) {
    cli.error(`couldn't find the kafka cluster ${cluster}, but found these addons instead: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.addonForSingleClusterCommand = function* (cluster) {
  var addons = yield this.addons();
  var addon;
  if (addons.kafkas.length === 1 && cluster === undefined) {
    addon = addons.kafkas[0];
  } else {
    addon = this.findByClusterName(addons, cluster)[0];
  }
  if (addon) {
    return addon;
  } else if (cluster !== undefined) {
    cli.error(`couldn't find the kafka cluster ${cluster}, but found these addons instead: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else if (addons.kafkas.length !== 1) {
    cli.error(`please specify a kafka cluster. Possible clusters: ${addons.kafkas.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  } else {
    cli.error(`kafka addon not found, but found these addons: ${addons.allAddons.map(function (addon) { return addon.name; }).join(',')}`);
    return null;
  }
};

HerokuKafkaClusters.prototype.findByClusterName = function (addons, cluster) {
  return addons.kafkas.filter(function (addon) { return _.contains(addon.config_vars, cluster) || addon.name == cluster; });
};

HerokuKafkaClusters.prototype.addons = function* () {
  let allAddons = yield this.heroku.apps(this.app).addons().listByApp();
  let kafkaAddons = allAddons.filter(function (addon) { return addon.addon_service.name.startsWith('heroku-kafka'); });
  return {
    kafkas: kafkaAddons,
    allAddons: allAddons
  };
};

module.exports = {
  HerokuKafkaClusters: HerokuKafkaClusters
};
<|endoftext|>


<commit_before>const themes = require('../../themes')
const tools = require('../../tools')

const _ = require('lodash')
const chalk = require('chalk')
const needle = require('needle')
const noon = require('noon')
const xml2js = require('xml2js')

const CFILE = `${process.env.HOME}/.leximaven.noon`

exports.command = 'origin <word>'
exports.desc = 'Wordnik etymologies'
exports.builder = {
  out: {
    alias: 'o',
    desc: 'Write cson, json, noon, plist, yaml, xml',
    default: '',
    type: 'string',
  },
  force: {
    alias: 'f',
    desc: 'Force overwriting outfile',
    default: false,
    type: 'boolean',
  },
  save: {
    alias: 's',
    desc: 'Save flags to config file',
    default: false,
    type: 'boolean',
  },
  canon: {
    alias: 'c',
    desc: 'Use canonical',
    default: false,
    type: 'boolean',
  },
}
exports.handler = (argv) => {
  tools.checkConfig(CFILE)
  let config = noon.load(CFILE)
  const userConfig = {
    origin: {
      canon: argv.c,
    },
  }
  if (config.merge) config = _.merge({}, config, userConfig)
  const theme = themes.loadTheme(config.theme)
  if (config.verbose) themes.labelDown('Wordnik', theme, null)
  const word = argv.word
  const task = 'etymologies'
  const prefix = 'http://api.wordnik.com:80/v4/word.json/'
  const apikey = process.env.WORDNIK
  const uri = `${prefix}${word}/${task}?`
  const pcont = []
  pcont.push(`useCanonical=${config.origin.canon}&`)
  pcont.push(`api_key=${apikey}`)
  const rest = pcont.join('')
  let url = `${uri}${rest}`
  url = encodeURI(url)
  const parser = new xml2js.Parser()
  const tofile = { type: 'etymology', source: 'http://www.wordnik.com' }
  const ctstyle = _.get(chalk, theme.content.style)
  needle.get(url, (error, response) => {
    if (!error && response.statusCode === 200) {
      const resp = response.body
      const origin = resp[0]
      console.log(origin)
      parser.parseString(origin, (err, result) => {
        const root = result.ety
        const content = root._
        let ets = root.ets
        ets = ets.join(', ')
        themes.labelRight('Etymology', theme, ctstyle(`${content} ${ets}`))
        tofile.etymology = content
        tofile.source = ets
      })
      if (argv.o) tools.outFile(argv.o, argv.f, tofile)
      if (argv.s && config.merge) noon.save(CFILE, config)
      if (argv.s && !config.merge) console.err(chalk.red('Set option merge to true!'))
    } else {
      console.error(`${chalk.red.bold(`HTTP ${response.statusCode}:`)} ${chalk.red(error)}`)
    }
  })
}
<commit_msg>fix(origin): fix output<commit_after>const themes = require('../../themes')
const tools = require('../../tools')

const _ = require('lodash')
const chalk = require('chalk')
const needle = require('needle')
const noon = require('noon')
const xml2js = require('xml2js')

const CFILE = `${process.env.HOME}/.leximaven.noon`

exports.command = 'origin <word>'
exports.desc = 'Wordnik etymologies'
exports.builder = {
  out: {
    alias: 'o',
    desc: 'Write cson, json, noon, plist, yaml, xml',
    default: '',
    type: 'string',
  },
  force: {
    alias: 'f',
    desc: 'Force overwriting outfile',
    default: false,
    type: 'boolean',
  },
  save: {
    alias: 's',
    desc: 'Save flags to config file',
    default: false,
    type: 'boolean',
  },
  canon: {
    alias: 'c',
    desc: 'Use canonical',
    default: false,
    type: 'boolean',
  },
}
exports.handler = (argv) => {
  tools.checkConfig(CFILE)
  let config = noon.load(CFILE)
  const userConfig = {
    origin: {
      canon: argv.c,
    },
  }
  if (config.merge) config = _.merge({}, config, userConfig)
  const theme = themes.loadTheme(config.theme)
  if (config.verbose) themes.labelDown('Wordnik', theme, null)
  const word = argv.word
  const task = 'etymologies'
  const prefix = 'http://api.wordnik.com:80/v4/word.json/'
  const apikey = process.env.WORDNIK
  const uri = `${prefix}${word}/${task}?`
  const pcont = []
  pcont.push(`useCanonical=${config.origin.canon}&`)
  pcont.push(`api_key=${apikey}`)
  const rest = pcont.join('')
  let url = `${uri}${rest}`
  url = encodeURI(url)
  const parser = new xml2js.Parser()
  const tofile = { type: 'etymology', source: 'http://www.wordnik.com' }
  const ctstyle = _.get(chalk, theme.content.style)
  needle.get(url, (error, response) => {
    if (!error && response.statusCode === 200) {
      const resp = response.body
      const origin = resp[0]
      parser.parseString(origin, (err, result) => {
        const root = result.ety
        const content = root._
        let ets = root.ets
        ets = ets.join(', ')
        themes.labelRight('Etymology', theme, ctstyle(`${content} ${ets}`))
        tofile.etymology = content
        tofile.source = ets
      })
      if (argv.o) tools.outFile(argv.o, argv.f, tofile)
      if (argv.s && config.merge) noon.save(CFILE, config)
      if (argv.s && !config.merge) console.err(chalk.red('Set option merge to true!'))
    } else {
      console.error(`${chalk.red.bold(`HTTP ${response.statusCode}:`)} ${chalk.red(error)}`)
    }
  })
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var async = require('async');
var execFile = require('child_process').execFile;
var hb = require('handlebars');

module.exports = {
    name:'template',
    description:'A command to allow generic, template driven creation of new services and apps',
    example:'bosco template | bosco template add|remove <githubRepo> | bosco template new <templateName> <serviceName>',
    cmd:cmd
}

function cmd(bosco, args, next) {
  var action = args.shift();
  if(action == 'create') { return newServiceFromTemplate(bosco, args, next); }
  if(action == 'add') { return addTemplate(bosco, args, next); }
  if(action == 'remove') { return removeTemplate(bosco, args, next); }
  listTemplates(bosco, next);
}

function listTemplates(bosco, next) {

  var templates = bosco.config.get('templates');

  bosco.log('Your current templates are:');
  _.each(templates, function(template) {
    bosco.log(' - ' + template.green);
  });

  bosco.log('Use the command: ' + 'bosco template add <githubRepo>'.green + ' to add to your template list.')
  if(next) { next(); }

}

function newServiceFromTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];

    var templateRepoName = args.shift();
    var targetServiceName = args.shift();
    var targetServicePort = args.shift();

    if(!templateRepoName || !targetServiceName || !targetServicePort) {
        return bosco.log('You need to specify a template, a target service name and a port: ' + 'bosco template create <githubRepo> <serviceName> <port>'.green);
    }

    var template = _.filter(templates, function(item) { return item.match(new RegExp(templateRepoName)); })[0];

    if(!template) {
      bosco.log('Couldnt find a service that matched: ' + templateRepoName.red);
      return listTemplates(bosco, next);
    }

    bosco.log('Creating new service: ' + targetServiceName.green + ' from template: ' + template.green);

    var gitCmd = 'git';
    var gitOptions = ['clone','--depth=1','git@github.com:' + template, targetServiceName];

    var serviceDirectory = path.resolve('.', targetServiceName);

    async.series([
      async.apply(execCmd, bosco, gitCmd, gitOptions, path.resolve('.')),
      async.apply(execCmd, bosco, 'rm',['-rf','.git'], serviceDirectory),
      async.apply(execCmd, bosco, 'git',['init'], serviceDirectory),
      async.apply(copyTemplateFiles, bosco, targetServiceName, targetServicePort, serviceDirectory),
      async.apply(execCmd, bosco, 'git',['add','--all','.'], serviceDirectory),
      async.apply(execCmd, bosco, 'git',['commit','-am','"First commit"'], serviceDirectory)
    ], function(err) {
      if(err) {
        return bosco.error(err.message);
      }
      bosco.log('Complete!');
    });

}

function copyTemplateFiles(bosco, serviceName, port, serviceDirectory, next) {

  var templateFiles = require(path.join(serviceDirectory, 'bosco-templates.json'));
  var variables = {
    serviceName: serviceName,
    serviceShortName: getShortName(serviceName),
    user: bosco.config.get('github:user'),
    port: port
  }
  async.map(templateFiles, function(template, cb) {
    if(!template.source || !template.destination) {
      return cb(new Error('You must specify both a source and destination'));
    }

    bosco.log('Applying template for file: ' + template.destination.green);

    try {
      var destination = hb.compile(template.destination)(variables);
      var source = hb.compile(template.source)(variables);
      var templateContent = fs.readFileSync(path.join(serviceDirectory, source));
      var outputContent = hb.compile(templateContent.toString())(variables);
      fs.writeFileSync(path.join(serviceDirectory, destination), outputContent);
    } catch(ex) {
      bosco.error('There has been an error applying the templates, check the configuration of the template project.');
      return cb(ex);
    }

    cb();

  }, next);

}

function getShortName(service) {
  service = service.replace(/^app\-/,'');
  service = service.replace(/^service\-/,'');
  return service;
}

function addTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];
    var templateRepo = args.shift();

    templates.push(templateRepo);
    bosco.config.set('templates', _.uniq(templates));

    bosco.config.save(function() {
      bosco.log('Added new template.');
      if(next) { next(); }
    });

}

function removeTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];
    var templateRepo = args.shift();

    _.pull(templates, templateRepo);

    bosco.config.set('templates', templates);

    bosco.config.save(function() {
      bosco.log('Removed any matching templates.');
      if(next) { next(); }
    });

}

function execCmd(bosco, cmd, params, cwd, next) {
  execFile(cmd, params, {
    cwd: cwd
  }, function(err, stdout, stderr) {
      next(err, stdout + stderr);
  });
}

<commit_msg>Amends to template command, better commit msg and cleaning up traces of template<commit_after>var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var async = require('async');
var execFile = require('child_process').execFile;
var hb = require('handlebars');

module.exports = {
    name:'template',
    description:'A command to allow generic, template driven creation of new services and apps',
    example:'bosco template | bosco template add|remove <githubRepo> | bosco template new <templateName> <serviceName>',
    cmd:cmd
}

function cmd(bosco, args, next) {
  var action = args.shift();
  if(action == 'create') { return newServiceFromTemplate(bosco, args, next); }
  if(action == 'add') { return addTemplate(bosco, args, next); }
  if(action == 'remove') { return removeTemplate(bosco, args, next); }
  listTemplates(bosco, next);
}

function listTemplates(bosco, next) {

  var templates = bosco.config.get('templates');

  bosco.log('Your current templates are:');
  _.each(templates, function(template) {
    bosco.log(' - ' + template.green);
  });

  bosco.log('Use the command: ' + 'bosco template add <githubRepo>'.green + ' to add to your template list.')
  if(next) { next(); }

}

function newServiceFromTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];

    var templateRepoName = args.shift();
    var targetServiceName = args.shift();
    var targetServicePort = args.shift();

    if(!templateRepoName || !targetServiceName || !targetServicePort) {
        return bosco.log('You need to specify a template, a target service name and a port: ' + 'bosco template create <githubRepo> <serviceName> <port>'.green);
    }

    var template = _.filter(templates, function(item) { return item.match(new RegExp(templateRepoName)); })[0];

    if(!template) {
      bosco.log('Couldnt find a service that matched: ' + templateRepoName.red);
      return listTemplates(bosco, next);
    }

    bosco.log('Creating new service: ' + targetServiceName.green + ' from template: ' + template.green);

    var gitCmd = 'git';
    var gitOptions = ['clone','--depth=1','git@github.com:' + template, targetServiceName];

    var serviceDirectory = path.resolve('.', targetServiceName);

    async.series([
      async.apply(execCmd, bosco, gitCmd, gitOptions, path.resolve('.')),
      async.apply(execCmd, bosco, 'rm',['-rf','.git'], serviceDirectory),
      async.apply(execCmd, bosco, 'git',['init'], serviceDirectory),
      async.apply(copyTemplateFiles, bosco, targetServiceName, targetServicePort, serviceDirectory),
      async.apply(execCmd, bosco, 'rm',['-rf','templates'], serviceDirectory),
      async.apply(execCmd, bosco, 'rm',['-f','bosco-templates.json'], serviceDirectory),
      async.apply(execCmd, bosco, 'git',['add','--all','.'], serviceDirectory),
      async.apply(execCmd, bosco, 'git',['commit','-m','First commit'], serviceDirectory)
    ], function(err) {
      if(err) {
        return bosco.error(err.message);
      }
      bosco.log('Complete!');
    });

}

function copyTemplateFiles(bosco, serviceName, port, serviceDirectory, next) {

  var templateFiles = require(path.join(serviceDirectory, 'bosco-templates.json'));
  var variables = {
    serviceName: serviceName,
    serviceShortName: getShortName(serviceName),
    user: bosco.config.get('github:user'),
    port: port
  }
  async.map(templateFiles, function(template, cb) {
    if(!template.source || !template.destination) {
      return cb(new Error('You must specify both a source and destination'));
    }

    bosco.log('Applying template for file: ' + template.destination.green);

    try {
      var destination = hb.compile(template.destination)(variables);
      var source = hb.compile(template.source)(variables);
      var templateContent = fs.readFileSync(path.join(serviceDirectory, source));
      var outputContent = hb.compile(templateContent.toString())(variables);
      fs.writeFileSync(path.join(serviceDirectory, destination), outputContent);
    } catch(ex) {
      bosco.error('There has been an error applying the templates, check the configuration of the template project.');
      return cb(ex);
    }

    cb();

  }, next);

}

function getShortName(service) {
  service = service.replace(/^app\-/,'');
  service = service.replace(/^service\-/,'');
  return service;
}

function addTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];
    var templateRepo = args.shift();

    templates.push(templateRepo);
    bosco.config.set('templates', _.uniq(templates));

    bosco.config.save(function() {
      bosco.log('Added new template.');
      if(next) { next(); }
    });

}

function removeTemplate(bosco, args, next) {

    var templates = bosco.config.get('templates') || [];
    var templateRepo = args.shift();

    _.pull(templates, templateRepo);

    bosco.config.set('templates', templates);

    bosco.config.save(function() {
      bosco.log('Removed any matching templates.');
      if(next) { next(); }
    });

}

function execCmd(bosco, cmd, params, cwd, next) {
  execFile(cmd, params, {
    cwd: cwd
  }, function(err, stdout, stderr) {
      next(err, stdout + stderr);
  });
}

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Button, Tabs, Input, Col, Select, Form, Pagination, Dropdown, Menu } from 'antd';
import { withRouter, withCollections, Link } from 'olymp';
import { createComponent } from 'react-fela';
import capitalize from 'lodash/upperFirst';

const StyledHeader = createComponent(() => ({
  marginBottom: '0px',
  marginTop: '6px',
  fontSize: '1.25rem'
}), props =>
);
const StyledForm = createComponent(() => ({
  padding: '20px!important',
  paddingBottom: '14px!important',
  borderWidth: '0!important',
}), props =>
);

const StyledButtonGroup = createComponent(() => ({
  // borderWidth: '0!important',
}), props => <Button.Group {...props} />);

const Panel = createComponent(({ seperator, align, padding, background }) => ({
  padding: padding || '5px 10px',
  borderTop: seperator ? '1px solid #e6e6e6' : 0,
  textAlign: align,
  backgroundColor: background,
}));

@withRouter
@withCollections
export default class SidebarHeader extends Component {
  renderSelect() {
    const { collectionTree, router, activePage, location } = this.props;
    const { pathname } = location;

    return (
      <Menu style={{ minWidth: 150 }}>
        {Object.keys(collectionTree).map((key) => {
          const wrapper = children => (
            <Menu.SubMenu key={key} title={capitalize(key)}>
              {children}
            </Menu.SubMenu>
          );
          const groupItem = (
            (collectionTree[key] || []).map(({ name, title }) => (
              <Menu.Item key={`/@/${name}`}>
                <Link to={{ pathname, query: { [`@${name.toLowerCase()}`]: null } }}>
                  {capitalize(title || name)}
                </Link>
              </Menu.Item>
            ))
          );

          return collectionTree[key].length === 1 ? groupItem : wrapper(groupItem);
        })}
        <Menu.Divider />
        <Menu.Item key="mediathek">
          <Link to={{ pathname, query: { '@media': null } }}>
            Mediathek
          </Link>
        </Menu.Item>
        <Menu.Item key="/@/users" disabled>Benutzer</Menu.Item>
        <Menu.Item key="/@/analytics" disabled>Statistik</Menu.Item>
        <Menu.Item key="page-settings" disabled>Einstellungen</Menu.Item>
        <Menu.Item key="user" disabled>Profil</Menu.Item>
      </Menu>
    );
  }

  render() {
    const { items, page, pageSize, setPage, searchFn, searchText, filter, filtering, setQueryToState, actions, states } = this.props;

    return (

              </Dropdown>
            </Col>
            <Col span="5">

            </Col>
          </Input.Group>
        </StyledForm>

        <Panel seperator>
          <Input.Group>
            <Col span="18">
              <Input onChange={searchFn} value={searchText} placeholder="Suche ..." />
            </Col>
            <Col span="6" className="pr-0">
              {filter && (filtering ? (
                <Button onClick={e => setQueryToState()} style={{ width: '100%' }}>Reset</Button>
              ) : (
                <Dropdown overlay={filter}>
                  <Button style={{ width: '100%' }}>Filter</Button>
                </Dropdown>
              ))}
            </Col>
          </Input.Group>
        </Panel>

        {!filtering && !!states && (
          <Panel seperator>
            <Tabs onChange={eq => setQueryToState(eq)} style={{ marginBottom: -16 }}>
              {Object.keys(states).map(name => <Tabs.TabPane tab={states[name]} key={name} />)}
            </Tabs>
          </Panel>
        )}

        {!!(page > 1 || (items || []).length > pageSize) && (
          <Panel>
            <Pagination size="small" current={page} onChange={setPage} defaultPageSize={pageSize} total={items && items.length} />
          </Panel>
        )}

    );
  }
}
<commit_msg>Fix title!<commit_after>import React, { Component } from 'react';
import { Button, Tabs, Input, Col, Select, Form, Pagination, Dropdown, Menu } from 'antd';
import { withRouter, withCollections, Link } from 'olymp';
import { createComponent } from 'react-fela';
import capitalize from 'lodash/upperFirst';

const StyledHeader = createComponent(() => ({
  marginBottom: '0px',
  marginTop: '6px',
  fontSize: '1.25rem'
}), props =>
);
const StyledForm = createComponent(() => ({
  padding: '20px!important',
  paddingBottom: '14px!important',
  borderWidth: '0!important',
}), props =>
);

const StyledButtonGroup = createComponent(() => ({
  // borderWidth: '0!important',
}), props => <Button.Group {...props} />);

const Panel = createComponent(({ seperator, align, padding, background }) => ({
  padding: padding || '5px 10px',
  borderTop: seperator ? '1px solid #e6e6e6' : 0,
  textAlign: align,
  backgroundColor: background,
}));

@withRouter
@withCollections
export default class SidebarHeader extends Component {
  renderSelect() {
    const { collectionTree, router, activePage, location } = this.props;
    const { pathname } = location;

    return (
      <Menu style={{ minWidth: 150 }}>
        {Object.keys(collectionTree).map((key) => {
          const wrapper = children => (
            <Menu.SubMenu key={key} title={capitalize(key)}>
              {children}
            </Menu.SubMenu>
          );
          const groupItem = (
            (collectionTree[key] || []).map(({ name, title }) => (
              <Menu.Item key={`/@/${name}`}>
                <Link to={{ pathname, query: { [`@${name.toLowerCase()}`]: null } }}>
                  {capitalize(title || name)}
                </Link>
              </Menu.Item>
            ))
          );

          return collectionTree[key].length === 1 ? groupItem : wrapper(groupItem);
        })}
        <Menu.Divider />
        <Menu.Item key="mediathek">
          <Link to={{ pathname, query: { '@media': null } }}>
            Mediathek
          </Link>
        </Menu.Item>
        <Menu.Item key="/@/users" disabled>Benutzer</Menu.Item>
        <Menu.Item key="/@/analytics" disabled>Statistik</Menu.Item>
        <Menu.Item key="page-settings" disabled>Einstellungen</Menu.Item>
        <Menu.Item key="user" disabled>Profil</Menu.Item>
      </Menu>
    );
  }

  render() {
    const { items, page, pageSize, setPage, searchFn, searchText, filter, filtering, setQueryToState, actions, states, activePage } = this.props;

    return (

              </Dropdown>
            </Col>
            <Col span="5">

            </Col>
          </Input.Group>
        </StyledForm>

        <Panel seperator>
          <Input.Group>
            <Col span="18">
              <Input onChange={searchFn} value={searchText} placeholder="Suche ..." />
            </Col>
            <Col span="6" className="pr-0">
              {filter && (filtering ? (
                <Button onClick={e => setQueryToState()} style={{ width: '100%' }}>Reset</Button>
              ) : (
                <Dropdown overlay={filter}>
                  <Button style={{ width: '100%' }}>Filter</Button>
                </Dropdown>
              ))}
            </Col>
          </Input.Group>
        </Panel>

        {!filtering && !!states && (
          <Panel seperator>
            <Tabs onChange={eq => setQueryToState(eq)} style={{ marginBottom: -16 }}>
              {Object.keys(states).map(name => <Tabs.TabPane tab={states[name]} key={name} />)}
            </Tabs>
          </Panel>
        )}

        {!!(page > 1 || (items || []).length > pageSize) && (
          <Panel>
            <Pagination size="small" current={page} onChange={setPage} defaultPageSize={pageSize} total={items && items.length} />
          </Panel>
        )}

    );
  }
}
<|endoftext|>