<commit_before>import PARAMETERS from '../store/parameters'
import { routing, MAIN_PATHS } from './routes'
import { CONTENT_REDIRECT_LINKS } from '../shared/config/config'

const { VIEW, VIEW_CENTER, LAYERS, LEGEND, ZOOM, EMBED } = PARAMETERS

// This are the known broken legacy links
const legacyRoutes = [
  // https://www.parool.nl/amsterdam/kaart-met-onontplofte-bommen-in-amsterdam-nu-openbaar~a4539314/
  {
    from:
      '/#?mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.telegraaf.nl/nieuws/1256075/ligt-er-een-bom-uit-woii-in-je-achtertuin-met-deze-kaart-kom-je-er-achter
  {
    from:
      '/#?mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.amsterdamsdagblad.nl/gemeente/duizend-bommen-en-granaten-de-bommenkaart
  {
    from:
      '/#?mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://intranet.alliander.com/blog/${VIEW}/5359847/kaart-met-onontplofte-bommen-in-amsterdam
  {
    from:
      '/#?mpb=topografie&mpz=14&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3889979:4.9094038&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/?_sp=144b47f5-2817-4a1f-888c-d1d1b69c89cb.1510908859477#?ate=T&mpb=topografie&mpz=14&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3889979:4.9094038&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.amsterdam.nl/ondernemen/biz/
  {
    from: '/#?mpb=topografie&mpz=9&mpfs=T&mpo=biz::T&mpv=52.3676245:4.8804992&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=biz%3A1&${LEGEND}=true&${ZOOM}=9`,
  },
  {
    from: '/#?ate=T&mpb=topografie&mpz=9&mpfs=T&mpo=biz::T&mpv=52.3676245:4.8804992&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart&${EMBED}=true&${LAYERS}=biz%3A1&${LEGEND}=true&${ZOOM}=9`,
  },
  // home map
  {
    from: '/#?mpb=topografie&mpz=11&mpfs=T&mpv=52.3731081:4.8932945&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart`,
  },
]
const shortUrls = [
  {
    from: '/themakaart/taxi/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=oovtig%3A1%7Cvezips%3A1%7Cmzt%3A0%7Cslpb%3A1%7Cslpnb%3A1%7Cbgt%3A1%7Ctar%3A1%7Cpvrts%3A1%7Cpvrll%3A1%7Cpvrpr%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/veiligheid-en-overlast/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=oovorlv%3A1%7Coovoalco%3A1%7Coovctg%3A1%7Coovodlrs%3A1%7Coovoalg%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/logistiek/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=mvw%3A1%7Cmzb%3A1%7Cmzva%3A1%7Cpvrpr%3A0%7Cpvrll%3A1%7Cpvrts%3A0%7Cvrr%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/ondergrond/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=vezips%3A1%7Cmbgm%3A1%7Cmbs%3A1%7Cmbz%3A1%7Cmbr%3A1%7Cmbaig%3A1%7Cmbgwm%3A1%7Cexin%3A1%7Cmvlpgv%3A1%7Cmvlpga%3A1%7Cmvlpgt%3A1%7Cmvlpgs%3A1%7Cnap%3A1%7Cgbhv%3A1%7Cgbep%3A1%7Cgbgg%3A1%7Cgbgs%3A1%7Cgbos%3A1%7Cgboh%3A1%7Cgbwu%3A1%7Cgbkw%3A1%7Cgbvv%3A1%7Cexvg%3A1%7Cexgg%3A1%7Cexuo%3A1%7Cmvabl%3A1&${LEGEND}=true`,
  },
  {
    from: '/datablog/',
    to: 'https://amsterdam.github.io/datablog/',
  },
]

const articleUrls = CONTENT_REDIRECT_LINKS.ARTICLES.map(item => ({
  from: item.from,
  to: routing.articleDetail.path
    .replace(':slug', item.to.slug)
    .replace(':id', item.to.id[process.env.NODE_ENV]),
}))

const overviewPaths = [
  MAIN_PATHS.ARTICLES,
  MAIN_PATHS.PUBLICATIONS,
  MAIN_PATHS.SPECIALS,
  MAIN_PATHS.DATASETS,
]

const overviewUrls = overviewPaths.map(pathName => ({
  from: `/${pathName}/`,
  to: `/${pathName}/zoek/`,
}))

export const REDIRECTS = [...legacyRoutes, ...shortUrls, ...articleUrls, ...overviewUrls]

export default function resolveRedirects() {
  const currentPath = normalizePath(
    `${window.location.pathname}${window.location.search}${window.location.hash}`,
  )
  const matchingRedirect = REDIRECTS.find(({ from }) => normalizePath(from) === currentPath)

  if (!matchingRedirect) {
    return false
  }

  // Tries to prevent cancelling the network request to Matomo from the middleware, arbitrary number that allows Matomo some time to load
  window.setTimeout(() => window.location.replace(matchingRedirect.to), 600)

  return true
}

function normalizePath(path) {
  return path.endsWith('/') ? path.slice(0, -1) : path
}
<commit_msg>Fix themekaart redirects<commit_after>import PARAMETERS from '../store/parameters'
import { routing, MAIN_PATHS } from './routes'
import { CONTENT_REDIRECT_LINKS } from '../shared/config/config'

const { VIEW, VIEW_CENTER, LAYERS, LEGEND, ZOOM, EMBED } = PARAMETERS

// This are the known broken legacy links
const legacyRoutes = [
  // https://www.parool.nl/amsterdam/kaart-met-onontplofte-bommen-in-amsterdam-nu-openbaar~a4539314/
  {
    from:
      '/#?mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.telegraaf.nl/nieuws/1256075/ligt-er-een-bom-uit-woii-in-je-achtertuin-met-deze-kaart-kom-je-er-achter
  {
    from:
      '/#?mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=11&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3815892:4.8626601&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.amsterdamsdagblad.nl/gemeente/duizend-bommen-en-granaten-de-bommenkaart
  {
    from:
      '/#?mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/#?ate=T&lse=T&mpb=topografie&mpz=8&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3733262:4.8934106&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://intranet.alliander.com/blog/${VIEW}/5359847/kaart-met-onontplofte-bommen-in-amsterdam
  {
    from:
      '/#?mpb=topografie&mpz=14&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3889979:4.9094038&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  {
    from:
      '/?_sp=144b47f5-2817-4a1f-888c-d1d1b69c89cb.1510908859477#?ate=T&mpb=topografie&mpz=14&mpfs=T&mpo=exvg::T:exin::T:exuo::T&mpv=52.3889979:4.9094038&pgn=home',
    to: `${routing.data.path}?${VIEW}=kaart&${VIEW_CENTER}=52.3787158140549%2C4.893662070270319&${EMBED}=true&${LAYERS}=exvg%3A1%7Cexin%3A1%7Cexuo%3A1&${LEGEND}=false&${ZOOM}=8`,
  },
  // https://www.amsterdam.nl/ondernemen/biz/
  {
    from: '/#?mpb=topografie&mpz=9&mpfs=T&mpo=biz::T&mpv=52.3676245:4.8804992&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=biz%3A1&${LEGEND}=true&${ZOOM}=9`,
  },
  {
    from: '/#?ate=T&mpb=topografie&mpz=9&mpfs=T&mpo=biz::T&mpv=52.3676245:4.8804992&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart&${EMBED}=true&${LAYERS}=biz%3A1&${LEGEND}=true&${ZOOM}=9`,
  },
  // home map
  {
    from: '/#?mpb=topografie&mpz=11&mpfs=T&mpv=52.3731081:4.8932945&pgn=home&uvm=T',
    to: `${routing.data.path}?${VIEW}=kaart`,
  },
]
const shortUrls = [
  {
    from: '/themakaart/taxi/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=themtaxi-bgt%3A1%7Cthemtaxi-tar%3A1%7Cthemtaxi-pvrts%3A1%7Cthemtaxi-mzt%3A1%7Cthemtaxi-oovtig%3A1%7Cthemtaxi-vezips%3A1%7Cthemtaxi-slpnb%3A1%7Cthemtaxi-slpb%3A1%7Cthemtaxi-nlpnb%3A1%7Cthemtaxi-nlpb%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/veiligheid-en-overlast/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=veilov-oovoalg%3A1%7Cveilov-oovodlrs%3A1%7Cveilov-oovctg%3A1%7Cveilov-oovoalco%3A1%7Cveilov-oovorlv%3A1%7Cveilov-oovtig%3A1%7Cveilov-vwrk%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/logistiek/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=logistk-rtsvr%3A1%7Clogistk-pvrll%3A1%7Clogistk-mzb%3A1%7Clogistk-mvw%3A1%7Clogistk-mzva%3A1&${LEGEND}=true`,
  },
  {
    from: '/themakaart/ondergrond/',
    to: `${routing.data.path}?${VIEW}=kaart&${LAYERS}=vondrgd-aardgasbel%3A1%7Condrgd-aardgas1let%3A1%7Condrgd-aardgas100let%3A1%7Condrgd-aardgaspr106%3A1%7Condrgd-aardgas%3A1%7Condrgd-exuo%3A1%7Condrgd-exgg%3A1%7Condrgd-exvg%3A1%7Condrgd-gbhv%3A1%7Condrgd-gbep%3A1%7Condrgd-gbgg%3A1%7Condrgd-gbgs%3A1%7Condrgd-gbos%3A1%7Condrgd-gboh%3A1%7Condrgd-gbwu%3A1%7Condrgd-gbkw%3A1%7Condrgd-gbvv%3A1%7Condrgd-mvlpgst%3A1%7Condrgd-mvlpgs%3A1%7Condrgd-mvlpgtgrp%3A1%7Condrgd-mvlpgtris%3A1%7Condrgd-mvlpgt%3A1%7Condrgd-mvlpgvgeb%3A1%7Condrgd-mvlpgv106%3A1%7Condrgd-mvlpgv105%3A1%7Condrgd-mvlpgeb%3A1%7Condrgd-mvlpga%3A1%7Condrgd-exin%3A1%7Condrgd-mbgm%3A1%7Condrgd-mbaig%3A1%7Condrgd-mbgwm%3A1%7Condrgd-mbz%3A1%7Condrgd-mbs%3A1%7Condrgd-mbr%3A1%7Condrgd-vezips%3A1&${LEGEND}=true`,
  },
  {
    from: '/datablog/',
    to: 'https://amsterdam.github.io/datablog/',
  },
]

const articleUrls = CONTENT_REDIRECT_LINKS.ARTICLES.map(item => ({
  from: item.from,
  to: routing.articleDetail.path
    .replace(':slug', item.to.slug)
    .replace(':id', item.to.id[process.env.NODE_ENV]),
}))

const overviewPaths = [
  MAIN_PATHS.ARTICLES,
  MAIN_PATHS.PUBLICATIONS,
  MAIN_PATHS.SPECIALS,
  MAIN_PATHS.DATASETS,
]

const overviewUrls = overviewPaths.map(pathName => ({
  from: `/${pathName}/`,
  to: `/${pathName}/zoek/`,
}))

export const REDIRECTS = [...legacyRoutes, ...shortUrls, ...articleUrls, ...overviewUrls]

export default function resolveRedirects() {
  const currentPath = normalizePath(
    `${window.location.pathname}${window.location.search}${window.location.hash}`,
  )
  const matchingRedirect = REDIRECTS.find(({ from }) => normalizePath(from) === currentPath)

  if (!matchingRedirect) {
    return false
  }

  // Tries to prevent cancelling the network request to Matomo from the middleware, arbitrary number that allows Matomo some time to load
  window.setTimeout(() => window.location.replace(matchingRedirect.to), 600)

  return true
}

function normalizePath(path) {
  return path.endsWith('/') ? path.slice(0, -1) : path
}
<|endoftext|>


<commit_before>var $ = require('jquery');

module.exports = {
  tableRowItems: function (first, second, cls) {
    return $('
')
      .addClass(cls)
      .append($('
').append(first))
      .append($('
').append(second));
  },

  tableRow: function (description, data) {
    return this.tableRowItems(
      $('').text(description),
      $('<input readonly="readonly"/>').val(data));
  },

  textRow: function (description, data, cls) {
    return this.tableRowItems(
      $('').text(description),
      $('<textarea readonly="readonly" class="gethDeployText"/>').val(data),
      cls);
  },

  preRow: function (description, data) {
    return this.tableRowItems(
      $('').text(description),
      $('
').text(data)
    );
  },

  formatAssemblyText: function (asm, prefix, source) {
    var self = this;
    if (typeof asm === typeof '' || asm === null || asm === undefined) {
      return prefix + asm + '\n';
    }
    var text = prefix + '.code\n';
    $.each(asm['.code'], function (i, item) {
      var v = item.value === undefined ? '' : item.value;
      var src = '';
      if (item.begin !== undefined && item.end !== undefined) {
        src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g');
      }
      if (src.length > 30) {
        src = src.slice(0, 30) + '...';
      }
      if (item.name !== 'tag') {
        text += '  ';
      }
      text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n';
    });
    text += prefix + '.data\n';
    if (asm['.data']) {
      $.each(asm['.data'], function (i, item) {
        text += '  ' + prefix + '' + i + ':\n';
        text += self.formatAssemblyText(item, prefix + '    ', source);
      });
    }
    return text;
  },

  gethDeploy: function (contractName, jsonInterface, bytecode) {
    var code = '';
    var funABI = this.getConstructorInterface(JSON.parse(jsonInterface));

    funABI.inputs.forEach(function (inp) {
      code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n';
    });

    code += 'var ' + contractName + 'Contract = web3.eth.contract(' + jsonInterface.replace('\n', '') + ');' +
      '\nvar ' + contractName + ' = ' + contractName + 'Contract.new(';

    funABI.inputs.forEach(function (inp) {
      code += '\n   ' + inp.name + ',';
    });

    code += '\n   {' +
      '\n     from: web3.eth.accounts[0], ' +
      "\n     data: '" + bytecode + "', " +
      '\n     gas: 4700000' +
      '\n   }, function (e, contract){' +
      '\n    console.log(e, contract);' +
      "\n    if (typeof contract.address !== 'undefined') {" +
      "\n         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" +
      '\n    }' +
      '\n })';

    return code;
  },

  getConstructorInterface: function (abi) {
    var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] };
    for (var i = 0; i < abi.length; i++) {
      if (abi[i].type === 'constructor') {
        funABI.inputs = abi[i].inputs || [];
        break;
      }
    }
    return funABI;
  },

  formatGasEstimates: function (data) {
    // FIXME: the whole gasEstimates object should be nil instead
    if (data.creation === undefined && data.external === undefined && data.internal === undefined) {
      return;
    }
    var gasToText = function (g) { return g === null ? 'unknown' : g; };
    var text = '';
    var fun;
    if ('creation' in data) {
      text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n';
    }

    if ('external' in data) {
      text += 'External:\n';
      for (fun in data.external) {
        text += '  ' + fun + ': ' + gasToText(data.external[fun]) + '\n';
      }
    }

    if ('internal' in data) {
      text += 'Internal:\n';
      for (fun in data.internal) {
        text += '  ' + fun + ': ' + gasToText(data.internal[fun]) + '\n';
      }
    }
    return text;
  },

  detailsOpen: {},
  getDetails: function (contract, source, contractName) {
    var button = $('<button>Toggle Details</button>');
    var details = $('
')
      .append(this.tableRow('Solidity Interface', contract.solidity_interface));

    if (contract.opcodes !== '') {
      details.append(this.tableRow('Opcodes', contract.opcodes));
    }

    var funHashes = '';
    for (var fun in contract.functionHashes) {
      funHashes += contract.functionHashes[fun] + ' ' + fun + '\n';
    }
    details.append(this.preRow('Functions', funHashes));

    var gasEstimates = this.formatGasEstimates(contract.gasEstimates);
    if (gasEstimates) {
      details.append(this.preRow('Gas Estimates', gasEstimates));
    }

    if (contract.runtimeBytecode && contract.runtimeBytecode.length > 0) {
      details.append(this.tableRow('Runtime Bytecode', contract.runtimeBytecode));
    }

    if (contract.assembly !== null) {
      details.append(this.preRow('Assembly', this.formatAssemblyText(contract.assembly, '', source)));
    }

    var self = this;
    button.click(function () { self.detailsOpen[contractName] = !self.detailsOpen[contractName]; details.toggle(); });
    if (this.detailsOpen[contractName]) {
      details.show();
    }
    return $('
').append(button).append(details);
  }
};
<commit_msg>Place the opcodes table after the runtime bytecode<commit_after>var $ = require('jquery');

module.exports = {
  tableRowItems: function (first, second, cls) {
    return $('
')
      .addClass(cls)
      .append($('
').append(first))
      .append($('
').append(second));
  },

  tableRow: function (description, data) {
    return this.tableRowItems(
      $('').text(description),
      $('<input readonly="readonly"/>').val(data));
  },

  textRow: function (description, data, cls) {
    return this.tableRowItems(
      $('').text(description),
      $('<textarea readonly="readonly" class="gethDeployText"/>').val(data),
      cls);
  },

  preRow: function (description, data) {
    return this.tableRowItems(
      $('').text(description),
      $('
').text(data)
    );
  },

  formatAssemblyText: function (asm, prefix, source) {
    var self = this;
    if (typeof asm === typeof '' || asm === null || asm === undefined) {
      return prefix + asm + '\n';
    }
    var text = prefix + '.code\n';
    $.each(asm['.code'], function (i, item) {
      var v = item.value === undefined ? '' : item.value;
      var src = '';
      if (item.begin !== undefined && item.end !== undefined) {
        src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g');
      }
      if (src.length > 30) {
        src = src.slice(0, 30) + '...';
      }
      if (item.name !== 'tag') {
        text += '  ';
      }
      text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n';
    });
    text += prefix + '.data\n';
    if (asm['.data']) {
      $.each(asm['.data'], function (i, item) {
        text += '  ' + prefix + '' + i + ':\n';
        text += self.formatAssemblyText(item, prefix + '    ', source);
      });
    }
    return text;
  },

  gethDeploy: function (contractName, jsonInterface, bytecode) {
    var code = '';
    var funABI = this.getConstructorInterface(JSON.parse(jsonInterface));

    funABI.inputs.forEach(function (inp) {
      code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n';
    });

    code += 'var ' + contractName + 'Contract = web3.eth.contract(' + jsonInterface.replace('\n', '') + ');' +
      '\nvar ' + contractName + ' = ' + contractName + 'Contract.new(';

    funABI.inputs.forEach(function (inp) {
      code += '\n   ' + inp.name + ',';
    });

    code += '\n   {' +
      '\n     from: web3.eth.accounts[0], ' +
      "\n     data: '" + bytecode + "', " +
      '\n     gas: 4700000' +
      '\n   }, function (e, contract){' +
      '\n    console.log(e, contract);' +
      "\n    if (typeof contract.address !== 'undefined') {" +
      "\n         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" +
      '\n    }' +
      '\n })';

    return code;
  },

  getConstructorInterface: function (abi) {
    var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] };
    for (var i = 0; i < abi.length; i++) {
      if (abi[i].type === 'constructor') {
        funABI.inputs = abi[i].inputs || [];
        break;
      }
    }
    return funABI;
  },

  formatGasEstimates: function (data) {
    // FIXME: the whole gasEstimates object should be nil instead
    if (data.creation === undefined && data.external === undefined && data.internal === undefined) {
      return;
    }
    var gasToText = function (g) { return g === null ? 'unknown' : g; };
    var text = '';
    var fun;
    if ('creation' in data) {
      text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n';
    }

    if ('external' in data) {
      text += 'External:\n';
      for (fun in data.external) {
        text += '  ' + fun + ': ' + gasToText(data.external[fun]) + '\n';
      }
    }

    if ('internal' in data) {
      text += 'Internal:\n';
      for (fun in data.internal) {
        text += '  ' + fun + ': ' + gasToText(data.internal[fun]) + '\n';
      }
    }
    return text;
  },

  detailsOpen: {},
  getDetails: function (contract, source, contractName) {
    var button = $('<button>Toggle Details</button>');
    var details = $('
')
      .append(this.tableRow('Solidity Interface', contract.solidity_interface));

    var funHashes = '';
    for (var fun in contract.functionHashes) {
      funHashes += contract.functionHashes[fun] + ' ' + fun + '\n';
    }
    details.append(this.preRow('Functions', funHashes));

    var gasEstimates = this.formatGasEstimates(contract.gasEstimates);
    if (gasEstimates) {
      details.append(this.preRow('Gas Estimates', gasEstimates));
    }

    if (contract.runtimeBytecode && contract.runtimeBytecode.length > 0) {
      details.append(this.tableRow('Runtime Bytecode', contract.runtimeBytecode));
    }

    if (contract.opcodes !== '') {
      details.append(this.tableRow('Opcodes', contract.opcodes));
    }

    if (contract.assembly !== null) {
      details.append(this.preRow('Assembly', this.formatAssemblyText(contract.assembly, '', source)));
    }

    var self = this;
    button.click(function () { self.detailsOpen[contractName] = !self.detailsOpen[contractName]; details.toggle(); });
    if (this.detailsOpen[contractName]) {
      details.show();
    }
    return $('
').append(button).append(details);
  }
};
<|endoftext|>


<commit_before>$(document).foundation();

var _gaq = _gaq || [];
_gaq.push(
  ['_setAccount', 'UA-2195009-2'],
  ['_trackPageview'],
  ['b._setAccount', 'UA-2195009-27'],
  ['b._trackPageview']
);

(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

!function() {

var _kmq = _kmq || [];
var _kmk = _kmk || "d945f04ff5e68057c85f5323b46f185efb3826b3";
function _kms(u){
  setTimeout(function(){
    var d = document, f = d.getElementsByTagName('script')[0],
    s = d.createElement('script');
    s.type = 'text/javascript'; s.async = true; s.src = u;
    f.parentNode.insertBefore(s, f);
  }, 1);
}
_kms('//i.kissmetrics.com/i.js');
_kms('//doug1izaerwt3.cloudfront.net/' + _kmk + '.1.js');

if($('#yeti-callout-card').is('*')) {

  _kmq.push(function() {
    var type = KM.ab("BB Ad Unit", ["yeti-callout-card", "yeti-callout-alert"]);
    var type = 'yeti-callout-card';
    if(type === 'yeti-callout-card') {
      $('#yeti-callout-card').removeClass('is-hidden');
    } else {
      $('#yeti-callout-alert').removeClass('is-hidden');
    }
  });

}

}();

var mySVGsToInject = document.querySelectorAll('img.inject-me');

var likes = new window.Likes();
likes.populateLikesInPage();
likes.setupLike();

SVGInjector(mySVGsToInject);
var $searchInput = $('input[type="search"]')
var setupFilterable = function($current, $links, updateMethod) {
  $links.on('click', function(e) {
    e.preventDefault();
    var $el = $(e.currentTarget);
    var type = $el.data().type;
    $current.text($el.text());
    updateMethod(type);
    $links.each(function() {
      var $link = $(this);
      if (typeof($link.data().hideActive) === 'undefined') {
        if ($link.data().type === type) {
          $link.addClass('is-active');
        } else {
          $link.removeClass('is-active');
        }
      } else {
        if ($link.data().type === type) {
          $link.addClass('hide');
        } else {
          $link.removeClass('hide');
        }
      }
    });
  });
}
var params = getParams();
if($searchInput.is('*')) {
  if(params.q) {
    $('#bb-search-bar').removeClass('is-hidden').show();
    $searchInput.focus();
  }
  window.search = new Search({
    input: $('input[type="search"]'),
    searchContainer: $('#search-results-container .card-container'),
    kitContainer: $('#search-results-container .kit-container'),
    initialQuery: params.q,
    onSearch: function(term, filter, sort, results, kitResults) {
      if(term.length > 0 || filter !== 'all' || sort !== 'newest') {
        $('#main-results-container').hide();
        $('#search-results-container').show();
        $('#search-results-container').foundation();
        $('#result-count').text(results.length);
      } else {
        $('#main-results-container').show();
        $('#search-results-container').hide();
        $('#result-count').text(results.length);
      }
      likes.populateLikesInPage();
    }
  });
  var $currentSort = $('[data-sort-current]');
  var $sortLinks = $('[data-sort]');
  setupFilterable($currentSort, $sortLinks, window.search.setSort.bind(window.search));

  var $currentFilter = $('[data-filter-current]');
  var $filterLinks = $('[data-filter]');
  setupFilterable($currentFilter, $filterLinks, window.search.setFilter.bind(window.search));
  $('#bb-search-bar').on('close.zf.trigger', function() {
    $searchInput.val('');
    window.search.updateSearch();
  }).on('toggle.zf.trigger', function() {
    setTimeout( () => { $searchInput.focus();window.search.updateSearch();}, 1)
  });
}

function getParams() {
  var search = location.search.substring(1);
  return search?JSON.parse('{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}',
                   function(key, value) { return key===""?value:decodeURIComponent(value) }):{}
}

function toggleCode() {
  $('#codeBoxSCSS').toggleClass('is-active');
  $('#scssToggle').toggleClass('is-active');
  $('#codeBoxCSS').toggleClass('is-active');
  $('#cssToggle').toggleClass('is-active');
}

$('#scssToggle').click(function(){
  if ($('#cssToggle').hasClass('is-active')) {
    toggleCode();
  }
});

$('#cssToggle').click(function(){
  if ($('#scssToggle').hasClass('is-active')) {
    toggleCode();
  }
});

var toggleHTML = $('[data-toggle-HTML]');
var toggleSCSS = $('[data-toggle-SCSS]');
var toggleJS   = $('[data-toggle-JS]');

// toggles trigger for the code boxes
toggleHTML.click(function(e) {
  if( toggleSCSS.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxHTML').toggleClass('is-active');
  }
  e.preventDefault();
});

toggleSCSS.click(function(e) {
  if( toggleHTML.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxSCSS').toggleClass('is-active');
  }
  e.preventDefault();
});

toggleSCSS.click(function(e) {
  if( toggleSCSS.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxJS').toggleClass('is-active');
  }
  e.preventDefault();
});

var socialName = $('meta[name="og:title"]').prop('content');
var socialImage = $('meta[name="og:image"]').prop('content');
$('#bb-social').jsSocials({
  showLabel: false,
  showCount: false,
  text: "Download this " + socialName + " from Foundation Building Blocks",
  shares: [ { share: "twitter", via: "ZURBFoundation" }, "facebook", {share: "pinterest", media: socialImage, text: socialName + " from Foundation Building Blocks"}]
});

$('[data-toggle-callout]').click(function() {
  $('.course-callout-alert').toggleClass('is-moved-over');
});

var $footer = $('#footer');
var $window = $(window);
var $callout = $('.course-callout-alert');

$(window).on("load scroll", function() {
    var footerOffset = $footer.offset().top;
    var myScrollPosition = $(this).scrollTop();
    var windowHeight = $window.height();
    var footerHeight = $footer.outerHeight();

    if ((myScrollPosition + windowHeight - footerHeight) > footerOffset) {
      $callout.addClass('absolute');
    } else {
      $callout.removeClass('absolute');
    }
});

<commit_msg>Move KM AB code outside of scope to get it to actually run<commit_after>$(document).foundation();

var _gaq = _gaq || [];
_gaq.push(
  ['_setAccount', 'UA-2195009-2'],
  ['_trackPageview'],
  ['b._setAccount', 'UA-2195009-27'],
  ['b._trackPageview']
);

(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
var _kmq = _kmq || [];
!function() {

var _kmq = _kmq || [];
var _kmk = _kmk || "d945f04ff5e68057c85f5323b46f185efb3826b3";
function _kms(u){
  setTimeout(function(){
    var d = document, f = d.getElementsByTagName('script')[0],
    s = d.createElement('script');
    s.type = 'text/javascript'; s.async = true; s.src = u;
    f.parentNode.insertBefore(s, f);
  }, 1);
}
_kms('//i.kissmetrics.com/i.js');
_kms('//doug1izaerwt3.cloudfront.net/' + _kmk + '.1.js');

}();

if($('#yeti-callout-card').is('*')) {

  _kmq.push(function() {
    var type = KM.ab("BB Ad Unit", ["yeti-callout-card", "yeti-callout-alert"]);
    var type = 'yeti-callout-card';
    if(type === 'yeti-callout-card') {
      $('#yeti-callout-card').removeClass('is-hidden');
    } else {
      $('#yeti-callout-alert').removeClass('is-hidden');
    }
  });

}

var mySVGsToInject = document.querySelectorAll('img.inject-me');

var likes = new window.Likes();
likes.populateLikesInPage();
likes.setupLike();

SVGInjector(mySVGsToInject);
var $searchInput = $('input[type="search"]')
var setupFilterable = function($current, $links, updateMethod) {
  $links.on('click', function(e) {
    e.preventDefault();
    var $el = $(e.currentTarget);
    var type = $el.data().type;
    $current.text($el.text());
    updateMethod(type);
    $links.each(function() {
      var $link = $(this);
      if (typeof($link.data().hideActive) === 'undefined') {
        if ($link.data().type === type) {
          $link.addClass('is-active');
        } else {
          $link.removeClass('is-active');
        }
      } else {
        if ($link.data().type === type) {
          $link.addClass('hide');
        } else {
          $link.removeClass('hide');
        }
      }
    });
  });
}
var params = getParams();
if($searchInput.is('*')) {
  if(params.q) {
    $('#bb-search-bar').removeClass('is-hidden').show();
    $searchInput.focus();
  }
  window.search = new Search({
    input: $('input[type="search"]'),
    searchContainer: $('#search-results-container .card-container'),
    kitContainer: $('#search-results-container .kit-container'),
    initialQuery: params.q,
    onSearch: function(term, filter, sort, results, kitResults) {
      if(term.length > 0 || filter !== 'all' || sort !== 'newest') {
        $('#main-results-container').hide();
        $('#search-results-container').show();
        $('#search-results-container').foundation();
        $('#result-count').text(results.length);
      } else {
        $('#main-results-container').show();
        $('#search-results-container').hide();
        $('#result-count').text(results.length);
      }
      likes.populateLikesInPage();
    }
  });
  var $currentSort = $('[data-sort-current]');
  var $sortLinks = $('[data-sort]');
  setupFilterable($currentSort, $sortLinks, window.search.setSort.bind(window.search));

  var $currentFilter = $('[data-filter-current]');
  var $filterLinks = $('[data-filter]');
  setupFilterable($currentFilter, $filterLinks, window.search.setFilter.bind(window.search));
  $('#bb-search-bar').on('close.zf.trigger', function() {
    $searchInput.val('');
    window.search.updateSearch();
  }).on('toggle.zf.trigger', function() {
    setTimeout( () => { $searchInput.focus();window.search.updateSearch();}, 1)
  });
}

function getParams() {
  var search = location.search.substring(1);
  return search?JSON.parse('{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}',
                   function(key, value) { return key===""?value:decodeURIComponent(value) }):{}
}

function toggleCode() {
  $('#codeBoxSCSS').toggleClass('is-active');
  $('#scssToggle').toggleClass('is-active');
  $('#codeBoxCSS').toggleClass('is-active');
  $('#cssToggle').toggleClass('is-active');
}

$('#scssToggle').click(function(){
  if ($('#cssToggle').hasClass('is-active')) {
    toggleCode();
  }
});

$('#cssToggle').click(function(){
  if ($('#scssToggle').hasClass('is-active')) {
    toggleCode();
  }
});

var toggleHTML = $('[data-toggle-HTML]');
var toggleSCSS = $('[data-toggle-SCSS]');
var toggleJS   = $('[data-toggle-JS]');

// toggles trigger for the code boxes
toggleHTML.click(function(e) {
  if( toggleSCSS.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxHTML').toggleClass('is-active');
  }
  e.preventDefault();
});

toggleSCSS.click(function(e) {
  if( toggleHTML.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxSCSS').toggleClass('is-active');
  }
  e.preventDefault();
});

toggleSCSS.click(function(e) {
  if( toggleSCSS.hasClass('is-active') || toggleJS.hasClass('.is-active') ) {
    $(this).toggleClass('is-active');
    $('#codeBoxJS').toggleClass('is-active');
  }
  e.preventDefault();
});

var socialName = $('meta[name="og:title"]').prop('content');
var socialImage = $('meta[name="og:image"]').prop('content');
$('#bb-social').jsSocials({
  showLabel: false,
  showCount: false,
  text: "Download this " + socialName + " from Foundation Building Blocks",
  shares: [ { share: "twitter", via: "ZURBFoundation" }, "facebook", {share: "pinterest", media: socialImage, text: socialName + " from Foundation Building Blocks"}]
});

$('[data-toggle-callout]').click(function() {
  $('.course-callout-alert').toggleClass('is-moved-over');
});

var $footer = $('#footer');
var $window = $(window);
var $callout = $('.course-callout-alert');

$(window).on("load scroll", function() {
    var footerOffset = $footer.offset().top;
    var myScrollPosition = $(this).scrollTop();
    var windowHeight = $window.height();
    var footerHeight = $footer.outerHeight();

    if ((myScrollPosition + windowHeight - footerHeight) > footerOffset) {
      $callout.addClass('absolute');
    } else {
      $callout.removeClass('absolute');
    }
});

<|endoftext|>


<commit_before>/* CONSTANTS */
const bMin = document.querySelector('.b--min');
const sMin = document.querySelector('.s--min');
const bPlus = document.querySelector('.b--plus');
const sPlus = document.querySelector('.s--plus');
const sSes = document.querySelector('.span--session');
const sBreak = document.querySelector('.span--break');
const h2Type = document.querySelector('.h2--type');
const bReset = document.querySelector('.b--reset');
const pTimer = document.querySelector('.p--timer');
const bTimer = document.querySelector('.b--timer');
const beep = new Audio('assets/beep.mp3');

/* Allow Notification */
if(Notification.permission !== 'granted') {
  Notification.requestPermission().then(perm => {
    if(perm === 'granted')
      console.log('Notifications will show');
  });
}

/* FUNCTION FOR SETTINGS */
const minOrPlus = (op, n)=>{
  if(op === 'min' && n.innerHTML > 0){
    if(n === sSes)
      n.innerHTML -= 5;
    else
      n.innerHTML -= 1;
  }
  else if(op == 'plus' && n.innerHTML < 60){
    if(n === sSes)
      n.innerHTML = +n.innerHTML + 5;
    else
      n.innerHTML = +n.innerHTML + 1;
  }

  if(n === sSes && h2Type.innerHTML === 'Session')
    pTimer.innerHTML = sSes.innerHTML + ':00';
  else if(n === sBreak && h2Type.innerHTML === 'Break')
    pTimer.innerHTML = sBreak.innerHTML + ':00';
};

/* FUNCTIONS FOR COUNTING */
const setSecs = (mins, secs)=>{
  if(secs > 10)
    return mins + ':' + (secs-1);
  else if(secs > 0)
    return mins + ':0' + (secs-1);
  else
    return setMins(mins);
};

const setMins = (mins)=>{
  if(mins > 10)
    return (mins-1) + ':59';
  else if(mins > 0)
    return (mins-1) + ':59';
  else
    return '0:00';
};

/* FUNCTIONS FOR TIMER */
const stop = (intervalID) => {
  clearInterval(intervalID);

  bMin.disabled = sMin.disabled = bPlus.disabled = sPlus.disabled = false;
  bTimer.style.background = 'none';

  bTimer.onclick = () => {run();};
};

const change = () => {
  beep.play();

  //add notification
  if(!window.myNoti)
    window.myNoti= new Notification('Timer Ended');

  bTimer.onclick = () => {
    //remove notification
    if(myNoti) {
      setTimeout(myNoti.close.bind(myNoti), 500);
      window.myNoti = undefined;
    }

    if(h2Type.innerHTML === 'Session') {
      h2Type.innerHTML = 'Break';
      pTimer.innerHTML = sBreak.innerHTML + ':00';
    }
    else {
      h2Type.innerHTML = 'Session';
      pTimer.innerHTML = sSes.innerHTML + ':00';
    }
  };
};

const run = () => {
  //Stop from clicking too fast
  if(bTimer.style.background === 'yellow')
    return;

  bMin.disabled = sMin.disabled = bPlus.disabled = sPlus.disabled = true;
  bTimer.style.background = 'yellow';

  const intervalID = setInterval(() => {
    //Running and Stopping
    if(pTimer.innerHTML !== '0:00'){
      pTimer.innerHTML =
        setSecs(pTimer.innerHTML.split(':')[0],
                pTimer.innerHTML.split(':')[1]);

      bTimer.onclick = () => { stop(intervalID); };
    }

    //Changing between Session and Break
    else change();
  }, 1000);

  //Reset button
  bReset.onclick = () => {
    stop(intervalID);
    pTimer.innerHTML = sSes.innerHTML + ':00';
    h2Type.innerHTML = 'Session';

    //remove notification
    if(myNoti) {
      setTimeout(myNoti.close.bind(myNoti), 500);
      window.myNoti = undefined;
    }
  };
};

/* VOLUME */
beep.volume = 1;

/* SETTINGS */
bMin.onclick = () => { minOrPlus('min', sBreak); };
sMin.onclick = () => { minOrPlus('min', sSes); };
bPlus.onclick = () => { minOrPlus('plus', sBreak); };
sPlus.onclick = () => { minOrPlus('plus', sSes); };

/* TIMER */
bTimer.onclick = () => { run(); };
<commit_msg>remove automatic closing of noti<commit_after>/* CONSTANTS */
const bMin = document.querySelector('.b--min');
const sMin = document.querySelector('.s--min');
const bPlus = document.querySelector('.b--plus');
const sPlus = document.querySelector('.s--plus');
const sSes = document.querySelector('.span--session');
const sBreak = document.querySelector('.span--break');
const h2Type = document.querySelector('.h2--type');
const bReset = document.querySelector('.b--reset');
const pTimer = document.querySelector('.p--timer');
const bTimer = document.querySelector('.b--timer');
const beep = new Audio('assets/beep.mp3');

/* Allow Notification */
if(Notification.permission !== 'granted') {
  Notification.requestPermission().then(perm => {
    if(perm === 'granted')
      console.log('Notifications will show');
  });
}

/* FUNCTION FOR SETTINGS */
const minOrPlus = (op, n)=>{
  if(op === 'min' && n.innerHTML > 0){
    if(n === sSes)
      n.innerHTML -= 5;
    else
      n.innerHTML -= 1;
  }
  else if(op == 'plus' && n.innerHTML < 60){
    if(n === sSes)
      n.innerHTML = +n.innerHTML + 5;
    else
      n.innerHTML = +n.innerHTML + 1;
  }

  if(n === sSes && h2Type.innerHTML === 'Session')
    pTimer.innerHTML = sSes.innerHTML + ':00';
  else if(n === sBreak && h2Type.innerHTML === 'Break')
    pTimer.innerHTML = sBreak.innerHTML + ':00';
};

/* FUNCTIONS FOR COUNTING */
const setSecs = (mins, secs)=>{
  if(secs > 10)
    return mins + ':' + (secs-1);
  else if(secs > 0)
    return mins + ':0' + (secs-1);
  else
    return setMins(mins);
};

const setMins = (mins)=>{
  if(mins > 10)
    return (mins-1) + ':59';
  else if(mins > 0)
    return (mins-1) + ':59';
  else
    return '0:00';
};

/* FUNCTIONS FOR TIMER */
const stop = (intervalID) => {
  clearInterval(intervalID);

  bMin.disabled = sMin.disabled = bPlus.disabled = sPlus.disabled = false;
  bTimer.style.background = 'none';

  bTimer.onclick = () => {run();};
};

const change = () => {
  beep.play();

  //add notification
  if(!window.myNoti)
    window.myNoti= new Notification('Timer Ended', { requireInteraction: true });

  bTimer.onclick = () => {
    //remove notification
    if(myNoti) {
      setTimeout(myNoti.close.bind(myNoti), 500);
      window.myNoti = undefined;
    }

    if(h2Type.innerHTML === 'Session') {
      h2Type.innerHTML = 'Break';
      pTimer.innerHTML = sBreak.innerHTML + ':00';
    }
    else {
      h2Type.innerHTML = 'Session';
      pTimer.innerHTML = sSes.innerHTML + ':00';
    }
  };
};

const run = () => {
  //Stop from clicking too fast
  if(bTimer.style.background === 'yellow')
    return;

  bMin.disabled = sMin.disabled = bPlus.disabled = sPlus.disabled = true;
  bTimer.style.background = 'yellow';

  const intervalID = setInterval(() => {
    //Running and Stopping
    if(pTimer.innerHTML !== '0:00'){
      pTimer.innerHTML =
        setSecs(pTimer.innerHTML.split(':')[0],
                pTimer.innerHTML.split(':')[1]);

      bTimer.onclick = () => { stop(intervalID); };
    }

    //Changing between Session and Break
    else change();
  }, 1000);

  //Reset button
  bReset.onclick = () => {
    stop(intervalID);
    pTimer.innerHTML = sSes.innerHTML + ':00';
    h2Type.innerHTML = 'Session';

    //remove notification
    if(myNoti) {
      setTimeout(myNoti.close.bind(myNoti), 500);
      window.myNoti = undefined;
    }
  };
};

/* VOLUME */
beep.volume = 1;

/* SETTINGS */
bMin.onclick = () => { minOrPlus('min', sBreak); };
sMin.onclick = () => { minOrPlus('min', sSes); };
bPlus.onclick = () => { minOrPlus('plus', sBreak); };
sPlus.onclick = () => { minOrPlus('plus', sSes); };

/* TIMER */
bTimer.onclick = () => { run(); };
<|endoftext|>


<commit_before>import isPlainObject from 'lodash.isplainobject'
import bufferActions from './bufferActions'
import { REHYDRATE } from './constants'

module.exports = function autoRehydrate (config = {}) {
  return (next) => (reducer, initialState) => {
    const rehydrationReducer = createRehydrationReducer(reducer)

    // buffer actions
    const store = next(rehydrationReducer, initialState)
    const dispatch = bufferActions(onBufferEnd)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }

  function onBufferEnd (err, queue) {
    if (err) console.error(err)
    if (config.log) console.log('redux-persist/autoRehydrate action buffer released', queue)
  }

  function createRehydrationReducer (reducer) {
    return (state, action) => {
      if (action.type === REHYDRATE) {
        let key = action.key
        let data = action.payload
        let reducedState = reducer(state, action)

        // if reducer modifies substate, skip auto rehydration
        if (state[key] !== reducedState[key]) {
          if (config.log) console.log('redux-persist/autoRehydrate sub state for key "%s" modified, skipping autoRehydrate', key)
          return reducedState
        }

        let autoReducedState = {...reducedState}
        if (!isPlainObject(data) || !isPlainObject(reducedState[key])) {
          // assign value
          autoReducedState[key] = data
        } else {
          // shallow merge
          var subState = {}
          for (var subkey in reducedState[key]) { subState[subkey] = reducedState[key][subkey] }
          for (var datakey in data) { subState[datakey] = data[datakey] }
          autoReducedState[key] = subState
        }

        if (config.log) console.log('redux-persist/autoRehydrate key: %s, rehydrated to:', key, autoReducedState[key])
        return autoReducedState
      } else {
        return reducer(state, action)
      }
    }
  }
}
<commit_msg>updated createRehydrationReducer with new method to check if state is an object (doesn't create warnings with immutable objects)<commit_after>import isPlainObject from 'lodash.isplainobject'
import bufferActions from './bufferActions'
import { REHYDRATE } from './constants'

module.exports = function autoRehydrate (config = {}) {
  return (next) => (reducer, initialState) => {
    const rehydrationReducer = createRehydrationReducer(reducer)

    // buffer actions
    const store = next(rehydrationReducer, initialState)
    const dispatch = bufferActions(onBufferEnd)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }

  function onBufferEnd (err, queue) {
    if (err) console.error(err)
    if (config.log) console.log('redux-persist/autoRehydrate action buffer released', queue)
  }

  function checkIsObject (data, reducedState, key) {
    if ((data.size || data.hasOwnProperty('size')) || (reducedState[key].size || reducedState[key].hasOwnProperty('size'))) {
      return true
    } else if (isPlainObject(data) || isPlainObject(reducedState[key])) {
      return true
    }
    return false
  }

  function createRehydrationReducer (reducer) {
    return (state, action) => {
      if (action.type === REHYDRATE) {
        let key = action.key
        let data = action.payload
        let reducedState = reducer(state, action)

        // if reducer modifies substate, skip auto rehydration
        if (state[key] !== reducedState[key]) {
          if (config.log) console.log('redux-persist/autoRehydrate sub state for key "%s" modified, skipping autoRehydrate', key)
          return reducedState
        }

        let autoReducedState = {...reducedState}
        let isObject = checkIsObject(data, reducedState, key)
        if (!isObject) {
          // assign value
          autoReducedState[key] = data
        } else {
          // shallow merge
          var subState = {}
          for (var subkey in reducedState[key]) { subState[subkey] = reducedState[key][subkey] }
          for (var datakey in data) { subState[datakey] = data[datakey] }
          autoReducedState[key] = subState
        }

        if (config.log) console.log('redux-persist/autoRehydrate key: %s, rehydrated to:', key, autoReducedState[key])
        return autoReducedState
      } else {
        return reducer(state, action)
      }
    }
  }
}
<|endoftext|>


<commit_before>// This is the backend that is injected into the page that a Vue app lives in
// when the Vue Devtools panel is activated.

import { highlight, unHighlight, getInstanceRect } from './highlighter'
import { initVuexBackend } from './vuex'
import { initEventsBackend } from './events'
import { stringify, classify, camelize } from '../util'
import path from 'path'

// Use a custom basename functions instead of the shimed version
// because it doesn't work on Windows
function basename (filename, ext) {
  return path.basename(
    filename.replace(/^[a-zA-Z]:/, '').replace(/\\/g, '/'),
    ext
  )
}

// hook should have been injected before this executes.
const hook = window.__VUE_DEVTOOLS_GLOBAL_HOOK__
const rootInstances = []
const propModes = ['default', 'sync', 'once']

const instanceMap = window.__VUE_DEVTOOLS_INSTANCE_MAP__ = new Map()
const consoleBoundInstances = Array(5)
let currentInspectedId
let bridge
let filter = ''
let captureCount = 0
let isLegacy = false

export function initBackend (_bridge) {
  bridge = _bridge
  if (hook.Vue) {
    isLegacy = hook.Vue.version && hook.Vue.version.split('.')[0] === '1'
    connect()
  } else {
    hook.once('init', connect)
  }
}

function connect () {
  hook.currentTab = 'components'
  bridge.on('switch-tab', tab => {
    hook.currentTab = tab
    if (tab === 'components') {
      flush()
    }
  })

  // the backend may get injected to the same page multiple times
  // if the user closes and reopens the devtools.
  // make sure there's only one flush listener.
  hook.off('flush')
  hook.on('flush', () => {
    if (hook.currentTab === 'components') {
      flush()
    }
  })

  bridge.on('select-instance', id => {
    currentInspectedId = id
    const instance = instanceMap.get(id)
    if (instance) {
      scrollIntoView(instance)
      highlight(instance)
    }
    bindToConsole(instance)
    flush()
    bridge.send('instance-details', stringify(getInstanceDetails(id)))
  })

  bridge.on('filter-instances', _filter => {
    filter = _filter.toLowerCase()
    flush()
  })

  bridge.on('refresh', scan)
  bridge.on('enter-instance', id => highlight(instanceMap.get(id)))
  bridge.on('leave-instance', unHighlight)

  // vuex
  if (hook.store) {
    initVuexBackend(hook, bridge)
  } else {
    hook.once('vuex:init', store => {
      initVuexBackend(hook, bridge)
    })
  }

  // events
  initEventsBackend(hook.Vue, bridge)

  bridge.log('backend ready.')
  bridge.send('ready', hook.Vue.version)
  console.log('[vue-devtools] Ready. Detected Vue v' + hook.Vue.version)
  scan()
}

/**
 * Scan the page for root level Vue instances.
 */

function scan () {
  rootInstances.length = 0
  let inFragment = false
  let currentFragment = null
  walk(document, function (node) {
    if (inFragment) {
      if (node === currentFragment._fragmentEnd) {
        inFragment = false
        currentFragment = null
      }
      return true
    }
    const instance = node.__vue__
    if (instance) {
      if (instance._isFragment) {
        inFragment = true
        currentFragment = instance
      }

      // respect Vue.config.devtools option
      let baseVue = instance.constructor
      while (baseVue.super) {
        baseVue = baseVue.super
      }
      if (baseVue.config && baseVue.config.devtools) {
        rootInstances.push(instance)
      }

      return true
    }
  })
  flush()
}

/**
 * DOM walk helper
 *
 * @param {NodeList} nodes
 * @param {Function} fn
 */

function walk (node, fn) {
  if (node.childNodes) {
    for (let i = 0, l = node.childNodes.length; i < l; i++) {
      const child = node.childNodes[i]
      const stop = fn(child)
      if (!stop) {
        walk(child, fn)
      }
    }
  }

  // also walk shadow DOM
  if (node.shadowRoot) {
    walk(node.shadowRoot, fn)
  }
}

/**
 * Called on every Vue.js batcher flush cycle.
 * Capture current component tree structure and the state
 * of the current inspected instance (if present) and
 * send it to the devtools.
 */

function flush () {
  let start
  if (process.env.NODE_ENV !== 'production') {
    captureCount = 0
    start = window.performance.now()
  }
  const payload = stringify({
    inspectedInstance: getInstanceDetails(currentInspectedId),
    instances: findQualifiedChildrenFromList(rootInstances)
  })
  if (process.env.NODE_ENV !== 'production') {
    console.log(`[flush] serialized ${captureCount} instances, took ${window.performance.now() - start}ms.`)
  }
  bridge.send('flush', payload)
}

/**
 * Iterate through an array of instances and flatten it into
 * an array of qualified instances. This is a depth-first
 * traversal - e.g. if an instance is not matched, we will
 * recursively go deeper until a qualified child is found.
 *
 * @param {Array} instances
 * @return {Array}
 */

function findQualifiedChildrenFromList (instances) {
  instances = instances
    .filter(child => !child._isBeingDestroyed)
  return !filter
    ? instances.map(capture)
    : Array.prototype.concat.apply([], instances.map(findQualifiedChildren))
}

/**
 * Find qualified children from a single instance.
 * If the instance itself is qualified, just return itself.
 * This is ok because [].concat works in both cases.
 *
 * @param {Vue} instance
 * @return {Vue|Array}
 */

function findQualifiedChildren (instance) {
  return isQualified(instance)
    ? capture(instance)
    : findQualifiedChildrenFromList(instance.$children)
}

/**
 * Check if an instance is qualified.
 *
 * @param {Vue} instance
 * @return {Boolean}
 */

function isQualified (instance) {
  const name = getInstanceName(instance).toLowerCase()
  return name.indexOf(filter) > -1
}

/**
 * Capture the meta information of an instance. (recursive)
 *
 * @param {Vue} instance
 * @return {Object}
 */

function capture (instance, _, list) {
  if (process.env.NODE_ENV !== 'production') {
    captureCount++
  }
  mark(instance)
  const ret = {
    id: instance._uid,
    name: getInstanceName(instance),
    inactive: !!instance._inactive,
    isFragment: !!instance._isFragment,
    children: instance.$children
      .filter(child => !child._isBeingDestroyed)
      .map(capture)
  }
  // record screen position to ensure correct ordering
  if ((!list || list.length > 1) && !instance._inactive) {
    const rect = getInstanceRect(instance)
    ret.top = rect ? rect.top : Infinity
  } else {
    ret.top = Infinity
  }
  // check if instance is available in console
  const consoleId = consoleBoundInstances.indexOf(instance._uid)
  ret.consoleId = consoleId > -1 ? '$vm' + consoleId : null
  // check router view
  const isRouterView2 = instance.$vnode && instance.$vnode.data.routerView
  if (instance._routerView || isRouterView2) {
    ret.isRouterView = true
    if (!instance._inactive) {
      const matched = instance.$route.matched
      const depth = isRouterView2
        ? instance.$vnode.data.routerViewDepth
        : instance._routerView.depth
      ret.matchedRouteSegment =
        matched &&
        matched[depth] &&
        (isRouterView2 ? matched[depth].path : matched[depth].handler.path)
    }
  }
  return ret
}

/**
 * Mark an instance as captured and store it in the instance map.
 *
 * @param {Vue} instance
 */

function mark (instance) {
  if (!instanceMap.has(instance._uid)) {
    instanceMap.set(instance._uid, instance)
    instance.$on('hook:beforeDestroy', function () {
      instanceMap.delete(instance._uid)
    })
  }
}

/**
 * Get the detailed information of an inspected instance.
 *
 * @param {Number} id
 */

function getInstanceDetails (id) {
  const instance = instanceMap.get(id)
  if (!instance) {
    return {}
  } else {
    return {
      id: id,
      name: getInstanceName(instance),
      state: processProps(instance).concat(
        processState(instance),
        processComputed(instance),
        processRouteContext(instance),
        processVuexGetters(instance),
        processFirebaseBindings(instance),
        processObservables(instance)
      )
    }
  }
}

/**
 * Get the appropriate display name for an instance.
 *
 * @param {Vue} instance
 * @return {String}
 */

export function getInstanceName (instance) {
  const name = instance.$options.name || instance.$options._componentTag
  if (name) {
    return classify(name)
  }
  const file = instance.$options.__file // injected by vue-loader
  if (file) {
    return classify(basename(file, '.vue'))
  }
  return instance.$root === instance
    ? 'Root'
    : 'Anonymous Component'
}

/**
 * Process the props of an instance.
 * Make sure return a plain object because window.postMessage()
 * will throw an Error if the passed object contains Functions.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processProps (instance) {
  let props
  if (isLegacy && (props = instance._props)) {
    // 1.x
    return Object.keys(props).map(key => {
      const prop = props[key]
      const options = prop.options
      return {
        type: 'props',
        key: prop.path,
        value: instance[prop.path],
        meta: {
          type: options.type ? getPropType(options.type) : 'any',
          required: !!options.required,
          mode: propModes[prop.mode]
        }
      }
    })
  } else if ((props = instance.$options.props)) {
    // 2.0
    const propsData = []
    for (let key in props) {
      const prop = props[key]
      key = camelize(key)
      propsData.push({
        type: 'props',
        key,
        value: instance[key],
        meta: {
          type: prop.type ? getPropType(prop.type) : 'any',
          required: !!prop.required
        }
      })
    }
    return propsData
  } else {
    return []
  }
}

/**
 * Convert prop type constructor to string.
 *
 * @param {Function} fn
 */

const fnTypeRE = /^(?:function|class) (\w+)/
function getPropType (type) {
  const match = type.toString().match(fnTypeRE)
  return typeof type === 'function'
    ? match && match[1] || 'any'
    : 'any'
}

/**
 * Process state, filtering out props and "clean" the result
 * with a JSON dance. This removes functions which can cause
 * errors during structured clone used by window.postMessage.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processState (instance) {
  const props = isLegacy
    ? instance._props
    : instance.$options.props
  const getters =
    instance.$options.vuex &&
    instance.$options.vuex.getters
  return Object.keys(instance._data)
    .filter(key => (
      !(props && key in props) &&
      !(getters && key in getters)
    ))
    .map(key => ({
      key,
      value: instance._data[key]
    }))
}

/**
 * Process the computed properties of an instance.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processComputed (instance) {
  const computed = []
  const defs = instance.$options.computed || {}
  // use for...in here because if 'computed' is not defined
  // on component, computed properties will be placed in prototype
  // and Object.keys does not include
  // properties from object's prototype
  for (const key in defs) {
    const def = defs[key]
    const type = typeof def === 'function' && def.vuex
      ? 'vuex bindings'
      : 'computed'
    // use try ... catch here because some computed properties may
    // throw error during its evaluation
    let computedProp = null
    try {
      computedProp = {
        type,
        key,
        value: instance[key]
      }
    } catch (e) {
      computedProp = {
        type,
        key,
        value: '(error during evaluation)'
      }
    }

    computed.push(computedProp)
  }

  return computed
}

/**
 * Process possible vue-router $route context
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processRouteContext (instance) {
  const route = instance.$route
  if (route) {
    const { path, query, params } = route
    const value = { path, query, params }
    if (route.fullPath) value.fullPath = route.fullPath
    if (route.hash) value.hash = route.hash
    if (route.name) value.name = route.name
    if (route.meta) value.meta = route.meta
    return [{
      key: '$route',
      value
    }]
  } else {
    return []
  }
}

/**
 * Process Vuex getters.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processVuexGetters (instance) {
  const getters =
    instance.$options.vuex &&
    instance.$options.vuex.getters
  if (getters) {
    return Object.keys(getters).map(key => {
      return {
        type: 'vuex getters',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Process Firebase bindings.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processFirebaseBindings (instance) {
  var refs = instance.$firebaseRefs
  if (refs) {
    return Object.keys(refs).map(key => {
      return {
        type: 'firebase bindings',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Process vue-rx observable bindings.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processObservables (instance) {
  var obs = instance.$observables
  if (obs) {
    return Object.keys(obs).map(key => {
      return {
        type: 'observables',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Sroll a node into view.
 *
 * @param {Vue} instance
 */

function scrollIntoView (instance) {
  const rect = getInstanceRect(instance)
  if (rect) {
    window.scrollBy(0, rect.top)
  }
}

/**
 * Binds given instance in console as $vm0.
 * For compatibility reasons it also binds it as $vm.
 *
 * @param {Vue} instance
 */

function bindToConsole (instance) {
  const id = instance._uid
  const index = consoleBoundInstances.indexOf(id)
  if (index > -1) {
    consoleBoundInstances.splice(index, 1)
  } else {
    consoleBoundInstances.pop()
  }
  consoleBoundInstances.unshift(id)
  for (var i = 0; i < 5; i++) {
    window['$vm' + i] = instanceMap.get(consoleBoundInstances[i])
  }
  window.$vm = instance
}
<commit_msg>fix instance id clashes with multiple roots on a page (#292)<commit_after>// This is the backend that is injected into the page that a Vue app lives in
// when the Vue Devtools panel is activated.

import { highlight, unHighlight, getInstanceRect } from './highlighter'
import { initVuexBackend } from './vuex'
import { initEventsBackend } from './events'
import { stringify, classify, camelize } from '../util'
import path from 'path'

// Use a custom basename functions instead of the shimed version
// because it doesn't work on Windows
function basename (filename, ext) {
  return path.basename(
    filename.replace(/^[a-zA-Z]:/, '').replace(/\\/g, '/'),
    ext
  )
}

// hook should have been injected before this executes.
const hook = window.__VUE_DEVTOOLS_GLOBAL_HOOK__
const rootInstances = []
const propModes = ['default', 'sync', 'once']

const instanceMap = window.__VUE_DEVTOOLS_INSTANCE_MAP__ = new Map()
const consoleBoundInstances = Array(5)
let currentInspectedId
let bridge
let filter = ''
let captureCount = 0
let isLegacy = false
let rootUID = 0

export function initBackend (_bridge) {
  bridge = _bridge
  if (hook.Vue) {
    isLegacy = hook.Vue.version && hook.Vue.version.split('.')[0] === '1'
    connect()
  } else {
    hook.once('init', connect)
  }
}

function connect () {
  hook.currentTab = 'components'
  bridge.on('switch-tab', tab => {
    hook.currentTab = tab
    if (tab === 'components') {
      flush()
    }
  })

  // the backend may get injected to the same page multiple times
  // if the user closes and reopens the devtools.
  // make sure there's only one flush listener.
  hook.off('flush')
  hook.on('flush', () => {
    if (hook.currentTab === 'components') {
      flush()
    }
  })

  bridge.on('select-instance', id => {
    currentInspectedId = id
    const instance = instanceMap.get(id)
    if (instance) {
      scrollIntoView(instance)
      highlight(instance)
    }
    bindToConsole(instance)
    flush()
    bridge.send('instance-details', stringify(getInstanceDetails(id)))
  })

  bridge.on('filter-instances', _filter => {
    filter = _filter.toLowerCase()
    flush()
  })

  bridge.on('refresh', scan)
  bridge.on('enter-instance', id => highlight(instanceMap.get(id)))
  bridge.on('leave-instance', unHighlight)

  // vuex
  if (hook.store) {
    initVuexBackend(hook, bridge)
  } else {
    hook.once('vuex:init', store => {
      initVuexBackend(hook, bridge)
    })
  }

  // events
  initEventsBackend(hook.Vue, bridge)

  bridge.log('backend ready.')
  bridge.send('ready', hook.Vue.version)
  console.log('[vue-devtools] Ready. Detected Vue v' + hook.Vue.version)
  scan()
}

/**
 * Scan the page for root level Vue instances.
 */

function scan () {
  rootInstances.length = 0
  let inFragment = false
  let currentFragment = null
  walk(document, function (node) {
    if (inFragment) {
      if (node === currentFragment._fragmentEnd) {
        inFragment = false
        currentFragment = null
      }
      return true
    }
    const instance = node.__vue__
    if (instance) {
      if (instance._isFragment) {
        inFragment = true
        currentFragment = instance
      }

      // respect Vue.config.devtools option
      let baseVue = instance.constructor
      while (baseVue.super) {
        baseVue = baseVue.super
      }
      if (baseVue.config && baseVue.config.devtools) {
        // give a unique id to root instance so we can
        // 'namespace' its children
        if (typeof instance.__VUE_DEVTOOLS_ROOT_UID__ === 'undefined') {
          instance.__VUE_DEVTOOLS_ROOT_UID__ = ++rootUID
        }
        rootInstances.push(instance)
      }

      return true
    }
  })
  flush()
}

/**
 * DOM walk helper
 *
 * @param {NodeList} nodes
 * @param {Function} fn
 */

function walk (node, fn) {
  if (node.childNodes) {
    for (let i = 0, l = node.childNodes.length; i < l; i++) {
      const child = node.childNodes[i]
      const stop = fn(child)
      if (!stop) {
        walk(child, fn)
      }
    }
  }

  // also walk shadow DOM
  if (node.shadowRoot) {
    walk(node.shadowRoot, fn)
  }
}

/**
 * Called on every Vue.js batcher flush cycle.
 * Capture current component tree structure and the state
 * of the current inspected instance (if present) and
 * send it to the devtools.
 */

function flush () {
  let start
  if (process.env.NODE_ENV !== 'production') {
    captureCount = 0
    start = window.performance.now()
  }
  const payload = stringify({
    inspectedInstance: getInstanceDetails(currentInspectedId),
    instances: findQualifiedChildrenFromList(rootInstances)
  })
  if (process.env.NODE_ENV !== 'production') {
    console.log(`[flush] serialized ${captureCount} instances, took ${window.performance.now() - start}ms.`)
  }
  bridge.send('flush', payload)
}

/**
 * Iterate through an array of instances and flatten it into
 * an array of qualified instances. This is a depth-first
 * traversal - e.g. if an instance is not matched, we will
 * recursively go deeper until a qualified child is found.
 *
 * @param {Array} instances
 * @return {Array}
 */

function findQualifiedChildrenFromList (instances) {
  instances = instances
    .filter(child => !child._isBeingDestroyed)
  return !filter
    ? instances.map(capture)
    : Array.prototype.concat.apply([], instances.map(findQualifiedChildren))
}

/**
 * Find qualified children from a single instance.
 * If the instance itself is qualified, just return itself.
 * This is ok because [].concat works in both cases.
 *
 * @param {Vue} instance
 * @return {Vue|Array}
 */

function findQualifiedChildren (instance) {
  return isQualified(instance)
    ? capture(instance)
    : findQualifiedChildrenFromList(instance.$children)
}

/**
 * Check if an instance is qualified.
 *
 * @param {Vue} instance
 * @return {Boolean}
 */

function isQualified (instance) {
  const name = getInstanceName(instance).toLowerCase()
  return name.indexOf(filter) > -1
}

/**
 * Capture the meta information of an instance. (recursive)
 *
 * @param {Vue} instance
 * @return {Object}
 */

function capture (instance, _, list) {
  if (process.env.NODE_ENV !== 'production') {
    captureCount++
  }
  // instance._uid is not reliable in devtools as there
  // may be 2 roots with same _uid which causes unexpected
  // behaviour
  instance.__VUE_DEVTOOLS_UID__ = getUniqueId(instance)
  mark(instance)
  const ret = {
    id: instance.__VUE_DEVTOOLS_UID__,
    name: getInstanceName(instance),
    inactive: !!instance._inactive,
    isFragment: !!instance._isFragment,
    children: instance.$children
      .filter(child => !child._isBeingDestroyed)
      .map(capture)
  }
  // record screen position to ensure correct ordering
  if ((!list || list.length > 1) && !instance._inactive) {
    const rect = getInstanceRect(instance)
    ret.top = rect ? rect.top : Infinity
  } else {
    ret.top = Infinity
  }
  // check if instance is available in console
  const consoleId = consoleBoundInstances.indexOf(instance.__VUE_DEVTOOLS_UID__)
  ret.consoleId = consoleId > -1 ? '$vm' + consoleId : null
  // check router view
  const isRouterView2 = instance.$vnode && instance.$vnode.data.routerView
  if (instance._routerView || isRouterView2) {
    ret.isRouterView = true
    if (!instance._inactive) {
      const matched = instance.$route.matched
      const depth = isRouterView2
        ? instance.$vnode.data.routerViewDepth
        : instance._routerView.depth
      ret.matchedRouteSegment =
        matched &&
        matched[depth] &&
        (isRouterView2 ? matched[depth].path : matched[depth].handler.path)
    }
  }
  return ret
}

/**
 * Mark an instance as captured and store it in the instance map.
 *
 * @param {Vue} instance
 */

function mark (instance) {
  if (!instanceMap.has(instance.__VUE_DEVTOOLS_UID__)) {
    instanceMap.set(instance.__VUE_DEVTOOLS_UID__, instance)
    instance.$on('hook:beforeDestroy', function () {
      instanceMap.delete(instance.__VUE_DEVTOOLS_UID__)
    })
  }
}

/**
 * Get the detailed information of an inspected instance.
 *
 * @param {Number} id
 */

function getInstanceDetails (id) {
  const instance = instanceMap.get(id)
  if (!instance) {
    return {}
  } else {
    return {
      id: id,
      name: getInstanceName(instance),
      state: processProps(instance).concat(
        processState(instance),
        processComputed(instance),
        processRouteContext(instance),
        processVuexGetters(instance),
        processFirebaseBindings(instance),
        processObservables(instance)
      )
    }
  }
}

/**
 * Get the appropriate display name for an instance.
 *
 * @param {Vue} instance
 * @return {String}
 */

export function getInstanceName (instance) {
  const name = instance.$options.name || instance.$options._componentTag
  if (name) {
    return classify(name)
  }
  const file = instance.$options.__file // injected by vue-loader
  if (file) {
    return classify(basename(file, '.vue'))
  }
  return instance.$root === instance
    ? 'Root'
    : 'Anonymous Component'
}

/**
 * Process the props of an instance.
 * Make sure return a plain object because window.postMessage()
 * will throw an Error if the passed object contains Functions.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processProps (instance) {
  let props
  if (isLegacy && (props = instance._props)) {
    // 1.x
    return Object.keys(props).map(key => {
      const prop = props[key]
      const options = prop.options
      return {
        type: 'props',
        key: prop.path,
        value: instance[prop.path],
        meta: {
          type: options.type ? getPropType(options.type) : 'any',
          required: !!options.required,
          mode: propModes[prop.mode]
        }
      }
    })
  } else if ((props = instance.$options.props)) {
    // 2.0
    const propsData = []
    for (let key in props) {
      const prop = props[key]
      key = camelize(key)
      propsData.push({
        type: 'props',
        key,
        value: instance[key],
        meta: {
          type: prop.type ? getPropType(prop.type) : 'any',
          required: !!prop.required
        }
      })
    }
    return propsData
  } else {
    return []
  }
}

/**
 * Convert prop type constructor to string.
 *
 * @param {Function} fn
 */

const fnTypeRE = /^(?:function|class) (\w+)/
function getPropType (type) {
  const match = type.toString().match(fnTypeRE)
  return typeof type === 'function'
    ? match && match[1] || 'any'
    : 'any'
}

/**
 * Process state, filtering out props and "clean" the result
 * with a JSON dance. This removes functions which can cause
 * errors during structured clone used by window.postMessage.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processState (instance) {
  const props = isLegacy
    ? instance._props
    : instance.$options.props
  const getters =
    instance.$options.vuex &&
    instance.$options.vuex.getters
  return Object.keys(instance._data)
    .filter(key => (
      !(props && key in props) &&
      !(getters && key in getters)
    ))
    .map(key => ({
      key,
      value: instance._data[key]
    }))
}

/**
 * Process the computed properties of an instance.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processComputed (instance) {
  const computed = []
  const defs = instance.$options.computed || {}
  // use for...in here because if 'computed' is not defined
  // on component, computed properties will be placed in prototype
  // and Object.keys does not include
  // properties from object's prototype
  for (const key in defs) {
    const def = defs[key]
    const type = typeof def === 'function' && def.vuex
      ? 'vuex bindings'
      : 'computed'
    // use try ... catch here because some computed properties may
    // throw error during its evaluation
    let computedProp = null
    try {
      computedProp = {
        type,
        key,
        value: instance[key]
      }
    } catch (e) {
      computedProp = {
        type,
        key,
        value: '(error during evaluation)'
      }
    }

    computed.push(computedProp)
  }

  return computed
}

/**
 * Process possible vue-router $route context
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processRouteContext (instance) {
  const route = instance.$route
  if (route) {
    const { path, query, params } = route
    const value = { path, query, params }
    if (route.fullPath) value.fullPath = route.fullPath
    if (route.hash) value.hash = route.hash
    if (route.name) value.name = route.name
    if (route.meta) value.meta = route.meta
    return [{
      key: '$route',
      value
    }]
  } else {
    return []
  }
}

/**
 * Process Vuex getters.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processVuexGetters (instance) {
  const getters =
    instance.$options.vuex &&
    instance.$options.vuex.getters
  if (getters) {
    return Object.keys(getters).map(key => {
      return {
        type: 'vuex getters',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Process Firebase bindings.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processFirebaseBindings (instance) {
  var refs = instance.$firebaseRefs
  if (refs) {
    return Object.keys(refs).map(key => {
      return {
        type: 'firebase bindings',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Process vue-rx observable bindings.
 *
 * @param {Vue} instance
 * @return {Array}
 */

function processObservables (instance) {
  var obs = instance.$observables
  if (obs) {
    return Object.keys(obs).map(key => {
      return {
        type: 'observables',
        key,
        value: instance[key]
      }
    })
  } else {
    return []
  }
}

/**
 * Sroll a node into view.
 *
 * @param {Vue} instance
 */

function scrollIntoView (instance) {
  const rect = getInstanceRect(instance)
  if (rect) {
    window.scrollBy(0, rect.top)
  }
}

/**
 * Binds given instance in console as $vm0.
 * For compatibility reasons it also binds it as $vm.
 *
 * @param {Vue} instance
 */

function bindToConsole (instance) {
  const id = instance.__VUE_DEVTOOLS_UID__
  const index = consoleBoundInstances.indexOf(id)
  if (index > -1) {
    consoleBoundInstances.splice(index, 1)
  } else {
    consoleBoundInstances.pop()
  }
  consoleBoundInstances.unshift(id)
  for (var i = 0; i < 5; i++) {
    window['$vm' + i] = instanceMap.get(consoleBoundInstances[i])
  }
  window.$vm = instance
}

/**
 * Returns a devtools unique id for instance.
 * @param {Vue} instance
 */
function getUniqueId (instance) {
  const rootVueId = instance.$root.__VUE_DEVTOOLS_ROOT_UID__
  return `${rootVueId}:${instance._uid}`
}
<|endoftext|>


<commit_before>var MongoClient = require('../../node_modules/mongodb').MongoClient;

MongoClient.connect(SP_DB_CONNECTION_STRING, function (err, db) {
    if (err) {
        console.error('Unable to connect to mongo server.');
    } else {
        console.log('Mongo online:', SP_DB_CONNECTION_STRING);
        global.DB_SERVER = db;
    }
});<commit_msg>console log mongo error<commit_after>var MongoClient = require('../../node_modules/mongodb').MongoClient;

MongoClient.connect(SP_DB_CONNECTION_STRING, function (err, db) {
    if (err) {
        console.error('Unable to connect to mongo server.');
        console.log(err);
    } else {
        console.log('Mongo online:', SP_DB_CONNECTION_STRING);
        global.DB_SERVER = db;
    }
});
<|endoftext|>