Remove test/vti/test_serving code, no longer used

This project was removed from the manifest in Dec'21 with aosp/1920522

This change will ensure that automated code scanners aren't reporting
issues on it.

Bug: 253296312
Change-Id: If2722726f5c90fb84602f2e89ceb171ed1e4e255
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975c..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
-  license_type: NOTICE
-}
diff --git a/OWNERS b/OWNERS
deleted file mode 100644
index 2132cd7..0000000
--- a/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-yim@google.com
-dchon@google.com
-hyunwooko@google.com
-jongmok@google.com
-younggyu@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 7049c8c..0000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-[Builtin Hooks]
-clang_format = true
-
-[Builtin Hooks Options]
-clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp,java
-
-[Hook Scripts]
-test_serving_unittests = ${REPO_ROOT}/test/framework/script/run-unittest.sh
-
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/__init__.py
+++ /dev/null
diff --git a/configs/global/Android.mk b/configs/global/Android.mk
deleted file mode 100644
index aba3244..0000000
--- a/configs/global/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vti-global-config-prod-zip :=
-vti-global-config-test-zip :=
-
-dirs := $(strip \
-  $(wildcard test/vti/test_serving/configs/global/prod) \
-  $(wildcard vendor/google_vts/configs/global/prod))
-ifdef dirs
-vti-global-config-prod-zip := $(HOST_OUT)/vti-global-config/vti-global-config-prod.zip
-$(vti-global-config-prod-zip): $(SOONG_ZIP) $(call find-files-in-subdirs,.,"*.*_config", $(dirs))
-	@echo "build vti config package: $@"
-	$(hide) mkdir -p $(dir $@)
-	$(hide) rm -f $@
-	$(hide) find test/vti/test_serving/configs/global/prod/ -name '*.*_config' | sort > $@.list
-	$(hide) find vendor/google_vts/configs/global/prod/ -name '*.*_config' | sort > $@.list.vendor
-	$(hide) $(SOONG_ZIP) -d -o $@ -C test/vti/test_serving/configs/global -l $@.list \
-	    -C vendor/google_vts/configs/global -l $@.list.vendor
-	$(hide) rm -f $@.list $@.list.vendor
-endif
-
-dirs := $(strip \
-    $(wildcard test/vti/test_serving/configs/global/test) \
-    $(wildcard vendor/google_vts/configs/global/test))
-ifdef dirs
-vti-global-config-test-zip := $(HOST_OUT)/vti-global-config/vti-global-config-test.zip
-$(vti-global-config-test-zip): $(SOONG_ZIP) $(call find-files-in-subdirs,.,"*.*_config", $(dirs))
-	@echo "build vti config package: $@"
-	$(hide) mkdir -p $(dir $@)
-	$(hide) rm -f $@
-	$(hide) find test/vti/test_serving/configs/global/test/ -name '*.*_config' | sort > $@.list
-	$(hide) find vendor/google_vts/configs/global/test/ -name '*.*_config' | sort > $@.list.vendor
-	$(hide) $(SOONG_ZIP) -d -o $@ -C test/vti/test_serving/configs/global -l $@.list \
-	    -C vendor/google_vts/configs/global -l $@.list.vendor
-	$(hide) rm -f $@.list $@.list.vendor
-endif
-
-.PHONY: vti-global-config
-vti-global-config: $(vti-global-config-prod-zip) $(vti-global-config-test-zip)
-$(call dist-for-goals, vti-global-config, $(vti-global-config-prod-zip) $(vti-global-config-test-zip))
-
-.PHONY: vti-config
-vti-config: vti-global-config
-
-.PHONY: vti
-vti: vti-config
-
-.PHONY: vts
-vts: vti-config
diff --git a/configs/infra/prod/androidtestcenter/bots.cfg b/configs/infra/prod/androidtestcenter/bots.cfg
deleted file mode 100644
index d48675f..0000000
--- a/configs/infra/prod/androidtestcenter/bots.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-#
-# Schema: BotsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/bots.proto
-
-trusted_dimensions: "pool"
-bot_group {
-  bot_id_prefix: "homedemo"
-  owners: "yim@google.com"
-  auth {
-    require_luci_machine_token: false
-    ip_whitelist: "vtslab-swarming-bots"
-  }
-  dimensions: "pool:home-demo"
-  bot_config_script: "home_bot_config.py"
-}
-
diff --git a/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py b/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py
deleted file mode 100644
index fe078fa..0000000
--- a/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# coding: utf-8
-# Copyright 2013 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-"""bot_config for swarming bots running in Home CI.
-
-A copy of this file is downloaded to every swarming bot automatically.
-Updates to this file are propogated to bots within ~10 minutes.
-
-Prerequisites:
-  - bot has eurtest_libs installed via: cipd install home_internal/eurtest_libs
-  - eurtest_libs directory is in PYTHONPATH
-
-There's 3 types of functions in this file:
-  - get_*() to return properties to describe this bot.
-  - on_*() as hooks based on events happening on the bot.
-  - setup_*() to setup global state on the host.
-"""
-
-import collections
-import json
-import logging
-import os
-import re
-import sys
-import time
-
-from api import os_utilities
-from api import platforms
-
-# Hack to de-prioritize sys.path variables that bot_code imports which are
-# incompatible with the libraries we're importing below.
-# see https://crbug.com/758609
-sys.path.sort(key=lambda x: 'swarm_env' not in x)
-# each bot must be run in a virtualenv that has eurtest_libs in PYTHONPATH
-try:
-  from eurtest.device import device as device_lib
-  from utilities import ssh_helper
-except ImportError as e:
-  sys.stderr.write('Exception: %s\n' % e)
-  sys.stderr.write('sys.path:\n%s' % str(sys.path))
-  # Temporary while debugging issue
-  import google
-  print 'google.__path__: %s' % str(google.__path__)
-  raise
-
-# Unused argument 'bot' - pylint: disable=W0613
-DeviceBot = collections.namedtuple('DeviceBot', 'dimensions state')
-
-
-def device(device_type, ip, groups=None, nic=None, serial=None, extra_state=None):
-  if not hasattr(ip, '__iter__'):
-    ip = [ip]
-  dimensions = {
-    u'device_ip': ip,
-    u'device_type': [device_type],
-    u'group': groups or ['COMMON'],
-    u'nic': [nic or 'ethernet'],
-  }
-  # You can't advertise a key that cannot be selected,
-  # so only set a dimension key if the value is not None
-  if serial:
-    dimensions[u'serial'] = [serial]
-  if len(ip) > 1:
-    dimensions[u'group'].append('multiconfig_box')
-  return DeviceBot(dimensions, extra_state)
-
-_BOT_DEVICE_MAP = {
-  ### home-demo pool ### - enforced via bot name prefix
-  'homedemo--1': device('assistantdefault', '1.2.3.4', ['abc_test']),
-}
-
-# global for caching device properties gathered dynamically during runtime
-_DEVICE = None
-
-### Helper Methods
-
-
-class SSHError(Exception):
-  pass
-
-
-class Device(object):
-  """Retrieves device property information for a device over SSH."""
-  # amount of time (secs) until state is due for a refresh
-  _STALE_STATE_DELTA = 60
-
-  def __init__(self, device_ip, bot_id):
-    self.device_ip = device_ip
-    self.bot_id = bot_id
-    self._device_client = device_lib.Device(
-        ethernet_ip=self.device_ip)
-    self._device_client.UseSsh()
-    self._last_connect_succeeded = False
-    self._properties = {}
-    self._stale_state_ts = 0
-
-  @property
-  def build_fingerprint(self):
-    return self.properties.get('ro.build.fingerprint', None)
-
-  @property
-  def hardware(self):
-    return self.properties.get('ro.hardware', None)
-
-  @property
-  def is_reachable(self):
-    """Checks if device is reachable over ssh."""
-    if self._properties is None or time.time() > self._stale_state_ts:
-      self._properties = self._fetch_properties()
-    return self._last_connect_succeeded
-
-  @property
-  def product(self):
-    return self.properties.get('ro.build.product', None)
-
-  @property
-  def properties(self):
-    """Returns all of the last-known device properties as a dict."""
-    if self._properties is None or time.time() > self._stale_state_ts:
-      try:
-        # Keep last-known properties when SSHError is raised
-        self._properties = self._fetch_properties()
-      except SSHError as e:
-        logging.exception(e)
-    return self._properties
-
-  def _exec_ssh_cmd(self, cmd):
-    """Executes the given cmd against the device over SSH.
-    Arguments:
-    - cmd: the command to be run on the device over ssh.
-    Returns:
-      stdout of cmd output
-    Raises:
-      SSHError: upon ssh cmd exec failure
-    """
-    # Temporary: fetch device properties from static local file when present.
-    # This let's us demo what our swarm bots will look like, even though the
-    # demo host ('voyager') is on a lab network in WAT that can't reach the
-    # MTV devices over ssh.  The real device properties are fetched over ssh
-    # by a script on Corp and copied to the swarm host before starting bots.
-    # TODO(jonesmi): remove this temporary workaround when bots run in MTV lab
-    bot_common_dir = os.getenv('BOT_COMMON_DIR')
-    if bot_common_dir:
-      props_file = os.path.join(bot_common_dir, '%s.props' % self.bot_id)
-      if os.path.isfile(props_file):
-        with open(props_file, 'r') as f:
-          # pretend that we read this from SSH connection
-          self._last_connect_succeeded = True
-          return f.read()
-    try:
-      if self._device_client.Cmd(cmd, timeout_secs=30):
-        self._last_connect_succeeded = True
-        return self._device_client.GetCmdOutput()
-      else:
-        self._last_connect_succeeded = False
-        raise SSHError('failed to execute cmd over ssh: %s' % cmd)
-    except ssh_helper.CommandThreadTimeoutError:
-      self._last_connect_succeeded = False
-      raise SSHError('timeout when waiting for ssh connect: %s' % cmd)
-
-  def _fetch_properties(self):
-    """Fetches device properties over ssh using getprop command."""
-    self._stale_state_ts = time.time() + self._STALE_STATE_DELTA
-    properties = {}
-    stdout = self._exec_ssh_cmd('getprop')
-    for line in stdout.strip().split('\n'):
-      match = re.match(r'\[(.*)\]: \[(.*)\]', line)
-      if match:
-        properties[match.group(1)] = match.group(2)
-    return properties
-
-
-### _get* Hooks
-def get_dimensions(bot):
-  # pylint: disable=line-too-long
-  """Returns dict with the bot's dimensions.
-  The dimensions are what are used to select the bot that can run each task.
-  The bot id will be automatically selected based on the hostname with
-  os_utilities.get_dimensions(). If you want something more special, specify it
-  in your bot_config.py and override the item 'id'.
-  The dimensions returned here will be joined with server defined dimensions
-  (extracted from bots.cfg config file based on the bot id). Server defined
-  dimensions override the ones provided by the bot. See bot.Bot.dimensions for
-  more information.
-  See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
-  Arguments:
-  - bot: bot.Bot instance or None. See ../api/bot.py.
-  """
-  dimensions = os_utilities.get_dimensions()
-  # The bot base directory is formatted like <HOME>/bots/<Id>
-  id = '%s--%s' % (
-      os_utilities.get_hostname_short(),
-      os.path.basename(bot.base_dir))
-  dimensions[u'id'] = [id]
-  if id in _BOT_DEVICE_MAP:
-    dimensions.update(_BOT_DEVICE_MAP[id].dimensions)
-    global _DEVICE
-    if not _DEVICE:
-      device_ip = dimensions[u'device_ip']
-      # use first device_ip in list of device IPs for pulling device attributes
-      if device_ip:
-        assert isinstance(device_ip, (list, tuple)), repr(device_ip)
-        _DEVICE = Device(device_ip[0], id)
-    if _DEVICE:
-      dimensions[u'build'] = _DEVICE.build_fingerprint,
-      dimensions[u'hardware'] = _DEVICE.hardware,
-      dimensions[u'product'] = _DEVICE.product,
-  # TODO(jonesmi): don't strip these anymore after swarming fix goes in for limit on # dimensions
-  del dimensions[u'cores']
-  del dimensions[u'cpu']
-  del dimensions[u'gpu']
-  del dimensions[u'machine_type']
-  return dimensions
-
-
-def get_state(bot):
-  # pylint: disable=line-too-long
-  """Returns dict with a state of the bot reported to the server with each poll.
-  It is only for dynamic state that changes while bot is running for information
-  for the sysadmins.
-  The server can not use this state for immediate scheduling purposes (use
-  'dimensions' for that), but it can use it for maintenance and bookkeeping
-  tasks.
-  See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
-  Arguments:
-  - bot: bot.Bot instance or None. See ../api/bot.py.
-  """
-  state = os_utilities.get_state()
-  if _DEVICE:
-    state[u'device'] = _DEVICE.properties
-    if _DEVICE.bot_id in _BOT_DEVICE_MAP:
-      extra_state = _BOT_DEVICE_MAP[_DEVICE.bot_id].state
-      if extra_state:
-        state[u'device'].update(extra_state)
-    if not _DEVICE.is_reachable:
-      state[u'quarantined'] = 'device is not reachable'
-  return state
-
-
-def get_authentication_headers(bot):
-  """Returns authentication headers and their expiration time.
-  The returned headers will be passed with each HTTP request to the Swarming
-  server (and only Swarming server). The bot will use the returned headers until
-  they are close to expiration (usually 6 min, see AUTH_HEADERS_EXPIRATION_SEC
-  in remote_client.py), and then it'll attempt to refresh them by calling
-  get_authentication_headers again.
-  Can be used to implement per-bot authentication. If no headers are returned,
-  the server will use only IP whitelist for bot authentication.
-  On GCE will use OAuth token of the default GCE service account. It should have
-  "User info" API scope enabled (this can be set when starting an instance). The
-  server should be configured (via bots.cfg) to trust this account (see
-  'require_service_account' in bots.proto).
-  May be called by different threads, but never concurrently.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  Returns:
-    Tuple (dict with headers or None, unix timestamp of when they expire).
-  """
-  if platforms.is_gce():
-    tok = platforms.gce.oauth2_access_token()
-    return {'Authorization': 'Bearer %s' % tok}, time.time() + 5*60
-  return (None, None)
-
-
-### on_* Hooks
-def on_bot_shutdown(bot):
-  """Hook function called when the bot shuts down, usually rebooting.
-  It's a good time to do other kinds of cleanup.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  """
-  pass
-
-
-def on_handshake(bot):
-  """Hook function called when the bot starts, after handshake with the server.
-  Here the bot already knows server enforced dimensions (defined in server side
-  bots.cfg file).
-  This is called right before starting to poll for tasks. It's a good time to
-  do some final initialization or cleanup that may depend on server provided
-  configuration.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  """
-  pass
-
-
-def on_before_task(bot, bot_file):
-  """Hook function called before running a task.
-  It shouldn't do much, since it can't cancel the task so it shouldn't do
-  anything too fancy.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - bot_file: Path to file to write information about the state of the bot.
-              This file can be used to pass certain info about the bot
-              to tasks, such as which connected android devices to run on. See
-              https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md#run_isolated
-  """
-  with open(bot_file, 'wb') as f:
-    json.dump(bot.dimensions, f)
-
-
-def on_after_task(bot, failure, internal_failure, dimensions, summary):
-  """Hook function called after running a task.
-  It is an excellent place to do post-task cleanup of temporary files.
-  The default implementation restarts after a task failure or an internal
-  failure.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - failure: bool, True if the task failed.
-  - internal_failure: bool, True if an internal failure happened.
-  - dimensions: dict, Dimensions requested as part of the task.
-  - summary: dict, Summary of the task execution.
-  """
-  # Example code:
-  #if failure:
-  #  bot.restart('Task failure')
-  #elif internal_failure:
-  #  bot.restart('Internal failure')
-
-
-def on_bot_idle(bot, since_last_action):
-  """Hook function called once when the bot has been idle; when it has no
-  command to execute.
-  This is an excellent place to put device in 'cool down' mode or any
-  "pre-warming" kind of stuff that could take several seconds to do, that would
-  not be appropriate to do in on_after_task(). It could be worth waiting for
-  `since_last_action` to be several seconds before doing a more lengthy
-  operation.
-  This function is called repeatedly until an action is taken (a task, updating,
-  etc).
-  This is a good place to do "auto reboot" for hardware based bots that are
-  rebooted periodically.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - since_last_action: time in second since last action; e.g. amount of time the
-                       bot has been idle.
-  """
-  pass
diff --git a/configs/infra/prod/androidtestcenter/settings.cfg b/configs/infra/prod/androidtestcenter/settings.cfg
deleted file mode 100644
index 1f6777b..0000000
--- a/configs/infra/prod/androidtestcenter/settings.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-# Browse online: https://androidtestcenter.appspot.com/restricted/config
-#
-# Schema: SettingsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/config.proto
-
-google_analytics: "UA-107546859-1"
-reusable_task_age_secs: 604800
-bot_death_timeout_secs: 600
-enable_ts_monitoring: true
-ui_client_id: "849130811101-pk615h6979i256cb243t2cacjohamkq7.apps.googleusercontent.com"
-display_server_url_template: "https://androidtestcenter.appspot.com/swarming/task/%s"
-isolate {
-  default_server: "https://vtslab-isolate-prod.appspot.com"
-  default_namespace: "default-gzip"
-}
-mp {
-  enabled: true
-}
-auth {
-  admins_group: "vtslab-swarming-admins"
-  bot_bootstrap_group: "vtslab-swarming-bot-bootstrap"
-  privileged_users_group: "vtslab-swarming-privileged-users"
-  users_group: "vtslab-swarming-users"
-  view_all_bots_group: "vtslab-swarming-view-all-bots"
-  view_all_tasks_group: "vtslab-swarming-view-all-tasks"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/acl.cfg b/configs/infra/prod/vtslab-config-prod/acl.cfg
deleted file mode 100644
index 0da0ca1..0000000
--- a/configs/infra/prod/vtslab-config-prod/acl.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:acl.cfg
-# *** WARNING ***
-# This file is sensitive. project_access_group specifies a super group
-# that has access to all projects, including internal ones.
-# This file is cached in process memory of instances for 10min
-# because it ~never changes.
-admin_group: "vtslab-config-admins"
-project_access_group: "vtslab-config-project-access"
diff --git a/configs/infra/prod/vtslab-config-prod/import.cfg b/configs/infra/prod/vtslab-config-prod/import.cfg
deleted file mode 100644
index d956889..0000000
--- a/configs/infra/prod/vtslab-config-prod/import.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:import.cfg
-gitiles {
-  project_config_default_ref: "refs/heads/infra/config"
-  ref_config_default_path: "infra/config"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/projects.cfg b/configs/infra/prod/vtslab-config-prod/projects.cfg
deleted file mode 100644
index 3f00a7d..0000000
--- a/configs/infra/prod/vtslab-config-prod/projects.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:projects.cfg
-#
-# Please keep the list sorted by project id!
-projects {
-  id: "aosp-master-vts"
-  config_location {
-    url: "https://android.googlesource.com/platform/test/vts/"
-    storage_type: GITILES
-  }
-}
-
-projects {
-  id: "aosp-master-goldfish"
-  config_location {
-    url: "https://android.googlesource.com/device/generic/goldfish/"
-    storage_type: GITILES
-  }
-}
diff --git a/configs/infra/prod/vtslab-config-prod/schemas.cfg b/configs/infra/prod/vtslab-config-prod/schemas.cfg
deleted file mode 100644
index 4ba2ae9..0000000
--- a/configs/infra/prod/vtslab-config-prod/schemas.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:schemas.cfg
-#
-# Please keep this list sorted by schema name.
-#
-################################################################################
-# WARNING: names and urls in this file will be exposed publicly. Do not put
-# internal stuff here!!!
-################################################################################
-################################################################################
-# ref configs
-schemas {
-  name: "projects/refs:cq.cfg"
-  url: "https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/third_party/cq_client/cq.proto"
-}
-################################################################################
-# project configs
-schemas {
-  name: "projects:buildbucket.cfg"
-  url: "https://chromium.googlesource.com/infra/infra/+/master/appengine/cr-buildbucket/proto/project_config.proto"
-}
-schemas {
-  name: "projects:refs.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-schemas {
-  name: "projects:project.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-################################################################################
-# luci-config service schemas
-schemas {
-  name: "services/luci-config:acl.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:import.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:projects.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:services.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:schemas.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-################################################################################
-# chrome-infra-auth service schemas.
-schemas {
-  name: "services/chrome-infra-auth:delegation.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:imports.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:ip_whitelist.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:oauth.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-################################################################################
-# LUCI LogDog service schemas.
-schemas {
-  name: "services/luci-logdog:services.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/config.proto"
-}
-schemas {
-  name: "services/luci-logdog:logdog.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/project.proto"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/services.cfg b/configs/infra/prod/vtslab-config-prod/services.cfg
deleted file mode 100644
index a9b22d6..0000000
--- a/configs/infra/prod/vtslab-config-prod/services.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-# Schema for this file: ServicesCfg message in
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:services.cfg
-#
-# Please keep the list sorted by id.
-#
-# *** WARNING
-# This file is sensitive. These services may receive contents of any config
-# files for validation purposes, including configs of internal projects.
-# ***
-################################################################################
-# Swarming
-services {
-  id: "androidtestcenter"
-  owners: "yim@google.com"
-  metadata_url: "https://androidtestcenter.appspot.com/_ah/api/config/v1/metadata"
-  access: "androidtestcenter@appspot.gserviceaccount.com"
-}
-################################################################################
-# Auth
-services {
-  id: "vtslab-auth-prod"
-  owners: "yim@google.com"
-  metadata_url: "https://vtslab-auth-prod.appspot.com/_ah/api/config/v1/metadata"
-  access: "vtslab-auth-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Commit Queue
-# services {
-#   id: "commit-queue"
-#   owners: "yim@google.com"
-#   metadata_url: "https://vtslab-cq-prod.appspot.com/api/metadata"
-# }
-################################################################################
-# GCE Backend
-services {
-  id: "vtslab-backend-prod"
-  owners: "yim@google.com"
-  access: "vtslab-backend-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# LUCI / Isolate Server
-services {
-  id: "vtslab-isolate-prod"
-  owners: "yim@google.com"
-  metadata_url: "https://vtslab-isolate-prod.appspot.com/_ah/api/config/v1/metadata"
-  access: "vtslab-isolate-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Machine Provider
-services {
-  id: "vtslab-machine-prod"
-  owners: "yim@google.com"
-  access: "vtslab-machine-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Doc Indexer
-services {
-  id: "vtslab-doc"
-  owners: "yim@google.com"
-}
diff --git a/configs/infra/test/androidtestcenter-test/bots.cfg b/configs/infra/test/androidtestcenter-test/bots.cfg
deleted file mode 100644
index d48675f..0000000
--- a/configs/infra/test/androidtestcenter-test/bots.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-#
-# Schema: BotsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/bots.proto
-
-trusted_dimensions: "pool"
-bot_group {
-  bot_id_prefix: "homedemo"
-  owners: "yim@google.com"
-  auth {
-    require_luci_machine_token: false
-    ip_whitelist: "vtslab-swarming-bots"
-  }
-  dimensions: "pool:home-demo"
-  bot_config_script: "home_bot_config.py"
-}
-
diff --git a/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py b/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py
deleted file mode 100644
index fe078fa..0000000
--- a/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# coding: utf-8
-# Copyright 2013 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-"""bot_config for swarming bots running in Home CI.
-
-A copy of this file is downloaded to every swarming bot automatically.
-Updates to this file are propogated to bots within ~10 minutes.
-
-Prerequisites:
-  - bot has eurtest_libs installed via: cipd install home_internal/eurtest_libs
-  - eurtest_libs directory is in PYTHONPATH
-
-There's 3 types of functions in this file:
-  - get_*() to return properties to describe this bot.
-  - on_*() as hooks based on events happening on the bot.
-  - setup_*() to setup global state on the host.
-"""
-
-import collections
-import json
-import logging
-import os
-import re
-import sys
-import time
-
-from api import os_utilities
-from api import platforms
-
-# Hack to de-prioritize sys.path variables that bot_code imports which are
-# incompatible with the libraries we're importing below.
-# see https://crbug.com/758609
-sys.path.sort(key=lambda x: 'swarm_env' not in x)
-# each bot must be run in a virtualenv that has eurtest_libs in PYTHONPATH
-try:
-  from eurtest.device import device as device_lib
-  from utilities import ssh_helper
-except ImportError as e:
-  sys.stderr.write('Exception: %s\n' % e)
-  sys.stderr.write('sys.path:\n%s' % str(sys.path))
-  # Temporary while debugging issue
-  import google
-  print 'google.__path__: %s' % str(google.__path__)
-  raise
-
-# Unused argument 'bot' - pylint: disable=W0613
-DeviceBot = collections.namedtuple('DeviceBot', 'dimensions state')
-
-
-def device(device_type, ip, groups=None, nic=None, serial=None, extra_state=None):
-  if not hasattr(ip, '__iter__'):
-    ip = [ip]
-  dimensions = {
-    u'device_ip': ip,
-    u'device_type': [device_type],
-    u'group': groups or ['COMMON'],
-    u'nic': [nic or 'ethernet'],
-  }
-  # You can't advertise a key that cannot be selected,
-  # so only set a dimension key if the value is not None
-  if serial:
-    dimensions[u'serial'] = [serial]
-  if len(ip) > 1:
-    dimensions[u'group'].append('multiconfig_box')
-  return DeviceBot(dimensions, extra_state)
-
-_BOT_DEVICE_MAP = {
-  ### home-demo pool ### - enforced via bot name prefix
-  'homedemo--1': device('assistantdefault', '1.2.3.4', ['abc_test']),
-}
-
-# global for caching device properties gathered dynamically during runtime
-_DEVICE = None
-
-### Helper Methods
-
-
-class SSHError(Exception):
-  pass
-
-
-class Device(object):
-  """Retrieves device property information for a device over SSH."""
-  # amount of time (secs) until state is due for a refresh
-  _STALE_STATE_DELTA = 60
-
-  def __init__(self, device_ip, bot_id):
-    self.device_ip = device_ip
-    self.bot_id = bot_id
-    self._device_client = device_lib.Device(
-        ethernet_ip=self.device_ip)
-    self._device_client.UseSsh()
-    self._last_connect_succeeded = False
-    self._properties = {}
-    self._stale_state_ts = 0
-
-  @property
-  def build_fingerprint(self):
-    return self.properties.get('ro.build.fingerprint', None)
-
-  @property
-  def hardware(self):
-    return self.properties.get('ro.hardware', None)
-
-  @property
-  def is_reachable(self):
-    """Checks if device is reachable over ssh."""
-    if self._properties is None or time.time() > self._stale_state_ts:
-      self._properties = self._fetch_properties()
-    return self._last_connect_succeeded
-
-  @property
-  def product(self):
-    return self.properties.get('ro.build.product', None)
-
-  @property
-  def properties(self):
-    """Returns all of the last-known device properties as a dict."""
-    if self._properties is None or time.time() > self._stale_state_ts:
-      try:
-        # Keep last-known properties when SSHError is raised
-        self._properties = self._fetch_properties()
-      except SSHError as e:
-        logging.exception(e)
-    return self._properties
-
-  def _exec_ssh_cmd(self, cmd):
-    """Executes the given cmd against the device over SSH.
-    Arguments:
-    - cmd: the command to be run on the device over ssh.
-    Returns:
-      stdout of cmd output
-    Raises:
-      SSHError: upon ssh cmd exec failure
-    """
-    # Temporary: fetch device properties from static local file when present.
-    # This let's us demo what our swarm bots will look like, even though the
-    # demo host ('voyager') is on a lab network in WAT that can't reach the
-    # MTV devices over ssh.  The real device properties are fetched over ssh
-    # by a script on Corp and copied to the swarm host before starting bots.
-    # TODO(jonesmi): remove this temporary workaround when bots run in MTV lab
-    bot_common_dir = os.getenv('BOT_COMMON_DIR')
-    if bot_common_dir:
-      props_file = os.path.join(bot_common_dir, '%s.props' % self.bot_id)
-      if os.path.isfile(props_file):
-        with open(props_file, 'r') as f:
-          # pretend that we read this from SSH connection
-          self._last_connect_succeeded = True
-          return f.read()
-    try:
-      if self._device_client.Cmd(cmd, timeout_secs=30):
-        self._last_connect_succeeded = True
-        return self._device_client.GetCmdOutput()
-      else:
-        self._last_connect_succeeded = False
-        raise SSHError('failed to execute cmd over ssh: %s' % cmd)
-    except ssh_helper.CommandThreadTimeoutError:
-      self._last_connect_succeeded = False
-      raise SSHError('timeout when waiting for ssh connect: %s' % cmd)
-
-  def _fetch_properties(self):
-    """Fetches device properties over ssh using getprop command."""
-    self._stale_state_ts = time.time() + self._STALE_STATE_DELTA
-    properties = {}
-    stdout = self._exec_ssh_cmd('getprop')
-    for line in stdout.strip().split('\n'):
-      match = re.match(r'\[(.*)\]: \[(.*)\]', line)
-      if match:
-        properties[match.group(1)] = match.group(2)
-    return properties
-
-
-### _get* Hooks
-def get_dimensions(bot):
-  # pylint: disable=line-too-long
-  """Returns dict with the bot's dimensions.
-  The dimensions are what are used to select the bot that can run each task.
-  The bot id will be automatically selected based on the hostname with
-  os_utilities.get_dimensions(). If you want something more special, specify it
-  in your bot_config.py and override the item 'id'.
-  The dimensions returned here will be joined with server defined dimensions
-  (extracted from bots.cfg config file based on the bot id). Server defined
-  dimensions override the ones provided by the bot. See bot.Bot.dimensions for
-  more information.
-  See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
-  Arguments:
-  - bot: bot.Bot instance or None. See ../api/bot.py.
-  """
-  dimensions = os_utilities.get_dimensions()
-  # The bot base directory is formatted like <HOME>/bots/<Id>
-  id = '%s--%s' % (
-      os_utilities.get_hostname_short(),
-      os.path.basename(bot.base_dir))
-  dimensions[u'id'] = [id]
-  if id in _BOT_DEVICE_MAP:
-    dimensions.update(_BOT_DEVICE_MAP[id].dimensions)
-    global _DEVICE
-    if not _DEVICE:
-      device_ip = dimensions[u'device_ip']
-      # use first device_ip in list of device IPs for pulling device attributes
-      if device_ip:
-        assert isinstance(device_ip, (list, tuple)), repr(device_ip)
-        _DEVICE = Device(device_ip[0], id)
-    if _DEVICE:
-      dimensions[u'build'] = _DEVICE.build_fingerprint,
-      dimensions[u'hardware'] = _DEVICE.hardware,
-      dimensions[u'product'] = _DEVICE.product,
-  # TODO(jonesmi): don't strip these anymore after swarming fix goes in for limit on # dimensions
-  del dimensions[u'cores']
-  del dimensions[u'cpu']
-  del dimensions[u'gpu']
-  del dimensions[u'machine_type']
-  return dimensions
-
-
-def get_state(bot):
-  # pylint: disable=line-too-long
-  """Returns dict with a state of the bot reported to the server with each poll.
-  It is only for dynamic state that changes while bot is running for information
-  for the sysadmins.
-  The server can not use this state for immediate scheduling purposes (use
-  'dimensions' for that), but it can use it for maintenance and bookkeeping
-  tasks.
-  See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
-  Arguments:
-  - bot: bot.Bot instance or None. See ../api/bot.py.
-  """
-  state = os_utilities.get_state()
-  if _DEVICE:
-    state[u'device'] = _DEVICE.properties
-    if _DEVICE.bot_id in _BOT_DEVICE_MAP:
-      extra_state = _BOT_DEVICE_MAP[_DEVICE.bot_id].state
-      if extra_state:
-        state[u'device'].update(extra_state)
-    if not _DEVICE.is_reachable:
-      state[u'quarantined'] = 'device is not reachable'
-  return state
-
-
-def get_authentication_headers(bot):
-  """Returns authentication headers and their expiration time.
-  The returned headers will be passed with each HTTP request to the Swarming
-  server (and only Swarming server). The bot will use the returned headers until
-  they are close to expiration (usually 6 min, see AUTH_HEADERS_EXPIRATION_SEC
-  in remote_client.py), and then it'll attempt to refresh them by calling
-  get_authentication_headers again.
-  Can be used to implement per-bot authentication. If no headers are returned,
-  the server will use only IP whitelist for bot authentication.
-  On GCE will use OAuth token of the default GCE service account. It should have
-  "User info" API scope enabled (this can be set when starting an instance). The
-  server should be configured (via bots.cfg) to trust this account (see
-  'require_service_account' in bots.proto).
-  May be called by different threads, but never concurrently.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  Returns:
-    Tuple (dict with headers or None, unix timestamp of when they expire).
-  """
-  if platforms.is_gce():
-    tok = platforms.gce.oauth2_access_token()
-    return {'Authorization': 'Bearer %s' % tok}, time.time() + 5*60
-  return (None, None)
-
-
-### on_* Hooks
-def on_bot_shutdown(bot):
-  """Hook function called when the bot shuts down, usually rebooting.
-  It's a good time to do other kinds of cleanup.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  """
-  pass
-
-
-def on_handshake(bot):
-  """Hook function called when the bot starts, after handshake with the server.
-  Here the bot already knows server enforced dimensions (defined in server side
-  bots.cfg file).
-  This is called right before starting to poll for tasks. It's a good time to
-  do some final initialization or cleanup that may depend on server provided
-  configuration.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  """
-  pass
-
-
-def on_before_task(bot, bot_file):
-  """Hook function called before running a task.
-  It shouldn't do much, since it can't cancel the task so it shouldn't do
-  anything too fancy.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - bot_file: Path to file to write information about the state of the bot.
-              This file can be used to pass certain info about the bot
-              to tasks, such as which connected android devices to run on. See
-              https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md#run_isolated
-  """
-  with open(bot_file, 'wb') as f:
-    json.dump(bot.dimensions, f)
-
-
-def on_after_task(bot, failure, internal_failure, dimensions, summary):
-  """Hook function called after running a task.
-  It is an excellent place to do post-task cleanup of temporary files.
-  The default implementation restarts after a task failure or an internal
-  failure.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - failure: bool, True if the task failed.
-  - internal_failure: bool, True if an internal failure happened.
-  - dimensions: dict, Dimensions requested as part of the task.
-  - summary: dict, Summary of the task execution.
-  """
-  # Example code:
-  #if failure:
-  #  bot.restart('Task failure')
-  #elif internal_failure:
-  #  bot.restart('Internal failure')
-
-
-def on_bot_idle(bot, since_last_action):
-  """Hook function called once when the bot has been idle; when it has no
-  command to execute.
-  This is an excellent place to put device in 'cool down' mode or any
-  "pre-warming" kind of stuff that could take several seconds to do, that would
-  not be appropriate to do in on_after_task(). It could be worth waiting for
-  `since_last_action` to be several seconds before doing a more lengthy
-  operation.
-  This function is called repeatedly until an action is taken (a task, updating,
-  etc).
-  This is a good place to do "auto reboot" for hardware based bots that are
-  rebooted periodically.
-  Arguments:
-  - bot: bot.Bot instance. See ../api/bot.py.
-  - since_last_action: time in second since last action; e.g. amount of time the
-                       bot has been idle.
-  """
-  pass
diff --git a/configs/infra/test/androidtestcenter-test/settings.cfg b/configs/infra/test/androidtestcenter-test/settings.cfg
deleted file mode 100644
index 412349f..0000000
--- a/configs/infra/test/androidtestcenter-test/settings.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-# Instance: androidtestcenter-test (swarming-test)
-# Browse online: https://androidtestcenter-test.appspot.com/restricted/config
-#
-# Schema: SettingsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/config.proto
-
-google_analytics: "UA-107546859-1"
-reusable_task_age_secs: 604800
-bot_death_timeout_secs: 600
-enable_ts_monitoring: true
-ui_client_id: "819908144382-mktl5tlg4cq9jkqfrqi0lat873itcfpi.apps.googleusercontent.com"
-display_server_url_template: "https://androidtestcenter-test.appspot.com/swarming/task/%s"
-isolate {
-  default_server: "https://vtslab-isolate-test.appspot.com"
-  default_namespace: "default-gzip"
-}
-mp {
-  enabled: true
-}
-auth {
-  admins_group: "vtslab-test-swarming-admins"
-  bot_bootstrap_group: "vtslab-test-swarming-bot-bootstrap"
-  privileged_users_group: "vtslab-test-swarming-privileged-users"
-  users_group: "vtslab-test-swarming-users"
-  view_all_bots_group: "vtslab-test-swarming-view-all-bots"
-  view_all_tasks_group: "vtslab-test-swarming-view-all-tasks"
-}
diff --git a/configs/infra/test/vtslab-config-test/acl.cfg b/configs/infra/test/vtslab-config-test/acl.cfg
deleted file mode 100644
index 0da0ca1..0000000
--- a/configs/infra/test/vtslab-config-test/acl.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:acl.cfg
-# *** WARNING ***
-# This file is sensitive. project_access_group specifies a super group
-# that has access to all projects, including internal ones.
-# This file is cached in process memory of instances for 10min
-# because it ~never changes.
-admin_group: "vtslab-config-admins"
-project_access_group: "vtslab-config-project-access"
diff --git a/configs/infra/test/vtslab-config-test/import.cfg b/configs/infra/test/vtslab-config-test/import.cfg
deleted file mode 100644
index 6bc8bdc..0000000
--- a/configs/infra/test/vtslab-config-test/import.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:import.cfg
-gitiles {
-  project_config_default_ref: "refs/heads/infra/config"
-  ref_config_default_path: "infra/config"
-}
diff --git a/configs/infra/test/vtslab-config-test/projects.cfg b/configs/infra/test/vtslab-config-test/projects.cfg
deleted file mode 100644
index b8043de..0000000
--- a/configs/infra/test/vtslab-config-test/projects.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:projects.cfg
-#
-# Please keep the list sorted by project id!
-projects {
-  id: "aosp-master-vts"
-  config_location {
-    url: "https://android.googlesource.com/platform/test/vts/"
-    storage_type: GITILES
-  }
-}
-
-projects {
-  id: "aosp-master-goldfish"
-  config_location {
-    url: "https://android.googlesource.com/device/generic/goldfish/"
-    storage_type: GITILES
-  }
-}
diff --git a/configs/infra/test/vtslab-config-test/schemas.cfg b/configs/infra/test/vtslab-config-test/schemas.cfg
deleted file mode 100644
index 91d34c7..0000000
--- a/configs/infra/test/vtslab-config-test/schemas.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:schemas.cfg
-#
-# Please keep this list sorted by schema name.
-#
-################################################################################
-# WARNING: names and urls in this file will be exposed publicly. Do not put
-# internal stuff here!!!
-################################################################################
-################################################################################
-# ref configs
-schemas {
-  name: "projects/refs:cq.cfg"
-  url: "https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/third_party/cq_client/cq.proto"
-}
-################################################################################
-# project configs
-schemas {
-  name: "projects:buildbucket.cfg"
-  url: "https://chromium.googlesource.com/infra/infra/+/master/appengine/cr-buildbucket/proto/project_config.proto"
-}
-schemas {
-  name: "projects:refs.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-schemas {
-  name: "projects:project.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-################################################################################
-# luci-config service schemas
-schemas {
-  name: "services/luci-config:acl.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:import.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:projects.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:services.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
-  name: "services/luci-config:schemas.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-################################################################################
-# chrome-infra-auth service schemas.
-schemas {
-  name: "services/chrome-infra-auth:delegation.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:imports.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:ip_whitelist.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
-  name: "services/chrome-infra-auth:oauth.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-################################################################################
-# LUCI LogDog service schemas.
-schemas {
-  name: "services/luci-logdog:services.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/config.proto"
-}
-schemas {
-  name: "services/luci-logdog:logdog.cfg"
-  url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/project.proto"
-}
diff --git a/configs/infra/test/vtslab-config-test/services.cfg b/configs/infra/test/vtslab-config-test/services.cfg
deleted file mode 100644
index 3377123..0000000
--- a/configs/infra/test/vtslab-config-test/services.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-# Schema for this file: ServicesCfg message in
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:services.cfg
-#
-# Please keep the list sorted by id.
-#
-# *** WARNING
-# This file is sensitive. These services may receive contents of any config
-# files for validation purposes, including configs of internal projects.
-# ***
-################################################################################
-# Swarming
-services {
-  id: "androidtestcenter-test"
-  owners: "yim@google.com"
-  metadata_url: "https://androidtestcenter-test.appspot.com/_ah/api/config/v1/metadata"
-  access: "androidtestcenter-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Auth
-services {
-  id: "vtslab-auth-test"
-  owners: "yim@google.com"
-  metadata_url: "https://vtslab-auth-test.appspot.com/_ah/api/config/v1/metadata"
-  access: "vtslab-auth-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Commit Queue
-# services {
-#   id: "commit-queue"
-#   owners: "yim@google.com"
-#   metadata_url: "https://vtslab-cq-test.appspot.com/api/metadata"
-# }
-################################################################################
-# GCE Backend
-services {
-  id: "vtslab-backend-test"
-  owners: "yim@google.com"
-  access: "vtslab-backend-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# LUCI / Isolate Server
-services {
-  id: "vtslab-isolate-test"
-  owners: "yim@google.com"
-  metadata_url: "https://vtslab-isolate-test.appspot.com/_ah/api/config/v1/metadata"
-  access: "vtslab-isolate-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Machine Provider
-services {
-  id: "vtslab-machine-test"
-  owners: "yim@google.com"
-  access: "vtslab-machine-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Doc Indexer
-services {
-  id: "vtslab-doc"
-  owners: "yim@google.com"
-}
diff --git a/gae/.gitignore b/gae/.gitignore
deleted file mode 100644
index 9d1699c..0000000
--- a/gae/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-webapp/static/**
diff --git a/gae/app.yaml b/gae/app.yaml
deleted file mode 100644
index 374c07c..0000000
--- a/gae/app.yaml
+++ /dev/null
@@ -1,57 +0,0 @@
-runtime: python27
-api_version: 1
-threadsafe: true
-
-# [START env_vars]
-env_variables:
-  ENDPOINTS_SERVICE_NAME: vtslab-schedule-prod.appspot.com
-  ENDPOINTS_SERVICE_VERSION: 2018-09-03r0
-  SESSION_SECRET_KEY: ''
-# [END env_vars]
-
-# [START builtins]
-builtins:
-# [END builtins]
-
-# [START handlers]
-handlers:
-# The endpoints handler must be mapped to /_ah/api.
-- url: /_ah/api/.*
-  script: webapp.src.endpoint_main.api
-
-- url: /(.*\.(html|js|css|txt|ico))
-  static_files: webapp/static/\1
-  upload: webapp/static/(.*\.(html|js|css|txt|ico))
-
-- url: /((build|device|job|lab|schedule)([?&/].*)?)?
-  static_files: webapp/static/index.html
-  upload: webapp/static/index.html
-
-- url: /.*
-  script: webapp.src.webapp_main.app
-# [END handlers]
-
-# [START libraries]
-libraries:
-- name: webapp2
-  version: latest
-- name: jinja2
-  version: latest
-- name: pycrypto
-  version: 2.6
-- name: ssl
-  version: 2.7.11
-# [END libraries]
-
-# [START exclude]
-skip_files:
-- ^(.*/)?#.*#$
-- ^(.*/)?.*~$
-- ^(.*/)?.*\.py[co]$
-- ^(.*/)?.*/RCS/.*$
-- ^(.*/)?\..*$
-- ^script/*$
-- testrunner.py
-- .*_test.py$
-- ^(.*/)?frontend/(.*)
-# [END exclude]
diff --git a/gae/appengine_config.py b/gae/appengine_config.py
deleted file mode 100644
index 1003e5e..0000000
--- a/gae/appengine_config.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# appengine_config.py
-from google.appengine.ext import vendor
-
-# Add any libraries install in the "lib" folder.
-vendor.add('lib')
diff --git a/gae/buildv1openapi.json b/gae/buildv1openapi.json
deleted file mode 100644
index a59a137..0000000
--- a/gae/buildv1openapi.json
+++ /dev/null
@@ -1,194 +0,0 @@
-{
-  "basePath": "/_ah/api",
-  "consumes": [
-    "application/json"
-  ],
-  "definitions": {
-    "WebappSrcProtoModelBuildInfoMessage": {
-      "properties": {
-        "artifact_type": {
-          "type": "string"
-        },
-        "artifacts": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "build_id": {
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "build_type": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "signed": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelBuildResponseMessage": {
-      "properties": {
-        "builds": {
-          "description": "A message for representing an individual build entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelBuildInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountRequestMessage": {
-      "properties": {
-        "filter": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountResponseMessage": {
-      "properties": {
-        "count": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDefaultResponse": {
-      "properties": {
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelGetRequestMessage": {
-      "properties": {
-        "direction": {
-          "type": "string"
-        },
-        "filter": {
-          "type": "string"
-        },
-        "offset": {
-          "format": "int64",
-          "type": "string"
-        },
-        "size": {
-          "format": "int64",
-          "type": "string"
-        },
-        "sort": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "host": "vtslab-schedule-prod.appspot.com",
-  "info": {
-    "description": "Endpoint API for build_info.",
-    "title": "build",
-    "version": "v1"
-  },
-  "paths": {
-    "/build/v1/count": {
-      "post": {
-        "operationId": "BuildInfoApi_count",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/build/v1/get": {
-      "post": {
-        "operationId": "BuildInfoApi_get",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelBuildResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/build/v1/set": {
-      "post": {
-        "operationId": "BuildInfoApi_set",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelBuildInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    }
-  },
-  "produces": [
-    "application/json"
-  ],
-  "schemes": [
-    "https"
-  ],
-  "securityDefinitions": {
-    "google_id_token": {
-      "authorizationUrl": "",
-      "flow": "implicit",
-      "type": "oauth2",
-      "x-google-issuer": "https://accounts.google.com",
-      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
-    }
-  },
-  "swagger": "2.0",
-  "x-google-api-name": "build"
-}
\ No newline at end of file
diff --git a/gae/cron.yaml b/gae/cron.yaml
deleted file mode 100644
index e4d4a71..0000000
--- a/gae/cron.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-cron:
-- description: "test scheduler job"
-  url: /tasks/schedule
-  schedule: every 5 minutes
-- description: "device_heartbeat"
-  url: /tasks/device_heartbeat
-  schedule: every 1 minutes
-- description: "job_heartbeat"
-  url: /tasks/job_heartbeat
-  schedule: every 1 minutes
-- description: "remove_outdated_devices"
-  url: /tasks/remove_outdated_devices
-  schedule: every 1 hours
diff --git a/gae/favicon.ico b/gae/favicon.ico
deleted file mode 100644
index 42506c0..0000000
--- a/gae/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/gae/frontend/.editorconfig b/gae/frontend/.editorconfig
deleted file mode 100644
index 6e87a00..0000000
--- a/gae/frontend/.editorconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-# Editor configuration, see http://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-max_line_length = off
-trim_trailing_whitespace = false
diff --git a/gae/frontend/.gitignore b/gae/frontend/.gitignore
deleted file mode 100644
index ee5c9d8..0000000
--- a/gae/frontend/.gitignore
+++ /dev/null
@@ -1,39 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-
-# dependencies
-/node_modules
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
diff --git a/gae/frontend/MODULE_LICENSE_MIT b/gae/frontend/MODULE_LICENSE_MIT
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/MODULE_LICENSE_MIT
+++ /dev/null
diff --git a/gae/frontend/NOTICE b/gae/frontend/NOTICE
deleted file mode 100644
index 40040b9..0000000
--- a/gae/frontend/NOTICE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License
-
-Copyright (c) 2014-2018 Google, Inc. http://angular.io
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
diff --git a/gae/frontend/angular.json b/gae/frontend/angular.json
deleted file mode 100644
index ca84a43..0000000
--- a/gae/frontend/angular.json
+++ /dev/null
@@ -1,127 +0,0 @@
-{
-  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
-  "version": 1,
-  "newProjectRoot": "projects",
-  "projects": {
-    "frontend": {
-      "root": "",
-      "sourceRoot": "src",
-      "projectType": "application",
-      "prefix": "app",
-      "schematics": {},
-      "architect": {
-        "build": {
-          "builder": "@angular-devkit/build-angular:browser",
-          "options": {
-            "outputPath": "dist",
-            "index": "src/index.html",
-            "main": "src/main.ts",
-            "polyfills": "src/polyfills.ts",
-            "tsConfig": "src/tsconfig.app.json",
-            "assets": [
-              "src/favicon.ico",
-              "src/assets"
-            ],
-            "styles": [
-              "src/styles.scss"
-            ],
-            "scripts": []
-          },
-          "configurations": {
-            "production": {
-              "fileReplacements": [
-                {
-                  "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.prod.ts"
-                }
-              ],
-              "optimization": true,
-              "outputHashing": "all",
-              "sourceMap": false,
-              "extractCss": true,
-              "namedChunks": false,
-              "aot": true,
-              "extractLicenses": true,
-              "vendorChunk": false,
-              "buildOptimizer": true
-            }
-          }
-        },
-        "serve": {
-          "builder": "@angular-devkit/build-angular:dev-server",
-          "options": {
-            "browserTarget": "frontend:build"
-          },
-          "configurations": {
-            "production": {
-              "browserTarget": "frontend:build:production"
-            }
-          }
-        },
-        "extract-i18n": {
-          "builder": "@angular-devkit/build-angular:extract-i18n",
-          "options": {
-            "browserTarget": "frontend:build"
-          }
-        },
-        "test": {
-          "builder": "@angular-devkit/build-angular:karma",
-          "options": {
-            "main": "src/test.ts",
-            "polyfills": "src/polyfills.ts",
-            "tsConfig": "src/tsconfig.spec.json",
-            "karmaConfig": "src/karma.conf.js",
-            "styles": [
-              "src/styles.scss"
-            ],
-            "scripts": [],
-            "assets": [
-              "src/favicon.ico",
-              "src/assets"
-            ]
-          }
-        },
-        "lint": {
-          "builder": "@angular-devkit/build-angular:tslint",
-          "options": {
-            "tsConfig": [
-              "src/tsconfig.app.json",
-              "src/tsconfig.spec.json"
-            ],
-            "exclude": [
-              "**/node_modules/**"
-            ]
-          }
-        }
-      }
-    },
-    "frontend-e2e": {
-      "root": "e2e/",
-      "projectType": "application",
-      "architect": {
-        "e2e": {
-          "builder": "@angular-devkit/build-angular:protractor",
-          "options": {
-            "protractorConfig": "e2e/protractor.conf.js",
-            "devServerTarget": "frontend:serve"
-          },
-          "configurations": {
-            "production": {
-              "devServerTarget": "frontend:serve:production"
-            }
-          }
-        },
-        "lint": {
-          "builder": "@angular-devkit/build-angular:tslint",
-          "options": {
-            "tsConfig": "e2e/tsconfig.e2e.json",
-            "exclude": [
-              "**/node_modules/**"
-            ]
-          }
-        }
-      }
-    }
-  },
-  "defaultProject": "frontend"
-}
diff --git a/gae/frontend/e2e/protractor.conf.js b/gae/frontend/e2e/protractor.conf.js
deleted file mode 100644
index 86776a3..0000000
--- a/gae/frontend/e2e/protractor.conf.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Protractor configuration file, see link for more information
-// https://github.com/angular/protractor/blob/master/lib/config.ts
-
-const { SpecReporter } = require('jasmine-spec-reporter');
-
-exports.config = {
-  allScriptsTimeout: 11000,
-  specs: [
-    './src/**/*.e2e-spec.ts'
-  ],
-  capabilities: {
-    'browserName': 'chrome'
-  },
-  directConnect: true,
-  baseUrl: 'http://localhost:4200/',
-  framework: 'jasmine',
-  jasmineNodeOpts: {
-    showColors: true,
-    defaultTimeoutInterval: 30000,
-    print: function() {}
-  },
-  onPrepare() {
-    require('ts-node').register({
-      project: require('path').join(__dirname, './tsconfig.e2e.json')
-    });
-    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
-  }
-};
\ No newline at end of file
diff --git a/gae/frontend/e2e/src/app.e2e-spec.ts b/gae/frontend/e2e/src/app.e2e-spec.ts
deleted file mode 100644
index 87525cf..0000000
--- a/gae/frontend/e2e/src/app.e2e-spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { AppPage } from './app.po';
-
-describe('workspace-project App', () => {
-  let page: AppPage;
-
-  beforeEach(() => {
-    page = new AppPage();
-  });
-
-  it('should display welcome message', () => {
-    page.navigateTo();
-    expect(page.getParagraphText()).toEqual('Welcome to frontend!');
-  });
-});
diff --git a/gae/frontend/e2e/src/app.po.ts b/gae/frontend/e2e/src/app.po.ts
deleted file mode 100644
index 82ea75b..0000000
--- a/gae/frontend/e2e/src/app.po.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { browser, by, element } from 'protractor';
-
-export class AppPage {
-  navigateTo() {
-    return browser.get('/');
-  }
-
-  getParagraphText() {
-    return element(by.css('app-root h1')).getText();
-  }
-}
diff --git a/gae/frontend/e2e/tsconfig.e2e.json b/gae/frontend/e2e/tsconfig.e2e.json
deleted file mode 100644
index a6dd622..0000000
--- a/gae/frontend/e2e/tsconfig.e2e.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "extends": "../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "../out-tsc/app",
-    "module": "commonjs",
-    "target": "es5",
-    "types": [
-      "jasmine",
-      "jasminewd2",
-      "node"
-    ]
-  }
-}
\ No newline at end of file
diff --git a/gae/frontend/package-lock.json b/gae/frontend/package-lock.json
deleted file mode 100644
index f697726..0000000
--- a/gae/frontend/package-lock.json
+++ /dev/null
@@ -1,10746 +0,0 @@
-{
-  "name": "frontend",
-  "version": "0.0.0",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "@angular-devkit/architect": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.6.8.tgz",
-      "integrity": "sha512-ZKTm/zC61iY9IBHOEAKoMSzZpvhkmv+1O/HHzpHEuR551jCzu6vSyCmMY9Z7GBcccscCV+hjeSMwgFrFRcqlkw==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/core": "0.6.8",
-        "rxjs": "6.2.1"
-      }
-    },
-    "@angular-devkit/build-angular": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.6.8.tgz",
-      "integrity": "sha512-VGqYAk8jpISraz2UHfsDre270NOUmV0CTSZw2p9sm5g/XIr5m+IHetFZz3gpoAr9+If2aFTs8Rt3sGdCRzwBqA==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/architect": "0.6.8",
-        "@angular-devkit/build-optimizer": "0.6.8",
-        "@angular-devkit/core": "0.6.8",
-        "@ngtools/webpack": "6.0.8",
-        "ajv": "6.4.0",
-        "autoprefixer": "8.6.2",
-        "cache-loader": "1.2.2",
-        "chalk": "2.2.2",
-        "circular-dependency-plugin": "5.0.2",
-        "clean-css": "4.1.11",
-        "copy-webpack-plugin": "4.5.1",
-        "file-loader": "1.1.11",
-        "glob": "7.1.2",
-        "html-webpack-plugin": "3.2.0",
-        "istanbul": "0.4.5",
-        "istanbul-instrumenter-loader": "3.0.1",
-        "karma-source-map-support": "1.3.0",
-        "less": "3.0.4",
-        "less-loader": "4.1.0",
-        "license-webpack-plugin": "1.3.1",
-        "lodash": "4.17.10",
-        "memory-fs": "0.4.1",
-        "mini-css-extract-plugin": "0.4.0",
-        "minimatch": "3.0.4",
-        "node-sass": "4.9.0",
-        "opn": "5.3.0",
-        "parse5": "4.0.0",
-        "portfinder": "1.0.13",
-        "postcss": "6.0.22",
-        "postcss-import": "11.1.0",
-        "postcss-loader": "2.1.5",
-        "postcss-url": "7.3.2",
-        "raw-loader": "0.5.1",
-        "resolve": "1.7.1",
-        "rxjs": "6.2.1",
-        "sass-loader": "7.0.3",
-        "silent-error": "1.1.0",
-        "source-map-support": "0.5.6",
-        "stats-webpack-plugin": "0.6.2",
-        "style-loader": "0.21.0",
-        "stylus": "0.54.5",
-        "stylus-loader": "3.0.2",
-        "tree-kill": "1.2.0",
-        "uglifyjs-webpack-plugin": "1.2.5",
-        "url-loader": "1.0.1",
-        "webpack": "4.8.3",
-        "webpack-dev-middleware": "3.1.3",
-        "webpack-dev-server": "3.1.4",
-        "webpack-merge": "4.1.3",
-        "webpack-sources": "1.1.0",
-        "webpack-subresource-integrity": "1.1.0-rc.4"
-      }
-    },
-    "@angular-devkit/build-optimizer": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.6.8.tgz",
-      "integrity": "sha512-of5syQbv3uNPp4AQkfRecfnp8AE8kvffbfYi+FFPZ6OGr7e59T1fGwk6+Zgb2qQFQg8HO2tzWI/uygtLIqmbmw==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "source-map": "0.5.7",
-        "typescript": "2.9.2",
-        "webpack-sources": "1.1.0"
-      },
-      "dependencies": {
-        "typescript": {
-          "version": "2.9.2",
-          "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
-          "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
-          "dev": true
-        }
-      }
-    },
-    "@angular-devkit/core": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.6.8.tgz",
-      "integrity": "sha512-rkIa1OSVWTt4g9leLSK/PsqOj3HZbDKHbZjqlslyfVa3AyCeiumFoOgViOVXlYgPX3HHDbE5uH24nyUWSD8uww==",
-      "dev": true,
-      "requires": {
-        "ajv": "6.4.0",
-        "chokidar": "2.0.3",
-        "rxjs": "6.2.1",
-        "source-map": "0.5.7"
-      }
-    },
-    "@angular-devkit/schematics": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.6.8.tgz",
-      "integrity": "sha512-R4YqAUdo62wtrhX/5HSRGSKXNTWqfQb66ZE6m8jj6GEJNFKdNXMdxOchxr07LCiKTxfh1w6G3nGzxIsu/+D4KA==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/core": "0.6.8",
-        "rxjs": "6.2.1"
-      }
-    },
-    "@angular/animations": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-6.0.6.tgz",
-      "integrity": "sha512-mJvWn0GuYARJfV9/KNUn5qUc5iNJKMSSNm//pRtUB8n829KnJHLnGpNsr95dzARH5wI3Om/t6hG3M0XCLbIfNQ==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/cdk": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-6.2.1.tgz",
-      "integrity": "sha512-uwW4eIGJKqOkR+ew6YcEAh1J4SP98jdyDpsZ4IEMkV9+jXcKfcwcxGFpZvs9wJsAvAr8EgNmZ8h+iuZLwJsvmA==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/cli": {
-      "version": "6.0.8",
-      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-6.0.8.tgz",
-      "integrity": "sha512-DhH1Zq5Yonthw6zh6W07fhf+9XrAZbD1fcQ0MrmbxlieCfLlTAdBqyK2LavFCKwSZkUMLF6UHM3+jiNRVZSSIg==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/architect": "0.6.8",
-        "@angular-devkit/core": "0.6.8",
-        "@angular-devkit/schematics": "0.6.8",
-        "@schematics/angular": "0.6.8",
-        "@schematics/update": "0.6.8",
-        "opn": "5.3.0",
-        "resolve": "1.7.1",
-        "rxjs": "6.2.1",
-        "semver": "5.5.0",
-        "silent-error": "1.1.0",
-        "symbol-observable": "1.2.0",
-        "yargs-parser": "10.0.0"
-      },
-      "dependencies": {
-        "camelcase": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-          "dev": true
-        },
-        "yargs-parser": {
-          "version": "10.0.0",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.0.0.tgz",
-          "integrity": "sha512-+DHejWujTVYeMHLff8U96rLc4uE4Emncoftvn5AjhB1Jw1pWxLzgBUT/WYbPrHmy6YPEBTZQx5myHhVcuuu64g==",
-          "dev": true,
-          "requires": {
-            "camelcase": "4.1.0"
-          }
-        }
-      }
-    },
-    "@angular/common": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/common/-/common-6.0.6.tgz",
-      "integrity": "sha512-SjCrrGNJSeRMtNLv/ug5HpyRUexdNl11TrWCWMeu3ye3ss4k6EnuM9jGB196B0PIm0IbjO0KrpQ8bqBx0/2vqw==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/compiler": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.0.6.tgz",
-      "integrity": "sha512-lcDNfkYLOWzOOqdD2Kspxwjk3xGs8kVLbq/8uk/aJ96ty8aA9j8Nbf3h53SCY9LuGoJMjOaaUpgwZCszFzqQyA==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/compiler-cli": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-6.0.6.tgz",
-      "integrity": "sha512-vWJK+X6B63+kdAN2s7Az1NHF4gAbECf1fkB+zkO6pP706teW4VlN2xdXeHLXgvK39iDJbhbctTnDfhqIaPmyjw==",
-      "dev": true,
-      "requires": {
-        "chokidar": "1.7.0",
-        "minimist": "1.2.0",
-        "reflect-metadata": "0.1.12",
-        "tsickle": "0.29.0"
-      },
-      "dependencies": {
-        "anymatch": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
-          "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
-          "dev": true,
-          "requires": {
-            "micromatch": "2.3.11",
-            "normalize-path": "2.1.1"
-          }
-        },
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "1.1.0"
-          }
-        },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-          "dev": true
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-          "dev": true,
-          "requires": {
-            "expand-range": "1.8.2",
-            "preserve": "0.2.0",
-            "repeat-element": "1.1.2"
-          }
-        },
-        "chokidar": {
-          "version": "1.7.0",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
-          "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
-          "dev": true,
-          "requires": {
-            "anymatch": "1.3.2",
-            "async-each": "1.0.1",
-            "fsevents": "1.2.4",
-            "glob-parent": "2.0.0",
-            "inherits": "2.0.3",
-            "is-binary-path": "1.0.1",
-            "is-glob": "2.0.1",
-            "path-is-absolute": "1.0.1",
-            "readdirp": "2.1.0"
-          }
-        },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-          "dev": true,
-          "requires": {
-            "is-posix-bracket": "0.1.1"
-          }
-        },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        },
-        "glob-parent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-          "dev": true,
-          "requires": {
-            "is-glob": "2.0.1"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "dev": true,
-          "requires": {
-            "arr-diff": "2.0.0",
-            "array-unique": "0.2.1",
-            "braces": "1.8.5",
-            "expand-brackets": "0.1.5",
-            "extglob": "0.3.2",
-            "filename-regex": "2.0.1",
-            "is-extglob": "1.0.0",
-            "is-glob": "2.0.1",
-            "kind-of": "3.2.2",
-            "normalize-path": "2.1.1",
-            "object.omit": "2.0.1",
-            "parse-glob": "3.0.4",
-            "regex-cache": "0.4.4"
-          }
-        },
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "@angular/core": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/core/-/core-6.0.6.tgz",
-      "integrity": "sha512-7J4wuQ5Bss2GmCptyXSfmgWk/IbCFK/MJwaXOpADLB9iWOkOIvKRSTntb4l6j3OVd9boCbs6Z/xW/HT964iMvw==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/flex-layout": {
-      "version": "6.0.0-beta.16",
-      "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-6.0.0-beta.16.tgz",
-      "integrity": "sha512-0AYtIBGrEJshdFMc6TXGloCkD19YTCRKVJl6xZHX4H5dLnUn+daqXcbh4UsWhayevnLp85HEf2ViHLmTa6jv3g==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/forms": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-6.0.6.tgz",
-      "integrity": "sha512-uVcvUz8JzO/R6HtxIUtefjK55nf4gJt9WjVdnjmA66pQe1+aQYscyQu9QFykGfGqta/0luhVSU7J+5g0rIRr/g==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/http": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/http/-/http-6.0.6.tgz",
-      "integrity": "sha512-ZyY7JS3lQM0HnKfoCJl+S9ZHeQVdG+FefjYE2s7pBKUufaoMo9DTIfQe5ZgSQeXRAFKjuUyJDf1EZlPVVvQzIw==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/language-service": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-6.0.6.tgz",
-      "integrity": "sha512-6zRuKreMPlLQkLGS7KaJ4xehwirPbst+S6tQZltcSHjgIKrZBu3acL7/tUo5G5jQW6OnPXWK9UYs2kCffPS3AQ==",
-      "dev": true
-    },
-    "@angular/material": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/@angular/material/-/material-6.2.1.tgz",
-      "integrity": "sha512-SBoUXxHknkgwzp5pNDHW0jyrTM0d0Tk4lVyDbtEX8VEPtXqG5nL3BSgyjpJbTvqlmy2kOooUu3qgAmt87VH9lw==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/platform-browser": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-6.0.6.tgz",
-      "integrity": "sha512-c+2c4Ba8IeIt9CnF1RmJVf/0xwljT9GSIJUC61SLrX01NMwRxDq/LC+tatcBGLzZ6rc1eYmsd1exTHOGfENOxw==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/platform-browser-dynamic": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.0.6.tgz",
-      "integrity": "sha512-t5+dvfcwVaDa5H8qsVnPAvmNJa0rDwJMu1T6kfz8sAxzgiw6tOvIQShJX0Ka94+nPpd4mg7gv43VV705z6ryMA==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@angular/router": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/@angular/router/-/router-6.0.6.tgz",
-      "integrity": "sha512-R49Gh/ate//AloPGjtQ2Nl3HNMT21pumcUoWZEZtYw8UyTbxSKLMc40yzdsldGrKZ/G/CafFTaS1hpZD7MF5/w==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "@ngtools/webpack": {
-      "version": "6.0.8",
-      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-6.0.8.tgz",
-      "integrity": "sha512-jorGpTd82ILbyUwg4JQekovHFaYwSMlZan4f7x+sd3+2WgyL3Z1+ZbVSGKvXZWKS/mAVx7eLkRikzJkuC4FgHw==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/core": "0.6.8",
-        "tree-kill": "1.2.0",
-        "webpack-sources": "1.1.0"
-      }
-    },
-    "@schematics/angular": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.6.8.tgz",
-      "integrity": "sha512-9kRphqTYG5Df/I8fvnT1zMsw0YNDPO9tl18tQZXj4am4raT7l9UCr+WkwJdlBoA5pwG6baWE9sL0iGWV/bzF/g==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/core": "0.6.8",
-        "@angular-devkit/schematics": "0.6.8",
-        "typescript": "2.7.2"
-      }
-    },
-    "@schematics/update": {
-      "version": "0.6.8",
-      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.6.8.tgz",
-      "integrity": "sha512-1Uq7LYnwL2wBwGVCgNz76QAR13ghAk+2vDDHOi+VX5+usHManxydrpoMGeX66OBPd+y5D3D2MFb+8mYHE7mygg==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/core": "0.6.8",
-        "@angular-devkit/schematics": "0.6.8",
-        "npm-registry-client": "8.5.1",
-        "rxjs": "6.2.1",
-        "semver": "5.5.0",
-        "semver-intersect": "1.3.1"
-      }
-    },
-    "@types/jasmine": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.8.tgz",
-      "integrity": "sha512-OJSUxLaxXsjjhob2DBzqzgrkLmukM3+JMpRp0r0E4HTdT1nwDCWhaswjYxazPij6uOdzHCJfNbDjmQ1/rnNbCg==",
-      "dev": true
-    },
-    "@types/jasminewd2": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.3.tgz",
-      "integrity": "sha512-hYDVmQZT5VA2kigd4H4bv7vl/OhlympwREUemqBdOqtrYTo5Ytm12a5W5/nGgGYdanGVxj0x/VhZ7J3hOg/YKg==",
-      "dev": true,
-      "requires": {
-        "@types/jasmine": "2.8.8"
-      }
-    },
-    "@types/node": {
-      "version": "8.9.5",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz",
-      "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==",
-      "dev": true
-    },
-    "@types/q": {
-      "version": "0.0.32",
-      "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
-      "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
-      "dev": true
-    },
-    "@types/selenium-webdriver": {
-      "version": "2.53.43",
-      "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz",
-      "integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==",
-      "dev": true
-    },
-    "@webassemblyjs/ast": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.4.3.tgz",
-      "integrity": "sha512-S6npYhPcTHDYe9nlsKa9CyWByFi8Vj8HovcAgtmMAQZUOczOZbQ8CnwMYKYC5HEZzxEE+oY0jfQk4cVlI3J59Q==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
-        "@webassemblyjs/wast-parser": "1.4.3",
-        "debug": "3.1.0",
-        "webassemblyjs": "1.4.3"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "@webassemblyjs/floating-point-hex-parser": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.4.3.tgz",
-      "integrity": "sha512-3zTkSFswwZOPNHnzkP9ONq4bjJSeKVMcuahGXubrlLmZP8fmTIJ58dW7h/zOVWiFSuG2em3/HH3BlCN7wyu9Rw==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-buffer": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.4.3.tgz",
-      "integrity": "sha512-e8+KZHh+RV8MUvoSRtuT1sFXskFnWG9vbDy47Oa166xX+l0dD5sERJ21g5/tcH8Yo95e9IN3u7Jc3NbhnUcSkw==",
-      "dev": true,
-      "requires": {
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "@webassemblyjs/helper-code-frame": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.4.3.tgz",
-      "integrity": "sha512-9FgHEtNsZQYaKrGCtsjswBil48Qp1agrzRcPzCbQloCoaTbOXLJ9IRmqT+uEZbenpULLRNFugz3I4uw18hJM8w==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/wast-printer": "1.4.3"
-      }
-    },
-    "@webassemblyjs/helper-fsm": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.4.3.tgz",
-      "integrity": "sha512-JINY76U+702IRf7ePukOt037RwmtH59JHvcdWbTTyHi18ixmQ+uOuNhcdCcQHTquDAH35/QgFlp3Y9KqtyJsCQ==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-wasm-bytecode": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.4.3.tgz",
-      "integrity": "sha512-I7bS+HaO0K07Io89qhJv+z1QipTpuramGwUSDkwEaficbSvCcL92CUZEtgykfNtk5wb0CoLQwWlmXTwGbNZUeQ==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-wasm-section": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.4.3.tgz",
-      "integrity": "sha512-p0yeeO/h2r30PyjnJX9xXSR6EDcvJd/jC6xa/Pxg4lpfcNi7JUswOpqDToZQ55HMMVhXDih/yqkaywHWGLxqyQ==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/helper-buffer": "1.4.3",
-        "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
-        "@webassemblyjs/wasm-gen": "1.4.3",
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "@webassemblyjs/leb128": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.4.3.tgz",
-      "integrity": "sha512-4u0LJLSPzuRDWHwdqsrThYn+WqMFVqbI2ltNrHvZZkzFPO8XOZ0HFQ5eVc4jY/TNHgXcnwrHjONhPGYuuf//KQ==",
-      "dev": true,
-      "requires": {
-        "leb": "0.3.0"
-      }
-    },
-    "@webassemblyjs/validation": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/validation/-/validation-1.4.3.tgz",
-      "integrity": "sha512-R+rRMKfhd9mq0rj2mhU9A9NKI2l/Rw65vIYzz4lui7eTKPcCu1l7iZNi4b9Gen8D42Sqh/KGiaQNk/x5Tn/iBQ==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3"
-      }
-    },
-    "@webassemblyjs/wasm-edit": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.4.3.tgz",
-      "integrity": "sha512-qzuwUn771PV6/LilqkXcS0ozJYAeY/OKbXIWU3a8gexuqb6De2p4ya/baBeH5JQ2WJdfhWhSvSbu86Vienttpw==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/helper-buffer": "1.4.3",
-        "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
-        "@webassemblyjs/helper-wasm-section": "1.4.3",
-        "@webassemblyjs/wasm-gen": "1.4.3",
-        "@webassemblyjs/wasm-opt": "1.4.3",
-        "@webassemblyjs/wasm-parser": "1.4.3",
-        "@webassemblyjs/wast-printer": "1.4.3",
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "@webassemblyjs/wasm-gen": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.4.3.tgz",
-      "integrity": "sha512-eR394T8dHZfpLJ7U/Z5pFSvxl1L63JdREebpv9gYc55zLhzzdJPAuxjBYT4XqevUdW67qU2s0nNA3kBuNJHbaQ==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
-        "@webassemblyjs/leb128": "1.4.3"
-      }
-    },
-    "@webassemblyjs/wasm-opt": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.4.3.tgz",
-      "integrity": "sha512-7Gp+nschuKiDuAL1xmp4Xz0rgEbxioFXw4nCFYEmy+ytynhBnTeGc9W9cB1XRu1w8pqRU2lbj2VBBA4cL5Z2Kw==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/helper-buffer": "1.4.3",
-        "@webassemblyjs/wasm-gen": "1.4.3",
-        "@webassemblyjs/wasm-parser": "1.4.3",
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "@webassemblyjs/wasm-parser": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.4.3.tgz",
-      "integrity": "sha512-KXBjtlwA3BVukR/yWHC9GF+SCzBcgj0a7lm92kTOaa4cbjaTaa47bCjXw6cX4SGQpkncB9PU2hHGYVyyI7wFRg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
-        "@webassemblyjs/leb128": "1.4.3",
-        "@webassemblyjs/wasm-parser": "1.4.3",
-        "webassemblyjs": "1.4.3"
-      }
-    },
-    "@webassemblyjs/wast-parser": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.4.3.tgz",
-      "integrity": "sha512-QhCsQzqV0CpsEkRYyTzQDilCNUZ+5j92f+g35bHHNqS22FppNTywNFfHPq8ZWZfYCgbectc+PoghD+xfzVFh1Q==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/floating-point-hex-parser": "1.4.3",
-        "@webassemblyjs/helper-code-frame": "1.4.3",
-        "@webassemblyjs/helper-fsm": "1.4.3",
-        "long": "3.2.0",
-        "webassemblyjs": "1.4.3"
-      }
-    },
-    "@webassemblyjs/wast-printer": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.4.3.tgz",
-      "integrity": "sha512-EgXk4anf8jKmuZJsqD8qy5bz2frEQhBvZruv+bqwNoLWUItjNSFygk8ywL3JTEz9KtxTlAmqTXNrdD1d9gNDtg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/wast-parser": "1.4.3",
-        "long": "3.2.0"
-      }
-    },
-    "abbrev": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
-      "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
-      "dev": true
-    },
-    "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
-      "dev": true,
-      "requires": {
-        "mime-types": "2.1.18",
-        "negotiator": "0.6.1"
-      }
-    },
-    "acorn": {
-      "version": "5.6.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz",
-      "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==",
-      "dev": true
-    },
-    "acorn-dynamic-import": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
-      "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
-      "dev": true,
-      "requires": {
-        "acorn": "5.6.2"
-      }
-    },
-    "adm-zip": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz",
-      "integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=",
-      "dev": true
-    },
-    "after": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
-      "dev": true
-    },
-    "agent-base": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
-      "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
-      "dev": true,
-      "requires": {
-        "es6-promisify": "5.0.0"
-      }
-    },
-    "ajv": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz",
-      "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=",
-      "dev": true,
-      "requires": {
-        "fast-deep-equal": "1.1.0",
-        "fast-json-stable-stringify": "2.0.0",
-        "json-schema-traverse": "0.3.1",
-        "uri-js": "3.0.2"
-      }
-    },
-    "ajv-keywords": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
-      "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
-      "dev": true
-    },
-    "align-text": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2",
-        "longest": "1.0.1",
-        "repeat-string": "1.6.1"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "amdefine": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
-      "dev": true
-    },
-    "ansi-html": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
-      "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
-      "dev": true
-    },
-    "ansi-regex": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-      "dev": true
-    },
-    "ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "requires": {
-        "color-convert": "1.9.2"
-      }
-    },
-    "anymatch": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
-      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
-      "dev": true,
-      "requires": {
-        "micromatch": "3.1.10",
-        "normalize-path": "2.1.1"
-      }
-    },
-    "app-root-path": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz",
-      "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=",
-      "dev": true
-    },
-    "append-transform": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
-      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
-      "dev": true,
-      "requires": {
-        "default-require-extensions": "2.0.0"
-      }
-    },
-    "aproba": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-      "dev": true
-    },
-    "are-we-there-yet": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
-      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
-      "dev": true,
-      "requires": {
-        "delegates": "1.0.0",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "requires": {
-        "sprintf-js": "1.0.3"
-      }
-    },
-    "arr-diff": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-      "dev": true
-    },
-    "arr-flatten": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
-      "dev": true
-    },
-    "arr-union": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
-      "dev": true
-    },
-    "array-find-index": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
-      "dev": true
-    },
-    "array-flatten": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
-      "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
-      "dev": true
-    },
-    "array-includes": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
-      "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2",
-        "es-abstract": "1.12.0"
-      }
-    },
-    "array-slice": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
-      "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
-      "dev": true
-    },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "1.0.3"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
-    "array-unique": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-      "dev": true
-    },
-    "arraybuffer.slice": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
-      "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=",
-      "dev": true
-    },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
-    },
-    "asap": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
-      "dev": true,
-      "optional": true
-    },
-    "asn1": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
-      "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
-      "dev": true
-    },
-    "asn1.js": {
-      "version": "4.10.1",
-      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
-      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "inherits": "2.0.3",
-        "minimalistic-assert": "1.0.1"
-      }
-    },
-    "assert": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
-      "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
-      "dev": true,
-      "requires": {
-        "util": "0.10.3"
-      },
-      "dependencies": {
-        "inherits": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
-          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
-          "dev": true
-        },
-        "util": {
-          "version": "0.10.3",
-          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
-          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
-          "dev": true,
-          "requires": {
-            "inherits": "2.0.1"
-          }
-        }
-      }
-    },
-    "assert-plus": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-      "dev": true
-    },
-    "assign-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
-      "dev": true
-    },
-    "async": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-      "dev": true
-    },
-    "async-each": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
-      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
-      "dev": true
-    },
-    "async-foreach": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
-      "dev": true,
-      "optional": true
-    },
-    "asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-      "dev": true
-    },
-    "atob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
-      "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
-      "dev": true
-    },
-    "autoprefixer": {
-      "version": "8.6.2",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.2.tgz",
-      "integrity": "sha512-cv9v1mYYBcAnZq4MHseJ9AIdjQmNahnpCpPO46oTkQJS2GggsBp2azHjNpAuQ95Epvsg+AIsyjYhfI9YwFxGSA==",
-      "dev": true,
-      "requires": {
-        "browserslist": "3.2.8",
-        "caniuse-lite": "1.0.30000855",
-        "normalize-range": "0.1.2",
-        "num2fraction": "1.2.2",
-        "postcss": "6.0.22",
-        "postcss-value-parser": "3.3.0"
-      }
-    },
-    "aws-sign2": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-      "dev": true
-    },
-    "aws4": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
-      "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==",
-      "dev": true
-    },
-    "babel-code-frame": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-      "dev": true,
-      "requires": {
-        "chalk": "1.1.3",
-        "esutils": "2.0.2",
-        "js-tokens": "3.0.2"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true
-        }
-      }
-    },
-    "babel-generator": {
-      "version": "6.26.1",
-      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
-      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
-      "dev": true,
-      "requires": {
-        "babel-messages": "6.23.0",
-        "babel-runtime": "6.26.0",
-        "babel-types": "6.26.0",
-        "detect-indent": "4.0.0",
-        "jsesc": "1.3.0",
-        "lodash": "4.17.10",
-        "source-map": "0.5.7",
-        "trim-right": "1.0.1"
-      }
-    },
-    "babel-messages": {
-      "version": "6.23.0",
-      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
-      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0"
-      }
-    },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "dev": true,
-      "requires": {
-        "core-js": "2.5.7",
-        "regenerator-runtime": "0.11.1"
-      }
-    },
-    "babel-template": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
-      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0",
-        "babel-traverse": "6.26.0",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0",
-        "lodash": "4.17.10"
-      }
-    },
-    "babel-traverse": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
-      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
-      "dev": true,
-      "requires": {
-        "babel-code-frame": "6.26.0",
-        "babel-messages": "6.23.0",
-        "babel-runtime": "6.26.0",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0",
-        "debug": "2.6.9",
-        "globals": "9.18.0",
-        "invariant": "2.2.4",
-        "lodash": "4.17.10"
-      }
-    },
-    "babel-types": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0",
-        "esutils": "2.0.2",
-        "lodash": "4.17.10",
-        "to-fast-properties": "1.0.3"
-      }
-    },
-    "babylon": {
-      "version": "6.18.0",
-      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
-      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
-      "dev": true
-    },
-    "backo2": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
-      "dev": true
-    },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-      "dev": true
-    },
-    "base": {
-      "version": "0.11.2",
-      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
-      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
-      "dev": true,
-      "requires": {
-        "cache-base": "1.0.1",
-        "class-utils": "0.3.6",
-        "component-emitter": "1.2.1",
-        "define-property": "1.0.0",
-        "isobject": "3.0.1",
-        "mixin-deep": "1.3.1",
-        "pascalcase": "0.1.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "1.0.2"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "1.0.0",
-            "is-data-descriptor": "1.0.0",
-            "kind-of": "6.0.2"
-          }
-        }
-      }
-    },
-    "base64-arraybuffer": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
-      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
-      "dev": true
-    },
-    "base64-js": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
-      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
-      "dev": true
-    },
-    "base64id": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
-      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
-      "dev": true
-    },
-    "batch": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-      "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
-      "dev": true
-    },
-    "bcrypt-pbkdf": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
-      "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "tweetnacl": "0.14.5"
-      }
-    },
-    "better-assert": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
-      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
-      "dev": true,
-      "requires": {
-        "callsite": "1.0.0"
-      }
-    },
-    "big.js": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
-      "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
-      "dev": true
-    },
-    "binary-extensions": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
-      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
-      "dev": true
-    },
-    "blob": {
-      "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
-      "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
-      "dev": true
-    },
-    "block-stream": {
-      "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "inherits": "2.0.3"
-      }
-    },
-    "blocking-proxy": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
-      "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
-      "dev": true,
-      "requires": {
-        "minimist": "1.2.0"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "bluebird": {
-      "version": "3.5.1",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
-      "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
-      "dev": true
-    },
-    "bn.js": {
-      "version": "4.11.8",
-      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
-      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
-      "dev": true
-    },
-    "body-parser": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
-      "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
-      "dev": true,
-      "requires": {
-        "bytes": "3.0.0",
-        "content-type": "1.0.4",
-        "debug": "2.6.9",
-        "depd": "1.1.2",
-        "http-errors": "1.6.3",
-        "iconv-lite": "0.4.19",
-        "on-finished": "2.3.0",
-        "qs": "6.5.1",
-        "raw-body": "2.3.2",
-        "type-is": "1.6.16"
-      },
-      "dependencies": {
-        "qs": {
-          "version": "6.5.1",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
-          "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
-          "dev": true
-        }
-      }
-    },
-    "bonjour": {
-      "version": "3.5.0",
-      "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
-      "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
-      "dev": true,
-      "requires": {
-        "array-flatten": "2.1.1",
-        "deep-equal": "1.0.1",
-        "dns-equal": "1.0.0",
-        "dns-txt": "2.0.2",
-        "multicast-dns": "6.2.3",
-        "multicast-dns-service-types": "1.1.0"
-      }
-    },
-    "boolbase": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
-      "dev": true
-    },
-    "boom": {
-      "version": "2.10.1",
-      "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
-      "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
-      "dev": true,
-      "requires": {
-        "hoek": "2.16.3"
-      }
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
-      "requires": {
-        "balanced-match": "1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "braces": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-      "dev": true,
-      "requires": {
-        "arr-flatten": "1.1.0",
-        "array-unique": "0.3.2",
-        "extend-shallow": "2.0.1",
-        "fill-range": "4.0.0",
-        "isobject": "3.0.1",
-        "repeat-element": "1.1.2",
-        "snapdragon": "0.8.2",
-        "snapdragon-node": "2.1.1",
-        "split-string": "3.1.0",
-        "to-regex": "3.0.2"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        }
-      }
-    },
-    "brorand": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
-      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
-      "dev": true
-    },
-    "browserify-aes": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
-      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
-      "dev": true,
-      "requires": {
-        "buffer-xor": "1.0.3",
-        "cipher-base": "1.0.4",
-        "create-hash": "1.2.0",
-        "evp_bytestokey": "1.0.3",
-        "inherits": "2.0.3",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "browserify-cipher": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
-      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
-      "dev": true,
-      "requires": {
-        "browserify-aes": "1.2.0",
-        "browserify-des": "1.0.1",
-        "evp_bytestokey": "1.0.3"
-      }
-    },
-    "browserify-des": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz",
-      "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==",
-      "dev": true,
-      "requires": {
-        "cipher-base": "1.0.4",
-        "des.js": "1.0.0",
-        "inherits": "2.0.3"
-      }
-    },
-    "browserify-rsa": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
-      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "randombytes": "2.0.6"
-      }
-    },
-    "browserify-sign": {
-      "version": "4.0.4",
-      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
-      "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "browserify-rsa": "4.0.1",
-        "create-hash": "1.2.0",
-        "create-hmac": "1.1.7",
-        "elliptic": "6.4.0",
-        "inherits": "2.0.3",
-        "parse-asn1": "5.1.1"
-      }
-    },
-    "browserify-zlib": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
-      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
-      "dev": true,
-      "requires": {
-        "pako": "1.0.6"
-      }
-    },
-    "browserslist": {
-      "version": "3.2.8",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
-      "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
-      "dev": true,
-      "requires": {
-        "caniuse-lite": "1.0.30000855",
-        "electron-to-chromium": "1.3.48"
-      }
-    },
-    "buffer": {
-      "version": "4.9.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
-      "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
-      "dev": true,
-      "requires": {
-        "base64-js": "1.3.0",
-        "ieee754": "1.1.12",
-        "isarray": "1.0.0"
-      }
-    },
-    "buffer-from": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
-      "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==",
-      "dev": true
-    },
-    "buffer-indexof": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
-      "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
-      "dev": true
-    },
-    "buffer-xor": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
-      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
-      "dev": true
-    },
-    "builtin-modules": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-      "dev": true
-    },
-    "builtin-status-codes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
-      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
-      "dev": true
-    },
-    "builtins": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
-      "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
-      "dev": true
-    },
-    "bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
-      "dev": true
-    },
-    "cacache": {
-      "version": "10.0.4",
-      "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
-      "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
-      "dev": true,
-      "requires": {
-        "bluebird": "3.5.1",
-        "chownr": "1.0.1",
-        "glob": "7.1.2",
-        "graceful-fs": "4.1.11",
-        "lru-cache": "4.1.3",
-        "mississippi": "2.0.0",
-        "mkdirp": "0.5.1",
-        "move-concurrently": "1.0.1",
-        "promise-inflight": "1.0.1",
-        "rimraf": "2.6.2",
-        "ssri": "5.3.0",
-        "unique-filename": "1.1.0",
-        "y18n": "4.0.0"
-      }
-    },
-    "cache-base": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
-      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
-      "dev": true,
-      "requires": {
-        "collection-visit": "1.0.0",
-        "component-emitter": "1.2.1",
-        "get-value": "2.0.6",
-        "has-value": "1.0.0",
-        "isobject": "3.0.1",
-        "set-value": "2.0.0",
-        "to-object-path": "0.3.0",
-        "union-value": "1.0.0",
-        "unset-value": "1.0.0"
-      }
-    },
-    "cache-loader": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.2.tgz",
-      "integrity": "sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "mkdirp": "0.5.1",
-        "neo-async": "2.5.1",
-        "schema-utils": "0.4.5"
-      }
-    },
-    "callsite": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
-      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
-      "dev": true
-    },
-    "camel-case": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
-      "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
-      "dev": true,
-      "requires": {
-        "no-case": "2.3.2",
-        "upper-case": "1.1.3"
-      }
-    },
-    "camelcase": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-      "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
-      "dev": true,
-      "optional": true
-    },
-    "camelcase-keys": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
-      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
-      "dev": true,
-      "requires": {
-        "camelcase": "2.1.1",
-        "map-obj": "1.0.1"
-      },
-      "dependencies": {
-        "camelcase": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
-          "dev": true
-        }
-      }
-    },
-    "caniuse-lite": {
-      "version": "1.0.30000855",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000855.tgz",
-      "integrity": "sha512-ajORrkXa5UYk62P5PK6ZmBraYOAOr9HWy+XxLwjDg8Ys/5KiSyarg8tIA32ZVqbFhtz67wyySXnU9imkh2ZT2w==",
-      "dev": true
-    },
-    "caseless": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
-      "dev": true
-    },
-    "center-align": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "align-text": "0.1.4",
-        "lazy-cache": "1.0.4"
-      }
-    },
-    "chalk": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz",
-      "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==",
-      "dev": true,
-      "requires": {
-        "ansi-styles": "3.2.1",
-        "escape-string-regexp": "1.0.5",
-        "supports-color": "4.5.0"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "4.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
-          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
-          "dev": true,
-          "requires": {
-            "has-flag": "2.0.0"
-          }
-        }
-      }
-    },
-    "chokidar": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
-      "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==",
-      "dev": true,
-      "requires": {
-        "anymatch": "2.0.0",
-        "async-each": "1.0.1",
-        "braces": "2.3.2",
-        "fsevents": "1.2.4",
-        "glob-parent": "3.1.0",
-        "inherits": "2.0.3",
-        "is-binary-path": "1.0.1",
-        "is-glob": "4.0.0",
-        "normalize-path": "2.1.1",
-        "path-is-absolute": "1.0.1",
-        "readdirp": "2.1.0",
-        "upath": "1.1.0"
-      }
-    },
-    "chownr": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
-      "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
-      "dev": true
-    },
-    "chrome-trace-event": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-0.1.3.tgz",
-      "integrity": "sha512-sjndyZHrrWiu4RY7AkHgjn80GfAM2ZSzUkZLV/Js59Ldmh6JDThf0SUmOHU53rFu2rVxxfCzJ30Ukcfch3Gb/A==",
-      "dev": true
-    },
-    "cipher-base": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
-      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "circular-dependency-plugin": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz",
-      "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==",
-      "dev": true
-    },
-    "class-utils": {
-      "version": "0.3.6",
-      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
-      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
-      "dev": true,
-      "requires": {
-        "arr-union": "3.1.0",
-        "define-property": "0.2.5",
-        "isobject": "3.0.1",
-        "static-extend": "0.1.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        }
-      }
-    },
-    "clean-css": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz",
-      "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=",
-      "dev": true,
-      "requires": {
-        "source-map": "0.5.7"
-      }
-    },
-    "cliui": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-      "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "center-align": "0.1.3",
-        "right-align": "0.1.3",
-        "wordwrap": "0.0.2"
-      },
-      "dependencies": {
-        "wordwrap": {
-          "version": "0.0.2",
-          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
-          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "clone": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
-      "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
-      "dev": true
-    },
-    "clone-deep": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
-      "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
-      "dev": true,
-      "requires": {
-        "for-own": "1.0.0",
-        "is-plain-object": "2.0.4",
-        "kind-of": "6.0.2",
-        "shallow-clone": "1.0.0"
-      }
-    },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-      "dev": true
-    },
-    "code-point-at": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
-      "dev": true
-    },
-    "codelyzer": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.2.1.tgz",
-      "integrity": "sha512-CKwfgpfkqi9dyzy4s6ELaxJ54QgJ6A8iTSsM4bzHbLuTpbKncvNc3DUlCvpnkHBhK47gEf4qFsWoYqLrJPhy6g==",
-      "dev": true,
-      "requires": {
-        "app-root-path": "2.0.1",
-        "css-selector-tokenizer": "0.7.0",
-        "cssauron": "1.4.0",
-        "semver-dsl": "1.0.1",
-        "source-map": "0.5.7",
-        "sprintf-js": "1.0.3"
-      }
-    },
-    "collection-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
-      "dev": true,
-      "requires": {
-        "map-visit": "1.0.0",
-        "object-visit": "1.0.1"
-      }
-    },
-    "color-convert": {
-      "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
-      "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
-      "dev": true,
-      "requires": {
-        "color-name": "1.1.1"
-      }
-    },
-    "color-name": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
-      "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
-      "dev": true
-    },
-    "colors": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
-      "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
-      "dev": true
-    },
-    "combine-lists": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz",
-      "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=",
-      "dev": true,
-      "requires": {
-        "lodash": "4.17.10"
-      }
-    },
-    "combined-stream": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
-      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
-      "dev": true,
-      "requires": {
-        "delayed-stream": "1.0.0"
-      }
-    },
-    "commander": {
-      "version": "2.15.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
-      "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
-      "dev": true
-    },
-    "commondir": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
-      "dev": true
-    },
-    "compare-versions": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz",
-      "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==",
-      "dev": true
-    },
-    "component-bind": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
-      "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
-      "dev": true
-    },
-    "component-emitter": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
-      "dev": true
-    },
-    "component-inherit": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
-      "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
-      "dev": true
-    },
-    "compressible": {
-      "version": "2.0.14",
-      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz",
-      "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=",
-      "dev": true,
-      "requires": {
-        "mime-db": "1.34.0"
-      },
-      "dependencies": {
-        "mime-db": {
-          "version": "1.34.0",
-          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.34.0.tgz",
-          "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=",
-          "dev": true
-        }
-      }
-    },
-    "compression": {
-      "version": "1.7.2",
-      "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz",
-      "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=",
-      "dev": true,
-      "requires": {
-        "accepts": "1.3.5",
-        "bytes": "3.0.0",
-        "compressible": "2.0.14",
-        "debug": "2.6.9",
-        "on-headers": "1.0.1",
-        "safe-buffer": "5.1.1",
-        "vary": "1.1.2"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
-          "dev": true
-        }
-      }
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "dev": true
-    },
-    "concat-stream": {
-      "version": "1.6.2",
-      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
-      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
-      "dev": true,
-      "requires": {
-        "buffer-from": "1.1.0",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6",
-        "typedarray": "0.0.6"
-      }
-    },
-    "connect": {
-      "version": "3.6.6",
-      "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
-      "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "finalhandler": "1.1.0",
-        "parseurl": "1.3.2",
-        "utils-merge": "1.0.1"
-      },
-      "dependencies": {
-        "finalhandler": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
-          "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
-          "dev": true,
-          "requires": {
-            "debug": "2.6.9",
-            "encodeurl": "1.0.2",
-            "escape-html": "1.0.3",
-            "on-finished": "2.3.0",
-            "parseurl": "1.3.2",
-            "statuses": "1.3.1",
-            "unpipe": "1.0.0"
-          }
-        },
-        "statuses": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
-          "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
-          "dev": true
-        }
-      }
-    },
-    "connect-history-api-fallback": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
-      "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
-      "dev": true
-    },
-    "console-browserify": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
-      "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
-      "dev": true,
-      "requires": {
-        "date-now": "0.1.4"
-      }
-    },
-    "console-control-strings": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
-      "dev": true
-    },
-    "constants-browserify": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
-      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
-      "dev": true
-    },
-    "content-disposition": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
-      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
-      "dev": true
-    },
-    "content-type": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
-      "dev": true
-    },
-    "convert-source-map": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
-      "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
-      "dev": true
-    },
-    "cookie": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
-      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
-      "dev": true
-    },
-    "cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
-      "dev": true
-    },
-    "copy-concurrently": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
-      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
-      "dev": true,
-      "requires": {
-        "aproba": "1.2.0",
-        "fs-write-stream-atomic": "1.0.10",
-        "iferr": "0.1.5",
-        "mkdirp": "0.5.1",
-        "rimraf": "2.6.2",
-        "run-queue": "1.0.3"
-      }
-    },
-    "copy-descriptor": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
-      "dev": true
-    },
-    "copy-webpack-plugin": {
-      "version": "4.5.1",
-      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.1.tgz",
-      "integrity": "sha512-OlTo6DYg0XfTKOF8eLf79wcHm4Ut10xU2cRBRPMW/NA5F9VMjZGTfRHWDIYC3s+1kObGYrBLshXWU1K0hILkNQ==",
-      "dev": true,
-      "requires": {
-        "cacache": "10.0.4",
-        "find-cache-dir": "1.0.0",
-        "globby": "7.1.1",
-        "is-glob": "4.0.0",
-        "loader-utils": "1.1.0",
-        "minimatch": "3.0.4",
-        "p-limit": "1.3.0",
-        "serialize-javascript": "1.5.0"
-      }
-    },
-    "core-js": {
-      "version": "2.5.7",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
-      "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
-    },
-    "core-util-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
-    },
-    "cosmiconfig": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz",
-      "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==",
-      "dev": true,
-      "requires": {
-        "is-directory": "0.3.1",
-        "js-yaml": "3.12.0",
-        "minimist": "1.2.0",
-        "object-assign": "4.1.1",
-        "os-homedir": "1.0.2",
-        "parse-json": "2.2.0",
-        "require-from-string": "1.2.1"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "create-ecdh": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
-      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "elliptic": "6.4.0"
-      }
-    },
-    "create-hash": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
-      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
-      "dev": true,
-      "requires": {
-        "cipher-base": "1.0.4",
-        "inherits": "2.0.3",
-        "md5.js": "1.3.4",
-        "ripemd160": "2.0.2",
-        "sha.js": "2.4.11"
-      }
-    },
-    "create-hmac": {
-      "version": "1.1.7",
-      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
-      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
-      "dev": true,
-      "requires": {
-        "cipher-base": "1.0.4",
-        "create-hash": "1.2.0",
-        "inherits": "2.0.3",
-        "ripemd160": "2.0.2",
-        "safe-buffer": "5.1.2",
-        "sha.js": "2.4.11"
-      }
-    },
-    "cross-spawn": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
-      "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "lru-cache": "4.1.3",
-        "which": "1.3.1"
-      }
-    },
-    "cryptiles": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
-      "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
-      "dev": true,
-      "requires": {
-        "boom": "2.10.1"
-      }
-    },
-    "crypto-browserify": {
-      "version": "3.12.0",
-      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
-      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
-      "dev": true,
-      "requires": {
-        "browserify-cipher": "1.0.1",
-        "browserify-sign": "4.0.4",
-        "create-ecdh": "4.0.3",
-        "create-hash": "1.2.0",
-        "create-hmac": "1.1.7",
-        "diffie-hellman": "5.0.3",
-        "inherits": "2.0.3",
-        "pbkdf2": "3.0.16",
-        "public-encrypt": "4.0.2",
-        "randombytes": "2.0.6",
-        "randomfill": "1.0.4"
-      }
-    },
-    "css-parse": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
-      "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
-      "dev": true
-    },
-    "css-select": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
-      "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
-      "dev": true,
-      "requires": {
-        "boolbase": "1.0.0",
-        "css-what": "2.1.0",
-        "domutils": "1.5.1",
-        "nth-check": "1.0.1"
-      }
-    },
-    "css-selector-tokenizer": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
-      "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
-      "dev": true,
-      "requires": {
-        "cssesc": "0.1.0",
-        "fastparse": "1.1.1",
-        "regexpu-core": "1.0.0"
-      }
-    },
-    "css-what": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
-      "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
-      "dev": true
-    },
-    "cssauron": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
-      "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
-      "dev": true,
-      "requires": {
-        "through": "2.3.8"
-      }
-    },
-    "cssesc": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
-      "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
-      "dev": true
-    },
-    "cuint": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
-      "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=",
-      "dev": true
-    },
-    "currently-unhandled": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
-      "dev": true,
-      "requires": {
-        "array-find-index": "1.0.2"
-      }
-    },
-    "custom-event": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
-      "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
-      "dev": true
-    },
-    "cyclist": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
-      "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
-      "dev": true
-    },
-    "d": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
-      "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
-      "dev": true,
-      "requires": {
-        "es5-ext": "0.10.45"
-      }
-    },
-    "dashdash": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0"
-      }
-    },
-    "date-now": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
-      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
-      "dev": true
-    },
-    "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "requires": {
-        "ms": "2.0.0"
-      }
-    },
-    "decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
-      "dev": true
-    },
-    "decode-uri-component": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
-      "dev": true
-    },
-    "deep-equal": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
-      "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
-      "dev": true
-    },
-    "deep-is": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
-      "dev": true
-    },
-    "default-require-extensions": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
-      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
-      "dev": true,
-      "requires": {
-        "strip-bom": "3.0.0"
-      },
-      "dependencies": {
-        "strip-bom": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
-          "dev": true
-        }
-      }
-    },
-    "define-properties": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
-      "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
-      "dev": true,
-      "requires": {
-        "foreach": "2.0.5",
-        "object-keys": "1.0.11"
-      }
-    },
-    "define-property": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
-      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
-      "dev": true,
-      "requires": {
-        "is-descriptor": "1.0.2",
-        "isobject": "3.0.1"
-      },
-      "dependencies": {
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "1.0.0",
-            "is-data-descriptor": "1.0.0",
-            "kind-of": "6.0.2"
-          }
-        }
-      }
-    },
-    "del": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
-      "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
-      "dev": true,
-      "requires": {
-        "globby": "6.1.0",
-        "is-path-cwd": "1.0.0",
-        "is-path-in-cwd": "1.0.1",
-        "p-map": "1.2.0",
-        "pify": "3.0.0",
-        "rimraf": "2.6.2"
-      },
-      "dependencies": {
-        "globby": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
-          "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
-          "dev": true,
-          "requires": {
-            "array-union": "1.0.2",
-            "glob": "7.1.2",
-            "object-assign": "4.1.1",
-            "pify": "2.3.0",
-            "pinkie-promise": "2.0.1"
-          },
-          "dependencies": {
-            "pify": {
-              "version": "2.3.0",
-              "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-              "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-              "dev": true
-            }
-          }
-        }
-      }
-    },
-    "delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-      "dev": true
-    },
-    "delegates": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
-      "dev": true
-    },
-    "depd": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
-      "dev": true
-    },
-    "des.js": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
-      "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "minimalistic-assert": "1.0.1"
-      }
-    },
-    "destroy": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
-      "dev": true
-    },
-    "detect-indent": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
-      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
-      "dev": true,
-      "requires": {
-        "repeating": "2.0.1"
-      }
-    },
-    "detect-node": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
-      "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=",
-      "dev": true
-    },
-    "di": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
-      "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
-      "dev": true
-    },
-    "diff": {
-      "version": "3.5.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
-      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
-      "dev": true
-    },
-    "diffie-hellman": {
-      "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
-      "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "miller-rabin": "4.0.1",
-        "randombytes": "2.0.6"
-      }
-    },
-    "dir-glob": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
-      "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
-      "dev": true,
-      "requires": {
-        "arrify": "1.0.1",
-        "path-type": "3.0.0"
-      }
-    },
-    "dns-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-      "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
-      "dev": true
-    },
-    "dns-packet": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
-      "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
-      "dev": true,
-      "requires": {
-        "ip": "1.1.5",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "dns-txt": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
-      "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
-      "dev": true,
-      "requires": {
-        "buffer-indexof": "1.1.1"
-      }
-    },
-    "dom-converter": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
-      "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=",
-      "dev": true,
-      "requires": {
-        "utila": "0.3.3"
-      },
-      "dependencies": {
-        "utila": {
-          "version": "0.3.3",
-          "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
-          "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
-          "dev": true
-        }
-      }
-    },
-    "dom-serialize": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
-      "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
-      "dev": true,
-      "requires": {
-        "custom-event": "1.0.1",
-        "ent": "2.2.0",
-        "extend": "3.0.1",
-        "void-elements": "2.0.1"
-      }
-    },
-    "dom-serializer": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
-      "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
-      "dev": true,
-      "requires": {
-        "domelementtype": "1.1.3",
-        "entities": "1.1.1"
-      },
-      "dependencies": {
-        "domelementtype": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
-          "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
-          "dev": true
-        }
-      }
-    },
-    "domain-browser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
-      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
-      "dev": true
-    },
-    "domelementtype": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
-      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
-      "dev": true
-    },
-    "domhandler": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz",
-      "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=",
-      "dev": true,
-      "requires": {
-        "domelementtype": "1.3.0"
-      }
-    },
-    "domutils": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
-      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
-      "dev": true,
-      "requires": {
-        "dom-serializer": "0.1.0",
-        "domelementtype": "1.3.0"
-      }
-    },
-    "duplexify": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
-      "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
-      "dev": true,
-      "requires": {
-        "end-of-stream": "1.4.1",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6",
-        "stream-shift": "1.0.0"
-      }
-    },
-    "ecc-jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
-      "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "jsbn": "0.1.1"
-      }
-    },
-    "ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
-      "dev": true
-    },
-    "ejs": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz",
-      "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==",
-      "dev": true
-    },
-    "electron-to-chromium": {
-      "version": "1.3.48",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz",
-      "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=",
-      "dev": true
-    },
-    "elliptic": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
-      "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "brorand": "1.1.0",
-        "hash.js": "1.1.4",
-        "hmac-drbg": "1.0.1",
-        "inherits": "2.0.3",
-        "minimalistic-assert": "1.0.1",
-        "minimalistic-crypto-utils": "1.0.1"
-      }
-    },
-    "emojis-list": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
-      "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
-      "dev": true
-    },
-    "encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
-      "dev": true
-    },
-    "end-of-stream": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
-      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
-      "dev": true,
-      "requires": {
-        "once": "1.4.0"
-      }
-    },
-    "engine.io": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz",
-      "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=",
-      "dev": true,
-      "requires": {
-        "accepts": "1.3.3",
-        "base64id": "1.0.0",
-        "cookie": "0.3.1",
-        "debug": "2.3.3",
-        "engine.io-parser": "1.3.2",
-        "ws": "1.1.2"
-      },
-      "dependencies": {
-        "accepts": {
-          "version": "1.3.3",
-          "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",
-          "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=",
-          "dev": true,
-          "requires": {
-            "mime-types": "2.1.18",
-            "negotiator": "0.6.1"
-          }
-        },
-        "debug": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
-          "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.2"
-          }
-        },
-        "ms": {
-          "version": "0.7.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-          "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
-          "dev": true
-        }
-      }
-    },
-    "engine.io-client": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz",
-      "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=",
-      "dev": true,
-      "requires": {
-        "component-emitter": "1.2.1",
-        "component-inherit": "0.0.3",
-        "debug": "2.3.3",
-        "engine.io-parser": "1.3.2",
-        "has-cors": "1.1.0",
-        "indexof": "0.0.1",
-        "parsejson": "0.0.3",
-        "parseqs": "0.0.5",
-        "parseuri": "0.0.5",
-        "ws": "1.1.2",
-        "xmlhttprequest-ssl": "1.5.3",
-        "yeast": "0.1.2"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
-          "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.2"
-          }
-        },
-        "ms": {
-          "version": "0.7.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-          "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
-          "dev": true
-        }
-      }
-    },
-    "engine.io-parser": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz",
-      "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
-      "dev": true,
-      "requires": {
-        "after": "0.8.2",
-        "arraybuffer.slice": "0.0.6",
-        "base64-arraybuffer": "0.1.5",
-        "blob": "0.0.4",
-        "has-binary": "0.1.7",
-        "wtf-8": "1.0.0"
-      }
-    },
-    "enhanced-resolve": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz",
-      "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "4.1.11",
-        "memory-fs": "0.4.1",
-        "tapable": "1.0.0"
-      }
-    },
-    "ent": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
-      "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
-      "dev": true
-    },
-    "entities": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
-      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
-      "dev": true
-    },
-    "errno": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
-      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
-      "dev": true,
-      "requires": {
-        "prr": "1.0.1"
-      }
-    },
-    "error-ex": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
-      "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
-      "dev": true,
-      "requires": {
-        "is-arrayish": "0.2.1"
-      }
-    },
-    "es-abstract": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
-      "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
-      "dev": true,
-      "requires": {
-        "es-to-primitive": "1.1.1",
-        "function-bind": "1.1.1",
-        "has": "1.0.3",
-        "is-callable": "1.1.3",
-        "is-regex": "1.0.4"
-      }
-    },
-    "es-to-primitive": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
-      "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
-      "dev": true,
-      "requires": {
-        "is-callable": "1.1.3",
-        "is-date-object": "1.0.1",
-        "is-symbol": "1.0.1"
-      }
-    },
-    "es5-ext": {
-      "version": "0.10.45",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz",
-      "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==",
-      "dev": true,
-      "requires": {
-        "es6-iterator": "2.0.3",
-        "es6-symbol": "3.1.1",
-        "next-tick": "1.0.0"
-      }
-    },
-    "es6-iterator": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-      "dev": true,
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.45",
-        "es6-symbol": "3.1.1"
-      }
-    },
-    "es6-promise": {
-      "version": "4.2.4",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
-      "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
-      "dev": true
-    },
-    "es6-promisify": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
-      "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
-      "dev": true,
-      "requires": {
-        "es6-promise": "4.2.4"
-      }
-    },
-    "es6-symbol": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
-      "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
-      "dev": true,
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.45"
-      }
-    },
-    "escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
-      "dev": true
-    },
-    "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
-    },
-    "escodegen": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
-      "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
-      "dev": true,
-      "requires": {
-        "esprima": "2.7.3",
-        "estraverse": "1.9.3",
-        "esutils": "2.0.2",
-        "optionator": "0.8.2",
-        "source-map": "0.2.0"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.2.0",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
-          "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "amdefine": "1.0.1"
-          }
-        }
-      }
-    },
-    "eslint-scope": {
-      "version": "3.7.1",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
-      "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
-      "dev": true,
-      "requires": {
-        "esrecurse": "4.2.1",
-        "estraverse": "4.2.0"
-      },
-      "dependencies": {
-        "estraverse": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
-          "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
-          "dev": true
-        }
-      }
-    },
-    "esprima": {
-      "version": "2.7.3",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
-      "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
-      "dev": true
-    },
-    "esrecurse": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
-      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
-      "dev": true,
-      "requires": {
-        "estraverse": "4.2.0"
-      },
-      "dependencies": {
-        "estraverse": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
-          "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
-          "dev": true
-        }
-      }
-    },
-    "estraverse": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
-      "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
-      "dev": true
-    },
-    "esutils": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
-      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
-      "dev": true
-    },
-    "etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
-      "dev": true
-    },
-    "eventemitter3": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
-      "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
-      "dev": true
-    },
-    "events": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
-      "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
-      "dev": true
-    },
-    "eventsource": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
-      "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
-      "dev": true,
-      "requires": {
-        "original": "1.0.1"
-      }
-    },
-    "evp_bytestokey": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
-      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
-      "dev": true,
-      "requires": {
-        "md5.js": "1.3.4",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "execa": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
-      "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
-      "dev": true,
-      "requires": {
-        "cross-spawn": "5.1.0",
-        "get-stream": "3.0.0",
-        "is-stream": "1.1.0",
-        "npm-run-path": "2.0.2",
-        "p-finally": "1.0.0",
-        "signal-exit": "3.0.2",
-        "strip-eof": "1.0.0"
-      },
-      "dependencies": {
-        "cross-spawn": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-          "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
-          "dev": true,
-          "requires": {
-            "lru-cache": "4.1.3",
-            "shebang-command": "1.2.0",
-            "which": "1.3.1"
-          }
-        }
-      }
-    },
-    "exit": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
-      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
-      "dev": true
-    },
-    "expand-braces": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz",
-      "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=",
-      "dev": true,
-      "requires": {
-        "array-slice": "0.2.3",
-        "array-unique": "0.2.1",
-        "braces": "0.1.5"
-      },
-      "dependencies": {
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-          "dev": true
-        },
-        "braces": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz",
-          "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=",
-          "dev": true,
-          "requires": {
-            "expand-range": "0.1.1"
-          }
-        },
-        "expand-range": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz",
-          "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=",
-          "dev": true,
-          "requires": {
-            "is-number": "0.1.1",
-            "repeat-string": "0.2.2"
-          }
-        },
-        "is-number": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz",
-          "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=",
-          "dev": true
-        },
-        "repeat-string": {
-          "version": "0.2.2",
-          "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz",
-          "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=",
-          "dev": true
-        }
-      }
-    },
-    "expand-brackets": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "define-property": "0.2.5",
-        "extend-shallow": "2.0.1",
-        "posix-character-classes": "0.1.1",
-        "regex-not": "1.0.2",
-        "snapdragon": "0.8.2",
-        "to-regex": "3.0.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        },
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        }
-      }
-    },
-    "expand-range": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
-      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
-      "dev": true,
-      "requires": {
-        "fill-range": "2.2.4"
-      },
-      "dependencies": {
-        "fill-range": {
-          "version": "2.2.4",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
-          "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
-          "dev": true,
-          "requires": {
-            "is-number": "2.1.0",
-            "isobject": "2.1.0",
-            "randomatic": "3.0.0",
-            "repeat-element": "1.1.2",
-            "repeat-string": "1.6.1"
-          }
-        },
-        "is-number": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
-          "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
-          "dev": true,
-          "requires": {
-            "kind-of": "3.2.2"
-          }
-        },
-        "isobject": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-          "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-          "dev": true,
-          "requires": {
-            "isarray": "1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "express": {
-      "version": "4.16.3",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
-      "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
-      "dev": true,
-      "requires": {
-        "accepts": "1.3.5",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.18.2",
-        "content-disposition": "0.5.2",
-        "content-type": "1.0.4",
-        "cookie": "0.3.1",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "1.1.2",
-        "encodeurl": "1.0.2",
-        "escape-html": "1.0.3",
-        "etag": "1.8.1",
-        "finalhandler": "1.1.1",
-        "fresh": "0.5.2",
-        "merge-descriptors": "1.0.1",
-        "methods": "1.1.2",
-        "on-finished": "2.3.0",
-        "parseurl": "1.3.2",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "2.0.3",
-        "qs": "6.5.1",
-        "range-parser": "1.2.0",
-        "safe-buffer": "5.1.1",
-        "send": "0.16.2",
-        "serve-static": "1.13.2",
-        "setprototypeof": "1.1.0",
-        "statuses": "1.4.0",
-        "type-is": "1.6.16",
-        "utils-merge": "1.0.1",
-        "vary": "1.1.2"
-      },
-      "dependencies": {
-        "array-flatten": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-          "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
-          "dev": true
-        },
-        "qs": {
-          "version": "6.5.1",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
-          "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
-          "dev": true
-        },
-        "safe-buffer": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
-          "dev": true
-        }
-      }
-    },
-    "extend": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
-      "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
-      "dev": true
-    },
-    "extend-shallow": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-      "dev": true,
-      "requires": {
-        "assign-symbols": "1.0.0",
-        "is-extendable": "1.0.1"
-      },
-      "dependencies": {
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "2.0.4"
-          }
-        }
-      }
-    },
-    "extglob": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-      "dev": true,
-      "requires": {
-        "array-unique": "0.3.2",
-        "define-property": "1.0.0",
-        "expand-brackets": "2.1.4",
-        "extend-shallow": "2.0.1",
-        "fragment-cache": "0.2.1",
-        "regex-not": "1.0.2",
-        "snapdragon": "0.8.2",
-        "to-regex": "3.0.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "1.0.2"
-          }
-        },
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "1.0.0",
-            "is-data-descriptor": "1.0.0",
-            "kind-of": "6.0.2"
-          }
-        }
-      }
-    },
-    "extsprintf": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-      "dev": true
-    },
-    "fast-deep-equal": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-      "dev": true
-    },
-    "fast-json-stable-stringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
-      "dev": true
-    },
-    "fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
-      "dev": true
-    },
-    "fastparse": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
-      "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
-      "dev": true
-    },
-    "faye-websocket": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
-      "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
-      "dev": true,
-      "requires": {
-        "websocket-driver": "0.7.0"
-      }
-    },
-    "file-loader": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
-      "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "schema-utils": "0.4.5"
-      }
-    },
-    "filename-regex": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
-      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
-      "dev": true
-    },
-    "fileset": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
-      "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
-      "dev": true,
-      "requires": {
-        "glob": "7.1.2",
-        "minimatch": "3.0.4"
-      }
-    },
-    "fill-range": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-      "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "2.0.1",
-        "is-number": "3.0.0",
-        "repeat-string": "1.6.1",
-        "to-regex-range": "2.1.1"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        }
-      }
-    },
-    "finalhandler": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
-      "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "encodeurl": "1.0.2",
-        "escape-html": "1.0.3",
-        "on-finished": "2.3.0",
-        "parseurl": "1.3.2",
-        "statuses": "1.4.0",
-        "unpipe": "1.0.0"
-      }
-    },
-    "find-cache-dir": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
-      "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
-      "dev": true,
-      "requires": {
-        "commondir": "1.0.1",
-        "make-dir": "1.3.0",
-        "pkg-dir": "2.0.0"
-      }
-    },
-    "find-up": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-      "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-      "dev": true,
-      "requires": {
-        "locate-path": "2.0.0"
-      }
-    },
-    "flush-write-stream": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
-      "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "follow-redirects": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz",
-      "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==",
-      "dev": true,
-      "requires": {
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "for-in": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
-      "dev": true
-    },
-    "for-own": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
-      "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
-      "dev": true,
-      "requires": {
-        "for-in": "1.0.2"
-      }
-    },
-    "foreach": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
-      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
-      "dev": true
-    },
-    "forever-agent": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
-      "dev": true
-    },
-    "form-data": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
-      "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
-      "dev": true,
-      "requires": {
-        "asynckit": "0.4.0",
-        "combined-stream": "1.0.6",
-        "mime-types": "2.1.18"
-      }
-    },
-    "forwarded": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
-      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
-      "dev": true
-    },
-    "fragment-cache": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
-      "dev": true,
-      "requires": {
-        "map-cache": "0.2.2"
-      }
-    },
-    "fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
-      "dev": true
-    },
-    "from2": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
-      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "fs-access": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
-      "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
-      "dev": true,
-      "requires": {
-        "null-check": "1.0.0"
-      }
-    },
-    "fs-write-stream-atomic": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
-      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "4.1.11",
-        "iferr": "0.1.5",
-        "imurmurhash": "0.1.4",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-      "dev": true
-    },
-    "fsevents": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
-      "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "nan": "2.10.0",
-        "node-pre-gyp": "0.10.0"
-      },
-      "dependencies": {
-        "abbrev": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "ansi-regex": {
-          "version": "2.1.1",
-          "bundled": true,
-          "dev": true
-        },
-        "aproba": {
-          "version": "1.2.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "are-we-there-yet": {
-          "version": "1.1.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "delegates": "1.0.0",
-            "readable-stream": "2.3.6"
-          }
-        },
-        "balanced-match": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true
-        },
-        "brace-expansion": {
-          "version": "1.1.11",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "balanced-match": "1.0.0",
-            "concat-map": "0.0.1"
-          }
-        },
-        "chownr": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "code-point-at": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true
-        },
-        "concat-map": {
-          "version": "0.0.1",
-          "bundled": true,
-          "dev": true
-        },
-        "console-control-strings": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true
-        },
-        "core-util-is": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "debug": {
-          "version": "2.6.9",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "deep-extend": {
-          "version": "0.5.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "delegates": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "detect-libc": {
-          "version": "1.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "fs-minipass": {
-          "version": "1.2.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "2.2.4"
-          }
-        },
-        "fs.realpath": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "gauge": {
-          "version": "2.7.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "aproba": "1.2.0",
-            "console-control-strings": "1.1.0",
-            "has-unicode": "2.0.1",
-            "object-assign": "4.1.1",
-            "signal-exit": "3.0.2",
-            "string-width": "1.0.2",
-            "strip-ansi": "3.0.1",
-            "wide-align": "1.1.2"
-          }
-        },
-        "glob": {
-          "version": "7.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "fs.realpath": "1.0.0",
-            "inflight": "1.0.6",
-            "inherits": "2.0.3",
-            "minimatch": "3.0.4",
-            "once": "1.4.0",
-            "path-is-absolute": "1.0.1"
-          }
-        },
-        "has-unicode": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "iconv-lite": {
-          "version": "0.4.21",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safer-buffer": "2.1.2"
-          }
-        },
-        "ignore-walk": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimatch": "3.0.4"
-          }
-        },
-        "inflight": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "once": "1.4.0",
-            "wrappy": "1.0.2"
-          }
-        },
-        "inherits": {
-          "version": "2.0.3",
-          "bundled": true,
-          "dev": true
-        },
-        "ini": {
-          "version": "1.3.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "number-is-nan": "1.0.1"
-          }
-        },
-        "isarray": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "minimatch": {
-          "version": "3.0.4",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "brace-expansion": "1.1.11"
-          }
-        },
-        "minimist": {
-          "version": "0.0.8",
-          "bundled": true,
-          "dev": true
-        },
-        "minipass": {
-          "version": "2.2.4",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "safe-buffer": "5.1.1",
-            "yallist": "3.0.2"
-          }
-        },
-        "minizlib": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "2.2.4"
-          }
-        },
-        "mkdirp": {
-          "version": "0.5.1",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "minimist": "0.0.8"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "needle": {
-          "version": "2.2.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "debug": "2.6.9",
-            "iconv-lite": "0.4.21",
-            "sax": "1.2.4"
-          }
-        },
-        "node-pre-gyp": {
-          "version": "0.10.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "detect-libc": "1.0.3",
-            "mkdirp": "0.5.1",
-            "needle": "2.2.0",
-            "nopt": "4.0.1",
-            "npm-packlist": "1.1.10",
-            "npmlog": "4.1.2",
-            "rc": "1.2.7",
-            "rimraf": "2.6.2",
-            "semver": "5.5.0",
-            "tar": "4.4.1"
-          }
-        },
-        "nopt": {
-          "version": "4.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "abbrev": "1.1.1",
-            "osenv": "0.1.5"
-          }
-        },
-        "npm-bundled": {
-          "version": "1.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "npm-packlist": {
-          "version": "1.1.10",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ignore-walk": "3.0.1",
-            "npm-bundled": "1.0.3"
-          }
-        },
-        "npmlog": {
-          "version": "4.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "are-we-there-yet": "1.1.4",
-            "console-control-strings": "1.1.0",
-            "gauge": "2.7.4",
-            "set-blocking": "2.0.0"
-          }
-        },
-        "number-is-nan": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "once": {
-          "version": "1.4.0",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "wrappy": "1.0.2"
-          }
-        },
-        "os-homedir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "os-tmpdir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "osenv": {
-          "version": "0.1.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "os-homedir": "1.0.2",
-            "os-tmpdir": "1.0.2"
-          }
-        },
-        "path-is-absolute": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "process-nextick-args": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "rc": {
-          "version": "1.2.7",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "deep-extend": "0.5.1",
-            "ini": "1.3.5",
-            "minimist": "1.2.0",
-            "strip-json-comments": "2.0.1"
-          },
-          "dependencies": {
-            "minimist": {
-              "version": "1.2.0",
-              "bundled": true,
-              "dev": true,
-              "optional": true
-            }
-          }
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "core-util-is": "1.0.2",
-            "inherits": "2.0.3",
-            "isarray": "1.0.0",
-            "process-nextick-args": "2.0.0",
-            "safe-buffer": "5.1.1",
-            "string_decoder": "1.1.1",
-            "util-deprecate": "1.0.2"
-          }
-        },
-        "rimraf": {
-          "version": "2.6.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "glob": "7.1.2"
-          }
-        },
-        "safe-buffer": {
-          "version": "5.1.1",
-          "bundled": true,
-          "dev": true
-        },
-        "safer-buffer": {
-          "version": "2.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "sax": {
-          "version": "1.2.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "semver": {
-          "version": "5.5.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "set-blocking": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "signal-exit": {
-          "version": "3.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "string-width": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "code-point-at": "1.1.0",
-            "is-fullwidth-code-point": "1.0.0",
-            "strip-ansi": "3.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safe-buffer": "5.1.1"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "ansi-regex": "2.1.1"
-          }
-        },
-        "strip-json-comments": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "tar": {
-          "version": "4.4.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chownr": "1.0.1",
-            "fs-minipass": "1.2.5",
-            "minipass": "2.2.4",
-            "minizlib": "1.1.0",
-            "mkdirp": "0.5.1",
-            "safe-buffer": "5.1.1",
-            "yallist": "3.0.2"
-          }
-        },
-        "util-deprecate": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "wide-align": {
-          "version": "1.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "string-width": "1.0.2"
-          }
-        },
-        "wrappy": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true
-        },
-        "yallist": {
-          "version": "3.0.2",
-          "bundled": true,
-          "dev": true
-        }
-      }
-    },
-    "fstream": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
-      "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "4.1.11",
-        "inherits": "2.0.3",
-        "mkdirp": "0.5.1",
-        "rimraf": "2.6.2"
-      }
-    },
-    "function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "dev": true
-    },
-    "gauge": {
-      "version": "2.7.4",
-      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
-      "dev": true,
-      "requires": {
-        "aproba": "1.2.0",
-        "console-control-strings": "1.1.0",
-        "has-unicode": "2.0.1",
-        "object-assign": "4.1.1",
-        "signal-exit": "3.0.2",
-        "string-width": "1.0.2",
-        "strip-ansi": "3.0.1",
-        "wide-align": "1.1.3"
-      }
-    },
-    "gaze": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
-      "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "globule": "1.2.1"
-      }
-    },
-    "generate-function": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
-      "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=",
-      "dev": true,
-      "optional": true
-    },
-    "generate-object-property": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
-      "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "is-property": "1.0.2"
-      }
-    },
-    "get-caller-file": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
-      "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
-      "dev": true
-    },
-    "get-stdin": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
-      "dev": true
-    },
-    "get-stream": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
-      "dev": true
-    },
-    "get-value": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
-      "dev": true
-    },
-    "getpass": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0"
-      }
-    },
-    "glob": {
-      "version": "7.1.2",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
-      "dev": true,
-      "requires": {
-        "fs.realpath": "1.0.0",
-        "inflight": "1.0.6",
-        "inherits": "2.0.3",
-        "minimatch": "3.0.4",
-        "once": "1.4.0",
-        "path-is-absolute": "1.0.1"
-      }
-    },
-    "glob-base": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
-      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
-      "dev": true,
-      "requires": {
-        "glob-parent": "2.0.0",
-        "is-glob": "2.0.1"
-      },
-      "dependencies": {
-        "glob-parent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-          "dev": true,
-          "requires": {
-            "is-glob": "2.0.1"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        }
-      }
-    },
-    "glob-parent": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-      "dev": true,
-      "requires": {
-        "is-glob": "3.1.0",
-        "path-dirname": "1.0.2"
-      },
-      "dependencies": {
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "2.1.1"
-          }
-        }
-      }
-    },
-    "globals": {
-      "version": "9.18.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
-      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
-      "dev": true
-    },
-    "globby": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
-      "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
-      "dev": true,
-      "requires": {
-        "array-union": "1.0.2",
-        "dir-glob": "2.0.0",
-        "glob": "7.1.2",
-        "ignore": "3.3.8",
-        "pify": "3.0.0",
-        "slash": "1.0.0"
-      }
-    },
-    "globule": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
-      "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "glob": "7.1.2",
-        "lodash": "4.17.10",
-        "minimatch": "3.0.4"
-      }
-    },
-    "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
-      "dev": true
-    },
-    "handle-thing": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
-      "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
-      "dev": true
-    },
-    "handlebars": {
-      "version": "4.0.11",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
-      "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=",
-      "dev": true,
-      "requires": {
-        "async": "1.5.2",
-        "optimist": "0.6.1",
-        "source-map": "0.4.4",
-        "uglify-js": "2.8.29"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
-          "dev": true,
-          "requires": {
-            "amdefine": "1.0.1"
-          }
-        },
-        "uglify-js": {
-          "version": "2.8.29",
-          "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
-          "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "source-map": "0.5.7",
-            "uglify-to-browserify": "1.0.2",
-            "yargs": "3.10.0"
-          },
-          "dependencies": {
-            "source-map": {
-              "version": "0.5.7",
-              "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-              "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-              "dev": true,
-              "optional": true
-            }
-          }
-        }
-      }
-    },
-    "har-schema": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
-      "dev": true
-    },
-    "har-validator": {
-      "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
-      "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
-      "dev": true,
-      "requires": {
-        "ajv": "5.5.2",
-        "har-schema": "2.0.0"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "5.5.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-          "dev": true,
-          "requires": {
-            "co": "4.6.0",
-            "fast-deep-equal": "1.1.0",
-            "fast-json-stable-stringify": "2.0.0",
-            "json-schema-traverse": "0.3.1"
-          }
-        }
-      }
-    },
-    "has": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "dev": true,
-      "requires": {
-        "function-bind": "1.1.1"
-      }
-    },
-    "has-ansi": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "2.1.1"
-      }
-    },
-    "has-binary": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz",
-      "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=",
-      "dev": true,
-      "requires": {
-        "isarray": "0.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        }
-      }
-    },
-    "has-cors": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
-      "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
-      "dev": true
-    },
-    "has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
-    },
-    "has-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
-      "dev": true
-    },
-    "has-unicode": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
-      "dev": true
-    },
-    "has-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
-      "dev": true,
-      "requires": {
-        "get-value": "2.0.6",
-        "has-values": "1.0.0",
-        "isobject": "3.0.1"
-      }
-    },
-    "has-values": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
-      "dev": true,
-      "requires": {
-        "is-number": "3.0.0",
-        "kind-of": "4.0.0"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "hash-base": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
-      "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "hash.js": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.4.tgz",
-      "integrity": "sha512-A6RlQvvZEtFS5fLU43IDu0QUmBy+fDO9VMdTXvufKwIkt/rFfvICAViCax5fbDO4zdNzaC3/27ZhKUok5bAJyw==",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "minimalistic-assert": "1.0.1"
-      }
-    },
-    "hawk": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
-      "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
-      "dev": true,
-      "requires": {
-        "boom": "2.10.1",
-        "cryptiles": "2.0.5",
-        "hoek": "2.16.3",
-        "sntp": "1.0.9"
-      }
-    },
-    "he": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
-      "dev": true
-    },
-    "hmac-drbg": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
-      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
-      "dev": true,
-      "requires": {
-        "hash.js": "1.1.4",
-        "minimalistic-assert": "1.0.1",
-        "minimalistic-crypto-utils": "1.0.1"
-      }
-    },
-    "hoek": {
-      "version": "2.16.3",
-      "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
-      "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
-      "dev": true
-    },
-    "hosted-git-info": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
-      "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
-      "dev": true
-    },
-    "hpack.js": {
-      "version": "2.1.6",
-      "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-      "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "obuf": "1.1.2",
-        "readable-stream": "2.3.6",
-        "wbuf": "1.7.3"
-      }
-    },
-    "html-entities": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
-      "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
-      "dev": true
-    },
-    "html-minifier": {
-      "version": "3.5.16",
-      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.16.tgz",
-      "integrity": "sha512-zP5EfLSpiLRp0aAgud4CQXPQZm9kXwWjR/cF0PfdOj+jjWnOaCgeZcll4kYXSvIBPeUMmyaSc7mM4IDtA+kboA==",
-      "dev": true,
-      "requires": {
-        "camel-case": "3.0.0",
-        "clean-css": "4.1.11",
-        "commander": "2.15.1",
-        "he": "1.1.1",
-        "param-case": "2.1.1",
-        "relateurl": "0.2.7",
-        "uglify-js": "3.3.28"
-      }
-    },
-    "html-webpack-plugin": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
-      "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
-      "dev": true,
-      "requires": {
-        "html-minifier": "3.5.16",
-        "loader-utils": "0.2.17",
-        "lodash": "4.17.10",
-        "pretty-error": "2.1.1",
-        "tapable": "1.0.0",
-        "toposort": "1.0.7",
-        "util.promisify": "1.0.0"
-      },
-      "dependencies": {
-        "loader-utils": {
-          "version": "0.2.17",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
-          "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
-          "dev": true,
-          "requires": {
-            "big.js": "3.2.0",
-            "emojis-list": "2.1.0",
-            "json5": "0.5.1",
-            "object-assign": "4.1.1"
-          }
-        }
-      }
-    },
-    "htmlparser2": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
-      "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
-      "dev": true,
-      "requires": {
-        "domelementtype": "1.3.0",
-        "domhandler": "2.1.0",
-        "domutils": "1.1.6",
-        "readable-stream": "1.0.34"
-      },
-      "dependencies": {
-        "domutils": {
-          "version": "1.1.6",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz",
-          "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=",
-          "dev": true,
-          "requires": {
-            "domelementtype": "1.3.0"
-          }
-        },
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "1.0.34",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-          "dev": true,
-          "requires": {
-            "core-util-is": "1.0.2",
-            "inherits": "2.0.3",
-            "isarray": "0.0.1",
-            "string_decoder": "0.10.31"
-          }
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        }
-      }
-    },
-    "http-deceiver": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-      "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
-      "dev": true
-    },
-    "http-errors": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
-      "dev": true,
-      "requires": {
-        "depd": "1.1.2",
-        "inherits": "2.0.3",
-        "setprototypeof": "1.1.0",
-        "statuses": "1.4.0"
-      }
-    },
-    "http-parser-js": {
-      "version": "0.4.13",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz",
-      "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=",
-      "dev": true
-    },
-    "http-proxy": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
-      "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
-      "dev": true,
-      "requires": {
-        "eventemitter3": "3.1.0",
-        "follow-redirects": "1.5.0",
-        "requires-port": "1.0.0"
-      }
-    },
-    "http-proxy-middleware": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz",
-      "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==",
-      "dev": true,
-      "requires": {
-        "http-proxy": "1.17.0",
-        "is-glob": "4.0.0",
-        "lodash": "4.17.10",
-        "micromatch": "3.1.10"
-      }
-    },
-    "http-signature": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0",
-        "jsprim": "1.4.1",
-        "sshpk": "1.14.2"
-      }
-    },
-    "https-browserify": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
-      "dev": true
-    },
-    "https-proxy-agent": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
-      "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
-      "dev": true,
-      "requires": {
-        "agent-base": "4.2.0",
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "iconv-lite": {
-      "version": "0.4.19",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
-      "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
-      "dev": true
-    },
-    "ieee754": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
-      "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==",
-      "dev": true
-    },
-    "iferr": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
-      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
-      "dev": true
-    },
-    "ignore": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
-      "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==",
-      "dev": true
-    },
-    "image-size": {
-      "version": "0.5.5",
-      "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
-      "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
-      "dev": true,
-      "optional": true
-    },
-    "immediate": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-      "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
-      "dev": true
-    },
-    "import-local": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
-      "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==",
-      "dev": true,
-      "requires": {
-        "pkg-dir": "2.0.0",
-        "resolve-cwd": "2.0.0"
-      }
-    },
-    "imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
-      "dev": true
-    },
-    "in-publish": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
-      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
-      "dev": true,
-      "optional": true
-    },
-    "indent-string": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
-      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
-      "dev": true,
-      "requires": {
-        "repeating": "2.0.1"
-      }
-    },
-    "indexof": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
-      "dev": true
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true,
-      "requires": {
-        "once": "1.4.0",
-        "wrappy": "1.0.2"
-      }
-    },
-    "inherits": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-      "dev": true
-    },
-    "ini": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
-      "dev": true
-    },
-    "internal-ip": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
-      "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
-      "dev": true,
-      "requires": {
-        "meow": "3.7.0"
-      }
-    },
-    "invariant": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-      "dev": true,
-      "requires": {
-        "loose-envify": "1.3.1"
-      }
-    },
-    "invert-kv": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
-      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
-      "dev": true
-    },
-    "ip": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
-      "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
-      "dev": true
-    },
-    "ipaddr.js": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
-      "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=",
-      "dev": true
-    },
-    "is-accessor-descriptor": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "is-arrayish": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
-      "dev": true
-    },
-    "is-binary-path": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "1.11.0"
-      }
-    },
-    "is-buffer": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
-      "dev": true
-    },
-    "is-builtin-module": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
-      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
-      "dev": true,
-      "requires": {
-        "builtin-modules": "1.1.1"
-      }
-    },
-    "is-callable": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
-      "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
-      "dev": true
-    },
-    "is-data-descriptor": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "is-date-object": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
-      "dev": true
-    },
-    "is-descriptor": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-      "dev": true,
-      "requires": {
-        "is-accessor-descriptor": "0.1.6",
-        "is-data-descriptor": "0.1.4",
-        "kind-of": "5.1.0"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
-        }
-      }
-    },
-    "is-directory": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
-      "dev": true
-    },
-    "is-dotfile": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
-      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
-      "dev": true
-    },
-    "is-equal-shallow": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
-      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
-      "dev": true,
-      "requires": {
-        "is-primitive": "2.0.0"
-      }
-    },
-    "is-extendable": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-      "dev": true
-    },
-    "is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-      "dev": true
-    },
-    "is-finite": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
-      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
-      "dev": true,
-      "requires": {
-        "number-is-nan": "1.0.1"
-      }
-    },
-    "is-fullwidth-code-point": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-      "dev": true,
-      "requires": {
-        "number-is-nan": "1.0.1"
-      }
-    },
-    "is-glob": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
-      "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
-      "dev": true,
-      "requires": {
-        "is-extglob": "2.1.1"
-      }
-    },
-    "is-my-ip-valid": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
-      "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
-      "dev": true,
-      "optional": true
-    },
-    "is-my-json-valid": {
-      "version": "2.17.2",
-      "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz",
-      "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "generate-function": "2.0.0",
-        "generate-object-property": "1.2.0",
-        "is-my-ip-valid": "1.0.0",
-        "jsonpointer": "4.0.1",
-        "xtend": "4.0.1"
-      }
-    },
-    "is-number": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-      "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "is-odd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz",
-      "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "4.0.0"
-      },
-      "dependencies": {
-        "is-number": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
-          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
-          "dev": true
-        }
-      }
-    },
-    "is-path-cwd": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
-      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
-      "dev": true
-    },
-    "is-path-in-cwd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
-      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
-      "dev": true,
-      "requires": {
-        "is-path-inside": "1.0.1"
-      }
-    },
-    "is-path-inside": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
-      "dev": true,
-      "requires": {
-        "path-is-inside": "1.0.2"
-      }
-    },
-    "is-plain-object": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
-      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
-      "dev": true,
-      "requires": {
-        "isobject": "3.0.1"
-      }
-    },
-    "is-posix-bracket": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
-      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
-      "dev": true
-    },
-    "is-primitive": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
-      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
-      "dev": true
-    },
-    "is-property": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
-      "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
-      "dev": true,
-      "optional": true
-    },
-    "is-regex": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
-      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
-      "dev": true,
-      "requires": {
-        "has": "1.0.3"
-      }
-    },
-    "is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
-      "dev": true
-    },
-    "is-symbol": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
-      "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
-      "dev": true
-    },
-    "is-typedarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
-      "dev": true
-    },
-    "is-utf8": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
-      "dev": true
-    },
-    "is-windows": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
-      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
-      "dev": true
-    },
-    "is-wsl": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
-      "dev": true
-    },
-    "isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
-    },
-    "isbinaryfile": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz",
-      "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=",
-      "dev": true
-    },
-    "isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
-      "dev": true
-    },
-    "isobject": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-      "dev": true
-    },
-    "isstream": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
-      "dev": true
-    },
-    "istanbul": {
-      "version": "0.4.5",
-      "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
-      "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
-      "dev": true,
-      "requires": {
-        "abbrev": "1.0.9",
-        "async": "1.5.2",
-        "escodegen": "1.8.1",
-        "esprima": "2.7.3",
-        "glob": "5.0.15",
-        "handlebars": "4.0.11",
-        "js-yaml": "3.12.0",
-        "mkdirp": "0.5.1",
-        "nopt": "3.0.6",
-        "once": "1.4.0",
-        "resolve": "1.1.7",
-        "supports-color": "3.2.3",
-        "which": "1.3.1",
-        "wordwrap": "1.0.0"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "5.0.15",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
-          "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
-          "dev": true,
-          "requires": {
-            "inflight": "1.0.6",
-            "inherits": "2.0.3",
-            "minimatch": "3.0.4",
-            "once": "1.4.0",
-            "path-is-absolute": "1.0.1"
-          }
-        },
-        "has-flag": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
-          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
-          "dev": true
-        },
-        "resolve": {
-          "version": "1.1.7",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
-          "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "dev": true,
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "istanbul-api": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz",
-      "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==",
-      "dev": true,
-      "requires": {
-        "async": "2.6.1",
-        "compare-versions": "3.3.0",
-        "fileset": "2.0.3",
-        "istanbul-lib-coverage": "1.2.0",
-        "istanbul-lib-hook": "1.2.1",
-        "istanbul-lib-instrument": "1.10.1",
-        "istanbul-lib-report": "1.1.4",
-        "istanbul-lib-source-maps": "1.2.5",
-        "istanbul-reports": "1.3.0",
-        "js-yaml": "3.12.0",
-        "mkdirp": "0.5.1",
-        "once": "1.4.0"
-      },
-      "dependencies": {
-        "async": {
-          "version": "2.6.1",
-          "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
-          "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
-          "dev": true,
-          "requires": {
-            "lodash": "4.17.10"
-          }
-        }
-      }
-    },
-    "istanbul-instrumenter-loader": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz",
-      "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==",
-      "dev": true,
-      "requires": {
-        "convert-source-map": "1.5.1",
-        "istanbul-lib-instrument": "1.10.1",
-        "loader-utils": "1.1.0",
-        "schema-utils": "0.3.0"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "5.5.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-          "dev": true,
-          "requires": {
-            "co": "4.6.0",
-            "fast-deep-equal": "1.1.0",
-            "fast-json-stable-stringify": "2.0.0",
-            "json-schema-traverse": "0.3.1"
-          }
-        },
-        "schema-utils": {
-          "version": "0.3.0",
-          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
-          "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
-          "dev": true,
-          "requires": {
-            "ajv": "5.5.2"
-          }
-        }
-      }
-    },
-    "istanbul-lib-coverage": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz",
-      "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==",
-      "dev": true
-    },
-    "istanbul-lib-hook": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz",
-      "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==",
-      "dev": true,
-      "requires": {
-        "append-transform": "1.0.0"
-      }
-    },
-    "istanbul-lib-instrument": {
-      "version": "1.10.1",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz",
-      "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==",
-      "dev": true,
-      "requires": {
-        "babel-generator": "6.26.1",
-        "babel-template": "6.26.0",
-        "babel-traverse": "6.26.0",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0",
-        "istanbul-lib-coverage": "1.2.0",
-        "semver": "5.5.0"
-      }
-    },
-    "istanbul-lib-report": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz",
-      "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==",
-      "dev": true,
-      "requires": {
-        "istanbul-lib-coverage": "1.2.0",
-        "mkdirp": "0.5.1",
-        "path-parse": "1.0.5",
-        "supports-color": "3.2.3"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
-          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "dev": true,
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "istanbul-lib-source-maps": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz",
-      "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==",
-      "dev": true,
-      "requires": {
-        "debug": "3.1.0",
-        "istanbul-lib-coverage": "1.2.0",
-        "mkdirp": "0.5.1",
-        "rimraf": "2.6.2",
-        "source-map": "0.5.7"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "istanbul-reports": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz",
-      "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==",
-      "dev": true,
-      "requires": {
-        "handlebars": "4.0.11"
-      }
-    },
-    "jasmine": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
-      "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
-      "dev": true,
-      "requires": {
-        "exit": "0.1.2",
-        "glob": "7.1.2",
-        "jasmine-core": "2.8.0"
-      },
-      "dependencies": {
-        "jasmine-core": {
-          "version": "2.8.0",
-          "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
-          "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
-          "dev": true
-        }
-      }
-    },
-    "jasmine-core": {
-      "version": "2.99.1",
-      "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
-      "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
-      "dev": true
-    },
-    "jasmine-spec-reporter": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
-      "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
-      "dev": true,
-      "requires": {
-        "colors": "1.1.2"
-      }
-    },
-    "jasminewd2": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
-      "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
-      "dev": true
-    },
-    "js-base64": {
-      "version": "2.4.5",
-      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz",
-      "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==",
-      "dev": true,
-      "optional": true
-    },
-    "js-tokens": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
-      "dev": true
-    },
-    "js-yaml": {
-      "version": "3.12.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
-      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
-      "dev": true,
-      "requires": {
-        "argparse": "1.0.10",
-        "esprima": "4.0.0"
-      },
-      "dependencies": {
-        "esprima": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
-          "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
-          "dev": true
-        }
-      }
-    },
-    "jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-      "dev": true,
-      "optional": true
-    },
-    "jsesc": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
-      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
-      "dev": true
-    },
-    "json-schema": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
-      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
-      "dev": true
-    },
-    "json-schema-traverse": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-      "dev": true
-    },
-    "json-stable-stringify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
-      "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "jsonify": "0.0.0"
-      }
-    },
-    "json-stringify-safe": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
-      "dev": true
-    },
-    "json3": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
-      "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
-      "dev": true
-    },
-    "json5": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
-      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
-      "dev": true
-    },
-    "jsonify": {
-      "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
-      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
-      "dev": true,
-      "optional": true
-    },
-    "jsonpointer": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
-      "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
-      "dev": true,
-      "optional": true
-    },
-    "jsprim": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
-      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0",
-        "extsprintf": "1.3.0",
-        "json-schema": "0.2.3",
-        "verror": "1.10.0"
-      }
-    },
-    "jszip": {
-      "version": "3.1.5",
-      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
-      "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
-      "dev": true,
-      "requires": {
-        "core-js": "2.3.0",
-        "es6-promise": "3.0.2",
-        "lie": "3.1.1",
-        "pako": "1.0.6",
-        "readable-stream": "2.0.6"
-      },
-      "dependencies": {
-        "core-js": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
-          "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=",
-          "dev": true
-        },
-        "es6-promise": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
-          "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=",
-          "dev": true
-        },
-        "process-nextick-args": {
-          "version": "1.0.7",
-          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "2.0.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
-          "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
-          "dev": true,
-          "requires": {
-            "core-util-is": "1.0.2",
-            "inherits": "2.0.3",
-            "isarray": "1.0.0",
-            "process-nextick-args": "1.0.7",
-            "string_decoder": "0.10.31",
-            "util-deprecate": "1.0.2"
-          }
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        }
-      }
-    },
-    "karma": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz",
-      "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==",
-      "dev": true,
-      "requires": {
-        "bluebird": "3.5.1",
-        "body-parser": "1.18.2",
-        "chokidar": "1.7.0",
-        "colors": "1.1.2",
-        "combine-lists": "1.0.1",
-        "connect": "3.6.6",
-        "core-js": "2.5.7",
-        "di": "0.0.1",
-        "dom-serialize": "2.2.1",
-        "expand-braces": "0.1.2",
-        "glob": "7.1.2",
-        "graceful-fs": "4.1.11",
-        "http-proxy": "1.17.0",
-        "isbinaryfile": "3.0.2",
-        "lodash": "3.10.1",
-        "log4js": "0.6.38",
-        "mime": "1.6.0",
-        "minimatch": "3.0.4",
-        "optimist": "0.6.1",
-        "qjobs": "1.2.0",
-        "range-parser": "1.2.0",
-        "rimraf": "2.6.2",
-        "safe-buffer": "5.1.2",
-        "socket.io": "1.7.3",
-        "source-map": "0.5.7",
-        "tmp": "0.0.31",
-        "useragent": "2.3.0"
-      },
-      "dependencies": {
-        "anymatch": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
-          "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
-          "dev": true,
-          "requires": {
-            "micromatch": "2.3.11",
-            "normalize-path": "2.1.1"
-          }
-        },
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "1.1.0"
-          }
-        },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-          "dev": true
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-          "dev": true,
-          "requires": {
-            "expand-range": "1.8.2",
-            "preserve": "0.2.0",
-            "repeat-element": "1.1.2"
-          }
-        },
-        "chokidar": {
-          "version": "1.7.0",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
-          "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
-          "dev": true,
-          "requires": {
-            "anymatch": "1.3.2",
-            "async-each": "1.0.1",
-            "fsevents": "1.2.4",
-            "glob-parent": "2.0.0",
-            "inherits": "2.0.3",
-            "is-binary-path": "1.0.1",
-            "is-glob": "2.0.1",
-            "path-is-absolute": "1.0.1",
-            "readdirp": "2.1.0"
-          }
-        },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-          "dev": true,
-          "requires": {
-            "is-posix-bracket": "0.1.1"
-          }
-        },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        },
-        "glob-parent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-          "dev": true,
-          "requires": {
-            "is-glob": "2.0.1"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        },
-        "lodash": {
-          "version": "3.10.1",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
-          "dev": true
-        },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "dev": true,
-          "requires": {
-            "arr-diff": "2.0.0",
-            "array-unique": "0.2.1",
-            "braces": "1.8.5",
-            "expand-brackets": "0.1.5",
-            "extglob": "0.3.2",
-            "filename-regex": "2.0.1",
-            "is-extglob": "1.0.0",
-            "is-glob": "2.0.1",
-            "kind-of": "3.2.2",
-            "normalize-path": "2.1.1",
-            "object.omit": "2.0.1",
-            "parse-glob": "3.0.4",
-            "regex-cache": "0.4.4"
-          }
-        }
-      }
-    },
-    "karma-chrome-launcher": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
-      "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
-      "dev": true,
-      "requires": {
-        "fs-access": "1.0.1",
-        "which": "1.3.1"
-      }
-    },
-    "karma-coverage-istanbul-reporter": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.1.tgz",
-      "integrity": "sha512-UcgrHkFehI5+ivMouD8NH/UOHiX4oCAtwaANylzPFdcAuD52fnCUuelacq2gh8tZ4ydhU3+xiXofSq7j5Ehygw==",
-      "dev": true,
-      "requires": {
-        "istanbul-api": "1.3.1",
-        "minimatch": "3.0.4"
-      }
-    },
-    "karma-jasmine": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz",
-      "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=",
-      "dev": true
-    },
-    "karma-jasmine-html-reporter": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz",
-      "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=",
-      "dev": true,
-      "requires": {
-        "karma-jasmine": "1.1.2"
-      }
-    },
-    "karma-source-map-support": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz",
-      "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==",
-      "dev": true,
-      "requires": {
-        "source-map-support": "0.5.6"
-      }
-    },
-    "killable": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
-      "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=",
-      "dev": true
-    },
-    "kind-of": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-      "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-      "dev": true
-    },
-    "lazy-cache": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
-      "dev": true,
-      "optional": true
-    },
-    "lcid": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
-      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
-      "dev": true,
-      "requires": {
-        "invert-kv": "1.0.0"
-      }
-    },
-    "leb": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/leb/-/leb-0.3.0.tgz",
-      "integrity": "sha1-Mr7p+tFoMo1q6oUi2DP0GA7tHaM=",
-      "dev": true
-    },
-    "less": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz",
-      "integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==",
-      "dev": true,
-      "requires": {
-        "errno": "0.1.7",
-        "graceful-fs": "4.1.11",
-        "image-size": "0.5.5",
-        "mime": "1.6.0",
-        "mkdirp": "0.5.1",
-        "promise": "7.3.1",
-        "request": "2.87.0",
-        "source-map": "0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "less-loader": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
-      "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
-      "dev": true,
-      "requires": {
-        "clone": "2.1.1",
-        "loader-utils": "1.1.0",
-        "pify": "3.0.0"
-      }
-    },
-    "levn": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2"
-      }
-    },
-    "license-webpack-plugin": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.3.1.tgz",
-      "integrity": "sha512-NqAFodJdpBUuf1iD+Ij8hQvF0rCFKlO2KaieoQzAPhFgzLCtJnC7Z7x5gQbGNjoe++wOKAtAmwVEIBLqq2Yp1A==",
-      "dev": true,
-      "requires": {
-        "ejs": "2.6.1"
-      }
-    },
-    "lie": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
-      "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
-      "dev": true,
-      "requires": {
-        "immediate": "3.0.6"
-      }
-    },
-    "load-json-file": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "4.1.11",
-        "parse-json": "2.2.0",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1",
-        "strip-bom": "2.0.0"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-          "dev": true
-        }
-      }
-    },
-    "loader-runner": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
-      "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=",
-      "dev": true
-    },
-    "loader-utils": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
-      "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
-      "dev": true,
-      "requires": {
-        "big.js": "3.2.0",
-        "emojis-list": "2.1.0",
-        "json5": "0.5.1"
-      }
-    },
-    "locate-path": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-      "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
-      "dev": true,
-      "requires": {
-        "p-locate": "2.0.0",
-        "path-exists": "3.0.0"
-      }
-    },
-    "lodash": {
-      "version": "4.17.10",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
-      "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
-      "dev": true
-    },
-    "lodash.assign": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
-      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
-      "dev": true,
-      "optional": true
-    },
-    "lodash.clonedeep": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
-      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
-      "dev": true
-    },
-    "lodash.mergewith": {
-      "version": "4.6.1",
-      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
-      "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
-      "dev": true,
-      "optional": true
-    },
-    "lodash.tail": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
-      "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
-      "dev": true
-    },
-    "log-symbols": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
-      "dev": true,
-      "requires": {
-        "chalk": "2.2.2"
-      }
-    },
-    "log4js": {
-      "version": "0.6.38",
-      "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
-      "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
-      "dev": true,
-      "requires": {
-        "readable-stream": "1.0.34",
-        "semver": "4.3.6"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "1.0.34",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-          "dev": true,
-          "requires": {
-            "core-util-is": "1.0.2",
-            "inherits": "2.0.3",
-            "isarray": "0.0.1",
-            "string_decoder": "0.10.31"
-          }
-        },
-        "semver": {
-          "version": "4.3.6",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
-          "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
-          "dev": true
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        }
-      }
-    },
-    "loglevel": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
-      "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
-      "dev": true
-    },
-    "loglevelnext": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz",
-      "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==",
-      "dev": true,
-      "requires": {
-        "es6-symbol": "3.1.1",
-        "object.assign": "4.1.0"
-      }
-    },
-    "long": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
-      "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
-      "dev": true
-    },
-    "longest": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
-      "dev": true
-    },
-    "loose-envify": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
-      "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
-      "dev": true,
-      "requires": {
-        "js-tokens": "3.0.2"
-      }
-    },
-    "loud-rejection": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
-      "dev": true,
-      "requires": {
-        "currently-unhandled": "0.4.1",
-        "signal-exit": "3.0.2"
-      }
-    },
-    "lower-case": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
-      "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
-      "dev": true
-    },
-    "lru-cache": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
-      "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
-      "dev": true,
-      "requires": {
-        "pseudomap": "1.0.2",
-        "yallist": "2.1.2"
-      }
-    },
-    "make-dir": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
-      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
-      "dev": true,
-      "requires": {
-        "pify": "3.0.0"
-      }
-    },
-    "make-error": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz",
-      "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
-      "dev": true
-    },
-    "map-cache": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
-      "dev": true
-    },
-    "map-obj": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
-      "dev": true
-    },
-    "map-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
-      "dev": true,
-      "requires": {
-        "object-visit": "1.0.1"
-      }
-    },
-    "math-random": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
-      "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
-      "dev": true
-    },
-    "md5.js": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
-      "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
-      "dev": true,
-      "requires": {
-        "hash-base": "3.0.4",
-        "inherits": "2.0.3"
-      }
-    },
-    "media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
-      "dev": true
-    },
-    "mem": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
-      "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
-      "dev": true,
-      "requires": {
-        "mimic-fn": "1.2.0"
-      }
-    },
-    "memory-fs": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-      "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
-      "dev": true,
-      "requires": {
-        "errno": "0.1.7",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "meow": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
-      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
-      "dev": true,
-      "requires": {
-        "camelcase-keys": "2.1.0",
-        "decamelize": "1.2.0",
-        "loud-rejection": "1.6.0",
-        "map-obj": "1.0.1",
-        "minimist": "1.2.0",
-        "normalize-package-data": "2.4.0",
-        "object-assign": "4.1.1",
-        "read-pkg-up": "1.0.1",
-        "redent": "1.0.0",
-        "trim-newlines": "1.0.0"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
-      "dev": true
-    },
-    "methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
-      "dev": true
-    },
-    "micromatch": {
-      "version": "3.1.10",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-      "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-      "dev": true,
-      "requires": {
-        "arr-diff": "4.0.0",
-        "array-unique": "0.3.2",
-        "braces": "2.3.2",
-        "define-property": "2.0.2",
-        "extend-shallow": "3.0.2",
-        "extglob": "2.0.4",
-        "fragment-cache": "0.2.1",
-        "kind-of": "6.0.2",
-        "nanomatch": "1.2.9",
-        "object.pick": "1.3.0",
-        "regex-not": "1.0.2",
-        "snapdragon": "0.8.2",
-        "to-regex": "3.0.2"
-      }
-    },
-    "miller-rabin": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
-      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "brorand": "1.1.0"
-      }
-    },
-    "mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "dev": true
-    },
-    "mime-db": {
-      "version": "1.33.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
-      "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
-      "dev": true
-    },
-    "mime-types": {
-      "version": "2.1.18",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
-      "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
-      "dev": true,
-      "requires": {
-        "mime-db": "1.33.0"
-      }
-    },
-    "mimic-fn": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-      "dev": true
-    },
-    "mini-css-extract-plugin": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.0.tgz",
-      "integrity": "sha512-2Zik6PhUZ/MbiboG6SDS9UTPL4XXy4qnyGjSdCIWRrr8xb6PwLtHE+AYOjkXJWdF0OG8vo/yrJ8CgS5WbMpzIg==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "webpack-sources": "1.1.0"
-      }
-    },
-    "minimalistic-assert": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
-      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
-      "dev": true
-    },
-    "minimalistic-crypto-utils": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
-      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
-      "dev": true
-    },
-    "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-      "dev": true,
-      "requires": {
-        "brace-expansion": "1.1.11"
-      }
-    },
-    "minimist": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
-      "dev": true
-    },
-    "mississippi": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
-      "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
-      "dev": true,
-      "requires": {
-        "concat-stream": "1.6.2",
-        "duplexify": "3.6.0",
-        "end-of-stream": "1.4.1",
-        "flush-write-stream": "1.0.3",
-        "from2": "2.3.0",
-        "parallel-transform": "1.1.0",
-        "pump": "2.0.1",
-        "pumpify": "1.5.1",
-        "stream-each": "1.2.2",
-        "through2": "2.0.3"
-      }
-    },
-    "mixin-deep": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
-      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
-      "dev": true,
-      "requires": {
-        "for-in": "1.0.2",
-        "is-extendable": "1.0.1"
-      },
-      "dependencies": {
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "2.0.4"
-          }
-        }
-      }
-    },
-    "mixin-object": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
-      "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
-      "dev": true,
-      "requires": {
-        "for-in": "0.1.8",
-        "is-extendable": "0.1.1"
-      },
-      "dependencies": {
-        "for-in": {
-          "version": "0.1.8",
-          "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
-          "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=",
-          "dev": true
-        }
-      }
-    },
-    "mkdirp": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-      "dev": true,
-      "requires": {
-        "minimist": "0.0.8"
-      }
-    },
-    "moment": {
-      "version": "2.22.2",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
-      "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y="
-    },
-    "moment-timezone": {
-      "version": "0.5.21",
-      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz",
-      "integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==",
-      "requires": {
-        "moment": "2.22.2"
-      }
-    },
-    "move-concurrently": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
-      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
-      "dev": true,
-      "requires": {
-        "aproba": "1.2.0",
-        "copy-concurrently": "1.0.5",
-        "fs-write-stream-atomic": "1.0.10",
-        "mkdirp": "0.5.1",
-        "rimraf": "2.6.2",
-        "run-queue": "1.0.3"
-      }
-    },
-    "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-      "dev": true
-    },
-    "multicast-dns": {
-      "version": "6.2.3",
-      "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
-      "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
-      "dev": true,
-      "requires": {
-        "dns-packet": "1.3.1",
-        "thunky": "1.0.2"
-      }
-    },
-    "multicast-dns-service-types": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
-      "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
-      "dev": true
-    },
-    "nan": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
-      "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
-      "dev": true,
-      "optional": true
-    },
-    "nanomatch": {
-      "version": "1.2.9",
-      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz",
-      "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==",
-      "dev": true,
-      "requires": {
-        "arr-diff": "4.0.0",
-        "array-unique": "0.3.2",
-        "define-property": "2.0.2",
-        "extend-shallow": "3.0.2",
-        "fragment-cache": "0.2.1",
-        "is-odd": "2.0.0",
-        "is-windows": "1.0.2",
-        "kind-of": "6.0.2",
-        "object.pick": "1.3.0",
-        "regex-not": "1.0.2",
-        "snapdragon": "0.8.2",
-        "to-regex": "3.0.2"
-      }
-    },
-    "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
-      "dev": true
-    },
-    "neo-async": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz",
-      "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==",
-      "dev": true
-    },
-    "next-tick": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
-      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
-      "dev": true
-    },
-    "no-case": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
-      "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
-      "dev": true,
-      "requires": {
-        "lower-case": "1.1.4"
-      }
-    },
-    "node-forge": {
-      "version": "0.7.5",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
-      "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
-      "dev": true
-    },
-    "node-gyp": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.7.0.tgz",
-      "integrity": "sha512-qDQE/Ft9xXP6zphwx4sD0t+VhwV7yFaloMpfbL2QnnDZcyaiakWlLdtFGGQfTAwpFHdpbRhRxVhIHN1OKAjgbg==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "fstream": "1.0.11",
-        "glob": "7.1.2",
-        "graceful-fs": "4.1.11",
-        "mkdirp": "0.5.1",
-        "nopt": "3.0.6",
-        "npmlog": "4.1.2",
-        "osenv": "0.1.5",
-        "request": "2.81.0",
-        "rimraf": "2.6.2",
-        "semver": "5.3.0",
-        "tar": "2.2.1",
-        "which": "1.3.1"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "4.11.8",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
-          "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "co": "4.6.0",
-            "json-stable-stringify": "1.0.1"
-          }
-        },
-        "assert-plus": {
-          "version": "0.2.0",
-          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
-          "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
-          "dev": true,
-          "optional": true
-        },
-        "aws-sign2": {
-          "version": "0.6.0",
-          "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
-          "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
-          "dev": true,
-          "optional": true
-        },
-        "form-data": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
-          "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "asynckit": "0.4.0",
-            "combined-stream": "1.0.6",
-            "mime-types": "2.1.18"
-          }
-        },
-        "har-schema": {
-          "version": "1.0.5",
-          "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
-          "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
-          "dev": true,
-          "optional": true
-        },
-        "har-validator": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
-          "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ajv": "4.11.8",
-            "har-schema": "1.0.5"
-          }
-        },
-        "http-signature": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
-          "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "assert-plus": "0.2.0",
-            "jsprim": "1.4.1",
-            "sshpk": "1.14.2"
-          }
-        },
-        "performance-now": {
-          "version": "0.2.0",
-          "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
-          "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
-          "dev": true,
-          "optional": true
-        },
-        "qs": {
-          "version": "6.4.0",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
-          "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
-          "dev": true,
-          "optional": true
-        },
-        "request": {
-          "version": "2.81.0",
-          "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
-          "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "aws-sign2": "0.6.0",
-            "aws4": "1.7.0",
-            "caseless": "0.12.0",
-            "combined-stream": "1.0.6",
-            "extend": "3.0.1",
-            "forever-agent": "0.6.1",
-            "form-data": "2.1.4",
-            "har-validator": "4.2.1",
-            "hawk": "3.1.3",
-            "http-signature": "1.1.1",
-            "is-typedarray": "1.0.0",
-            "isstream": "0.1.2",
-            "json-stringify-safe": "5.0.1",
-            "mime-types": "2.1.18",
-            "oauth-sign": "0.8.2",
-            "performance-now": "0.2.0",
-            "qs": "6.4.0",
-            "safe-buffer": "5.1.2",
-            "stringstream": "0.0.6",
-            "tough-cookie": "2.3.4",
-            "tunnel-agent": "0.6.0",
-            "uuid": "3.2.1"
-          }
-        },
-        "semver": {
-          "version": "5.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
-          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "node-libs-browser": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
-      "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
-      "dev": true,
-      "requires": {
-        "assert": "1.4.1",
-        "browserify-zlib": "0.2.0",
-        "buffer": "4.9.1",
-        "console-browserify": "1.1.0",
-        "constants-browserify": "1.0.0",
-        "crypto-browserify": "3.12.0",
-        "domain-browser": "1.2.0",
-        "events": "1.1.1",
-        "https-browserify": "1.0.0",
-        "os-browserify": "0.3.0",
-        "path-browserify": "0.0.0",
-        "process": "0.11.10",
-        "punycode": "1.4.1",
-        "querystring-es3": "0.2.1",
-        "readable-stream": "2.3.6",
-        "stream-browserify": "2.0.1",
-        "stream-http": "2.8.3",
-        "string_decoder": "1.1.1",
-        "timers-browserify": "2.0.10",
-        "tty-browserify": "0.0.0",
-        "url": "0.11.0",
-        "util": "0.10.4",
-        "vm-browserify": "0.0.4"
-      },
-      "dependencies": {
-        "punycode": {
-          "version": "1.4.1",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
-          "dev": true
-        }
-      }
-    },
-    "node-sass": {
-      "version": "4.9.0",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz",
-      "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "async-foreach": "0.1.3",
-        "chalk": "1.1.3",
-        "cross-spawn": "3.0.1",
-        "gaze": "1.1.3",
-        "get-stdin": "4.0.1",
-        "glob": "7.1.2",
-        "in-publish": "2.0.0",
-        "lodash.assign": "4.2.0",
-        "lodash.clonedeep": "4.5.0",
-        "lodash.mergewith": "4.6.1",
-        "meow": "3.7.0",
-        "mkdirp": "0.5.1",
-        "nan": "2.10.0",
-        "node-gyp": "3.7.0",
-        "npmlog": "4.1.2",
-        "request": "2.79.0",
-        "sass-graph": "2.2.4",
-        "stdout-stream": "1.4.0",
-        "true-case-path": "1.0.2"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true
-        },
-        "assert-plus": {
-          "version": "0.2.0",
-          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
-          "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
-          "dev": true,
-          "optional": true
-        },
-        "aws-sign2": {
-          "version": "0.6.0",
-          "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
-          "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
-          "dev": true,
-          "optional": true
-        },
-        "caseless": {
-          "version": "0.11.0",
-          "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
-          "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
-          "dev": true,
-          "optional": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        },
-        "form-data": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
-          "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "asynckit": "0.4.0",
-            "combined-stream": "1.0.6",
-            "mime-types": "2.1.18"
-          }
-        },
-        "har-validator": {
-          "version": "2.0.6",
-          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
-          "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chalk": "1.1.3",
-            "commander": "2.15.1",
-            "is-my-json-valid": "2.17.2",
-            "pinkie-promise": "2.0.1"
-          }
-        },
-        "http-signature": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
-          "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "assert-plus": "0.2.0",
-            "jsprim": "1.4.1",
-            "sshpk": "1.14.2"
-          }
-        },
-        "qs": {
-          "version": "6.3.2",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
-          "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=",
-          "dev": true,
-          "optional": true
-        },
-        "request": {
-          "version": "2.79.0",
-          "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
-          "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "aws-sign2": "0.6.0",
-            "aws4": "1.7.0",
-            "caseless": "0.11.0",
-            "combined-stream": "1.0.6",
-            "extend": "3.0.1",
-            "forever-agent": "0.6.1",
-            "form-data": "2.1.4",
-            "har-validator": "2.0.6",
-            "hawk": "3.1.3",
-            "http-signature": "1.1.1",
-            "is-typedarray": "1.0.0",
-            "isstream": "0.1.2",
-            "json-stringify-safe": "5.0.1",
-            "mime-types": "2.1.18",
-            "oauth-sign": "0.8.2",
-            "qs": "6.3.2",
-            "stringstream": "0.0.6",
-            "tough-cookie": "2.3.4",
-            "tunnel-agent": "0.4.3",
-            "uuid": "3.2.1"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true
-        },
-        "tunnel-agent": {
-          "version": "0.4.3",
-          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
-          "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "nopt": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
-      "dev": true,
-      "requires": {
-        "abbrev": "1.0.9"
-      }
-    },
-    "normalize-package-data": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
-      "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
-      "dev": true,
-      "requires": {
-        "hosted-git-info": "2.6.0",
-        "is-builtin-module": "1.0.0",
-        "semver": "5.5.0",
-        "validate-npm-package-license": "3.0.3"
-      }
-    },
-    "normalize-path": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
-      "dev": true,
-      "requires": {
-        "remove-trailing-separator": "1.1.0"
-      }
-    },
-    "normalize-range": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
-      "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
-      "dev": true
-    },
-    "npm-package-arg": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
-      "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
-      "dev": true,
-      "requires": {
-        "hosted-git-info": "2.6.0",
-        "osenv": "0.1.5",
-        "semver": "5.5.0",
-        "validate-npm-package-name": "3.0.0"
-      }
-    },
-    "npm-registry-client": {
-      "version": "8.5.1",
-      "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.5.1.tgz",
-      "integrity": "sha512-7rjGF2eA7hKDidGyEWmHTiKfXkbrcQAsGL/Rh4Rt3x3YNRNHhwaTzVJfW3aNvvlhg4G62VCluif0sLCb/i51Hg==",
-      "dev": true,
-      "requires": {
-        "concat-stream": "1.6.2",
-        "graceful-fs": "4.1.11",
-        "normalize-package-data": "2.4.0",
-        "npm-package-arg": "6.1.0",
-        "npmlog": "4.1.2",
-        "once": "1.4.0",
-        "request": "2.87.0",
-        "retry": "0.10.1",
-        "safe-buffer": "5.1.2",
-        "semver": "5.5.0",
-        "slide": "1.1.6",
-        "ssri": "5.3.0"
-      }
-    },
-    "npm-run-path": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
-      "dev": true,
-      "requires": {
-        "path-key": "2.0.1"
-      }
-    },
-    "npmlog": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-      "dev": true,
-      "requires": {
-        "are-we-there-yet": "1.1.5",
-        "console-control-strings": "1.1.0",
-        "gauge": "2.7.4",
-        "set-blocking": "2.0.0"
-      }
-    },
-    "nth-check": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
-      "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
-      "dev": true,
-      "requires": {
-        "boolbase": "1.0.0"
-      }
-    },
-    "null-check": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
-      "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
-      "dev": true
-    },
-    "num2fraction": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
-      "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
-      "dev": true
-    },
-    "number-is-nan": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
-      "dev": true
-    },
-    "oauth-sign": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
-      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
-      "dev": true
-    },
-    "object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true
-    },
-    "object-component": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
-      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
-      "dev": true
-    },
-    "object-copy": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
-      "dev": true,
-      "requires": {
-        "copy-descriptor": "0.1.1",
-        "define-property": "0.2.5",
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "object-keys": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
-      "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
-      "dev": true
-    },
-    "object-visit": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
-      "dev": true,
-      "requires": {
-        "isobject": "3.0.1"
-      }
-    },
-    "object.assign": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
-      "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2",
-        "function-bind": "1.1.1",
-        "has-symbols": "1.0.0",
-        "object-keys": "1.0.11"
-      }
-    },
-    "object.getownpropertydescriptors": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
-      "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2",
-        "es-abstract": "1.12.0"
-      }
-    },
-    "object.omit": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
-      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
-      "dev": true,
-      "requires": {
-        "for-own": "0.1.5",
-        "is-extendable": "0.1.1"
-      },
-      "dependencies": {
-        "for-own": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
-          "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
-          "dev": true,
-          "requires": {
-            "for-in": "1.0.2"
-          }
-        }
-      }
-    },
-    "object.pick": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
-      "dev": true,
-      "requires": {
-        "isobject": "3.0.1"
-      }
-    },
-    "obuf": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
-      "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
-      "dev": true
-    },
-    "on-finished": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
-      "dev": true,
-      "requires": {
-        "ee-first": "1.1.1"
-      }
-    },
-    "on-headers": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
-      "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
-      "dev": true
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true,
-      "requires": {
-        "wrappy": "1.0.2"
-      }
-    },
-    "opn": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
-      "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
-      "dev": true,
-      "requires": {
-        "is-wsl": "1.1.0"
-      }
-    },
-    "optimist": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
-      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
-      "dev": true,
-      "requires": {
-        "minimist": "0.0.8",
-        "wordwrap": "0.0.3"
-      },
-      "dependencies": {
-        "wordwrap": {
-          "version": "0.0.3",
-          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
-          "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
-          "dev": true
-        }
-      }
-    },
-    "optionator": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
-      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
-      "dev": true,
-      "requires": {
-        "deep-is": "0.1.3",
-        "fast-levenshtein": "2.0.6",
-        "levn": "0.3.0",
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2",
-        "wordwrap": "1.0.0"
-      }
-    },
-    "options": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
-      "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=",
-      "dev": true
-    },
-    "original": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz",
-      "integrity": "sha512-IEvtB5vM5ULvwnqMxWBLxkS13JIEXbakizMSo3yoPNPCIWzg8TG3Usn/UhXoZFM/m+FuEA20KdzPSFq/0rS+UA==",
-      "dev": true,
-      "requires": {
-        "url-parse": "1.4.1"
-      }
-    },
-    "os-browserify": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
-      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
-      "dev": true
-    },
-    "os-homedir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-      "dev": true
-    },
-    "os-locale": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
-      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "lcid": "1.0.0"
-      }
-    },
-    "os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-      "dev": true
-    },
-    "osenv": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
-      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-      "dev": true,
-      "requires": {
-        "os-homedir": "1.0.2",
-        "os-tmpdir": "1.0.2"
-      }
-    },
-    "p-finally": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
-      "dev": true
-    },
-    "p-limit": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-      "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-      "dev": true,
-      "requires": {
-        "p-try": "1.0.0"
-      }
-    },
-    "p-locate": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-      "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
-      "dev": true,
-      "requires": {
-        "p-limit": "1.3.0"
-      }
-    },
-    "p-map": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
-      "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
-      "dev": true
-    },
-    "p-try": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-      "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-      "dev": true
-    },
-    "pako": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
-      "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
-      "dev": true
-    },
-    "parallel-transform": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
-      "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
-      "dev": true,
-      "requires": {
-        "cyclist": "0.2.2",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "param-case": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
-      "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
-      "dev": true,
-      "requires": {
-        "no-case": "2.3.2"
-      }
-    },
-    "parse-asn1": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
-      "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
-      "dev": true,
-      "requires": {
-        "asn1.js": "4.10.1",
-        "browserify-aes": "1.2.0",
-        "create-hash": "1.2.0",
-        "evp_bytestokey": "1.0.3",
-        "pbkdf2": "3.0.16"
-      }
-    },
-    "parse-glob": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
-      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
-      "dev": true,
-      "requires": {
-        "glob-base": "0.3.0",
-        "is-dotfile": "1.0.3",
-        "is-extglob": "1.0.0",
-        "is-glob": "2.0.1"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
-        }
-      }
-    },
-    "parse-json": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
-      "dev": true,
-      "requires": {
-        "error-ex": "1.3.1"
-      }
-    },
-    "parse5": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
-      "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
-      "dev": true
-    },
-    "parsejson": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz",
-      "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=",
-      "dev": true,
-      "requires": {
-        "better-assert": "1.0.2"
-      }
-    },
-    "parseqs": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
-      "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
-      "dev": true,
-      "requires": {
-        "better-assert": "1.0.2"
-      }
-    },
-    "parseuri": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
-      "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
-      "dev": true,
-      "requires": {
-        "better-assert": "1.0.2"
-      }
-    },
-    "parseurl": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
-      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
-      "dev": true
-    },
-    "pascalcase": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
-      "dev": true
-    },
-    "path-browserify": {
-      "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
-      "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
-      "dev": true
-    },
-    "path-dirname": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
-      "dev": true
-    },
-    "path-exists": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
-      "dev": true
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "dev": true
-    },
-    "path-is-inside": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
-      "dev": true
-    },
-    "path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-      "dev": true
-    },
-    "path-parse": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
-      "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
-      "dev": true
-    },
-    "path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
-      "dev": true
-    },
-    "path-type": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-      "dev": true,
-      "requires": {
-        "pify": "3.0.0"
-      }
-    },
-    "pbkdf2": {
-      "version": "3.0.16",
-      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
-      "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==",
-      "dev": true,
-      "requires": {
-        "create-hash": "1.2.0",
-        "create-hmac": "1.1.7",
-        "ripemd160": "2.0.2",
-        "safe-buffer": "5.1.2",
-        "sha.js": "2.4.11"
-      }
-    },
-    "performance-now": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
-      "dev": true
-    },
-    "pify": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-      "dev": true
-    },
-    "pinkie": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
-      "dev": true
-    },
-    "pinkie-promise": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
-      "dev": true,
-      "requires": {
-        "pinkie": "2.0.4"
-      }
-    },
-    "pkg-dir": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
-      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
-      "dev": true,
-      "requires": {
-        "find-up": "2.1.0"
-      }
-    },
-    "portfinder": {
-      "version": "1.0.13",
-      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
-      "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
-      "dev": true,
-      "requires": {
-        "async": "1.5.2",
-        "debug": "2.6.9",
-        "mkdirp": "0.5.1"
-      }
-    },
-    "posix-character-classes": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
-      "dev": true
-    },
-    "postcss": {
-      "version": "6.0.22",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz",
-      "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==",
-      "dev": true,
-      "requires": {
-        "chalk": "2.4.1",
-        "source-map": "0.6.1",
-        "supports-color": "5.4.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "2.4.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
-          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "3.2.1",
-            "escape-string-regexp": "1.0.5",
-            "supports-color": "5.4.0"
-          }
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "postcss-import": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
-      "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==",
-      "dev": true,
-      "requires": {
-        "postcss": "6.0.22",
-        "postcss-value-parser": "3.3.0",
-        "read-cache": "1.0.0",
-        "resolve": "1.7.1"
-      }
-    },
-    "postcss-load-config": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
-      "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
-      "dev": true,
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1",
-        "postcss-load-options": "1.2.0",
-        "postcss-load-plugins": "2.3.0"
-      }
-    },
-    "postcss-load-options": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
-      "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
-      "dev": true,
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1"
-      }
-    },
-    "postcss-load-plugins": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
-      "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
-      "dev": true,
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1"
-      }
-    },
-    "postcss-loader": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.5.tgz",
-      "integrity": "sha512-pV7kB5neJ0/1tZ8L1uGOBNTVBCSCXQoIsZMsrwvO8V2rKGa2tBl/f80GGVxow2jJnRJ2w1ocx693EKhZAb9Isg==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "postcss": "6.0.22",
-        "postcss-load-config": "1.2.0",
-        "schema-utils": "0.4.5"
-      }
-    },
-    "postcss-url": {
-      "version": "7.3.2",
-      "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.2.tgz",
-      "integrity": "sha512-QMV5mA+pCYZQcUEPQkmor9vcPQ2MT+Ipuu8qdi1gVxbNiIiErEGft+eny1ak19qALoBkccS5AHaCaCDzh7b9MA==",
-      "dev": true,
-      "requires": {
-        "mime": "1.6.0",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.1",
-        "postcss": "6.0.22",
-        "xxhashjs": "0.2.2"
-      }
-    },
-    "postcss-value-parser": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
-      "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
-      "dev": true
-    },
-    "prelude-ls": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
-      "dev": true
-    },
-    "preserve": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
-      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
-      "dev": true
-    },
-    "pretty-error": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz",
-      "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=",
-      "dev": true,
-      "requires": {
-        "renderkid": "2.0.1",
-        "utila": "0.4.0"
-      }
-    },
-    "process": {
-      "version": "0.11.10",
-      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
-      "dev": true
-    },
-    "process-nextick-args": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
-      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
-      "dev": true
-    },
-    "promise": {
-      "version": "7.3.1",
-      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
-      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "asap": "2.0.6"
-      }
-    },
-    "promise-inflight": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
-      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
-      "dev": true
-    },
-    "protractor": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.3.2.tgz",
-      "integrity": "sha512-pw4uwwiy5lHZjIguxNpkEwJJa7hVz+bJsvaTI+IbXlfn2qXwzbF8eghW/RmrZwE2sGx82I8etb8lVjQ+JrjejA==",
-      "dev": true,
-      "requires": {
-        "@types/node": "6.0.113",
-        "@types/q": "0.0.32",
-        "@types/selenium-webdriver": "2.53.43",
-        "blocking-proxy": "1.0.1",
-        "chalk": "1.1.3",
-        "glob": "7.1.2",
-        "jasmine": "2.8.0",
-        "jasminewd2": "2.2.0",
-        "optimist": "0.6.1",
-        "q": "1.4.1",
-        "saucelabs": "1.5.0",
-        "selenium-webdriver": "3.6.0",
-        "source-map-support": "0.4.18",
-        "webdriver-js-extender": "1.0.0",
-        "webdriver-manager": "12.0.6"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "6.0.113",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.113.tgz",
-          "integrity": "sha512-f9XXUWFqryzjkZA1EqFvJHSFyqyasV17fq8zCDIzbRV4ctL7RrJGKvG+lcex86Rjbzd1GrER9h9VmF5sSjV0BQ==",
-          "dev": true
-        },
-        "adm-zip": {
-          "version": "0.4.11",
-          "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
-          "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        },
-        "del": {
-          "version": "2.2.2",
-          "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
-          "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
-          "dev": true,
-          "requires": {
-            "globby": "5.0.0",
-            "is-path-cwd": "1.0.0",
-            "is-path-in-cwd": "1.0.1",
-            "object-assign": "4.1.1",
-            "pify": "2.3.0",
-            "pinkie-promise": "2.0.1",
-            "rimraf": "2.6.2"
-          }
-        },
-        "globby": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
-          "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
-          "dev": true,
-          "requires": {
-            "array-union": "1.0.2",
-            "arrify": "1.0.1",
-            "glob": "7.1.2",
-            "object-assign": "4.1.1",
-            "pify": "2.3.0",
-            "pinkie-promise": "2.0.1"
-          }
-        },
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        },
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-          "dev": true
-        },
-        "source-map-support": {
-          "version": "0.4.18",
-          "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
-          "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
-          "dev": true,
-          "requires": {
-            "source-map": "0.5.7"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true
-        },
-        "webdriver-manager": {
-          "version": "12.0.6",
-          "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.0.6.tgz",
-          "integrity": "sha1-PfGkgZdwELTL+MnYXHpXeCjA5ws=",
-          "dev": true,
-          "requires": {
-            "adm-zip": "0.4.11",
-            "chalk": "1.1.3",
-            "del": "2.2.2",
-            "glob": "7.1.2",
-            "ini": "1.3.5",
-            "minimist": "1.2.0",
-            "q": "1.4.1",
-            "request": "2.87.0",
-            "rimraf": "2.6.2",
-            "semver": "5.5.0",
-            "xml2js": "0.4.19"
-          }
-        }
-      }
-    },
-    "proxy-addr": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
-      "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
-      "dev": true,
-      "requires": {
-        "forwarded": "0.1.2",
-        "ipaddr.js": "1.6.0"
-      }
-    },
-    "prr": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
-      "dev": true
-    },
-    "pseudomap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
-      "dev": true
-    },
-    "public-encrypt": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
-      "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "browserify-rsa": "4.0.1",
-        "create-hash": "1.2.0",
-        "parse-asn1": "5.1.1",
-        "randombytes": "2.0.6"
-      }
-    },
-    "pump": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
-      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
-      "dev": true,
-      "requires": {
-        "end-of-stream": "1.4.1",
-        "once": "1.4.0"
-      }
-    },
-    "pumpify": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
-      "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
-      "dev": true,
-      "requires": {
-        "duplexify": "3.6.0",
-        "inherits": "2.0.3",
-        "pump": "2.0.1"
-      }
-    },
-    "punycode": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-      "dev": true
-    },
-    "q": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
-      "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
-      "dev": true
-    },
-    "qjobs": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
-      "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
-      "dev": true
-    },
-    "qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
-      "dev": true
-    },
-    "querystring": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
-      "dev": true
-    },
-    "querystring-es3": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
-      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
-      "dev": true
-    },
-    "querystringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz",
-      "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
-      "dev": true
-    },
-    "randomatic": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz",
-      "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==",
-      "dev": true,
-      "requires": {
-        "is-number": "4.0.0",
-        "kind-of": "6.0.2",
-        "math-random": "1.0.1"
-      },
-      "dependencies": {
-        "is-number": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
-          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
-          "dev": true
-        }
-      }
-    },
-    "randombytes": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
-      "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "randomfill": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
-      "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
-      "dev": true,
-      "requires": {
-        "randombytes": "2.0.6",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "range-parser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
-      "dev": true
-    },
-    "raw-body": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
-      "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
-      "dev": true,
-      "requires": {
-        "bytes": "3.0.0",
-        "http-errors": "1.6.2",
-        "iconv-lite": "0.4.19",
-        "unpipe": "1.0.0"
-      },
-      "dependencies": {
-        "depd": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
-          "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
-          "dev": true
-        },
-        "http-errors": {
-          "version": "1.6.2",
-          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
-          "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
-          "dev": true,
-          "requires": {
-            "depd": "1.1.1",
-            "inherits": "2.0.3",
-            "setprototypeof": "1.0.3",
-            "statuses": "1.4.0"
-          }
-        },
-        "setprototypeof": {
-          "version": "1.0.3",
-          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
-          "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
-          "dev": true
-        }
-      }
-    },
-    "raw-loader": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
-      "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
-      "dev": true
-    },
-    "read-cache": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
-      "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
-      "dev": true,
-      "requires": {
-        "pify": "2.3.0"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-          "dev": true
-        }
-      }
-    },
-    "read-pkg": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
-      "dev": true,
-      "requires": {
-        "load-json-file": "1.1.0",
-        "normalize-package-data": "2.4.0",
-        "path-type": "1.1.0"
-      },
-      "dependencies": {
-        "path-type": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-          "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
-          "dev": true,
-          "requires": {
-            "graceful-fs": "4.1.11",
-            "pify": "2.3.0",
-            "pinkie-promise": "2.0.1"
-          }
-        },
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-          "dev": true
-        }
-      }
-    },
-    "read-pkg-up": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
-      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
-      "dev": true,
-      "requires": {
-        "find-up": "1.1.2",
-        "read-pkg": "1.1.0"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
-          "dev": true,
-          "requires": {
-            "path-exists": "2.1.0",
-            "pinkie-promise": "2.0.1"
-          }
-        },
-        "path-exists": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
-          "dev": true,
-          "requires": {
-            "pinkie-promise": "2.0.1"
-          }
-        }
-      }
-    },
-    "readable-stream": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-      "dev": true,
-      "requires": {
-        "core-util-is": "1.0.2",
-        "inherits": "2.0.3",
-        "isarray": "1.0.0",
-        "process-nextick-args": "2.0.0",
-        "safe-buffer": "5.1.2",
-        "string_decoder": "1.1.1",
-        "util-deprecate": "1.0.2"
-      }
-    },
-    "readdirp": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
-      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "4.1.11",
-        "minimatch": "3.0.4",
-        "readable-stream": "2.3.6",
-        "set-immediate-shim": "1.0.1"
-      }
-    },
-    "redent": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
-      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
-      "dev": true,
-      "requires": {
-        "indent-string": "2.1.0",
-        "strip-indent": "1.0.1"
-      }
-    },
-    "reflect-metadata": {
-      "version": "0.1.12",
-      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
-      "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==",
-      "dev": true
-    },
-    "regenerate": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
-      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
-      "dev": true
-    },
-    "regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
-      "dev": true
-    },
-    "regex-cache": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
-      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
-      "dev": true,
-      "requires": {
-        "is-equal-shallow": "0.1.3"
-      }
-    },
-    "regex-not": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
-      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "3.0.2",
-        "safe-regex": "1.1.0"
-      }
-    },
-    "regexpu-core": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
-      "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
-      "dev": true,
-      "requires": {
-        "regenerate": "1.4.0",
-        "regjsgen": "0.2.0",
-        "regjsparser": "0.1.5"
-      }
-    },
-    "regjsgen": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
-      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
-      "dev": true
-    },
-    "regjsparser": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
-      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
-      "dev": true,
-      "requires": {
-        "jsesc": "0.5.0"
-      },
-      "dependencies": {
-        "jsesc": {
-          "version": "0.5.0",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
-          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
-          "dev": true
-        }
-      }
-    },
-    "relateurl": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-      "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
-      "dev": true
-    },
-    "remove-trailing-separator": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
-      "dev": true
-    },
-    "renderkid": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz",
-      "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=",
-      "dev": true,
-      "requires": {
-        "css-select": "1.2.0",
-        "dom-converter": "0.1.4",
-        "htmlparser2": "3.3.0",
-        "strip-ansi": "3.0.1",
-        "utila": "0.3.3"
-      },
-      "dependencies": {
-        "utila": {
-          "version": "0.3.3",
-          "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
-          "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
-          "dev": true
-        }
-      }
-    },
-    "repeat-element": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
-      "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
-      "dev": true
-    },
-    "repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
-      "dev": true
-    },
-    "repeating": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
-      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
-      "dev": true,
-      "requires": {
-        "is-finite": "1.0.2"
-      }
-    },
-    "request": {
-      "version": "2.87.0",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
-      "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
-      "dev": true,
-      "requires": {
-        "aws-sign2": "0.7.0",
-        "aws4": "1.7.0",
-        "caseless": "0.12.0",
-        "combined-stream": "1.0.6",
-        "extend": "3.0.1",
-        "forever-agent": "0.6.1",
-        "form-data": "2.3.2",
-        "har-validator": "5.0.3",
-        "http-signature": "1.2.0",
-        "is-typedarray": "1.0.0",
-        "isstream": "0.1.2",
-        "json-stringify-safe": "5.0.1",
-        "mime-types": "2.1.18",
-        "oauth-sign": "0.8.2",
-        "performance-now": "2.1.0",
-        "qs": "6.5.2",
-        "safe-buffer": "5.1.2",
-        "tough-cookie": "2.3.4",
-        "tunnel-agent": "0.6.0",
-        "uuid": "3.2.1"
-      }
-    },
-    "require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
-      "dev": true
-    },
-    "require-from-string": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
-      "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=",
-      "dev": true
-    },
-    "require-main-filename": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
-      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
-      "dev": true
-    },
-    "requires-port": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
-      "dev": true
-    },
-    "resolve": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
-      "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
-      "dev": true,
-      "requires": {
-        "path-parse": "1.0.5"
-      }
-    },
-    "resolve-cwd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-      "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
-      "dev": true,
-      "requires": {
-        "resolve-from": "3.0.0"
-      }
-    },
-    "resolve-from": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-      "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
-      "dev": true
-    },
-    "resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
-      "dev": true
-    },
-    "ret": {
-      "version": "0.1.15",
-      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
-      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
-      "dev": true
-    },
-    "retry": {
-      "version": "0.10.1",
-      "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
-      "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
-      "dev": true
-    },
-    "right-align": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "align-text": "0.1.4"
-      }
-    },
-    "rimraf": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
-      "dev": true,
-      "requires": {
-        "glob": "7.1.2"
-      }
-    },
-    "ripemd160": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
-      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
-      "dev": true,
-      "requires": {
-        "hash-base": "3.0.4",
-        "inherits": "2.0.3"
-      }
-    },
-    "run-queue": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
-      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
-      "dev": true,
-      "requires": {
-        "aproba": "1.2.0"
-      }
-    },
-    "rxjs": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz",
-      "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==",
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
-    },
-    "safe-regex": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
-      "dev": true,
-      "requires": {
-        "ret": "0.1.15"
-      }
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
-    },
-    "sass-graph": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
-      "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "glob": "7.1.2",
-        "lodash": "4.17.10",
-        "scss-tokenizer": "0.2.3",
-        "yargs": "7.1.0"
-      },
-      "dependencies": {
-        "camelcase": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
-          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
-          "dev": true,
-          "optional": true
-        },
-        "cliui": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
-          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "string-width": "1.0.2",
-            "strip-ansi": "3.0.1",
-            "wrap-ansi": "2.1.0"
-          }
-        },
-        "y18n": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
-          "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
-          "dev": true,
-          "optional": true
-        },
-        "yargs": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
-          "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "camelcase": "3.0.0",
-            "cliui": "3.2.0",
-            "decamelize": "1.2.0",
-            "get-caller-file": "1.0.2",
-            "os-locale": "1.4.0",
-            "read-pkg-up": "1.0.1",
-            "require-directory": "2.1.1",
-            "require-main-filename": "1.0.1",
-            "set-blocking": "2.0.0",
-            "string-width": "1.0.2",
-            "which-module": "1.0.0",
-            "y18n": "3.2.1",
-            "yargs-parser": "5.0.0"
-          }
-        }
-      }
-    },
-    "sass-loader": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.0.3.tgz",
-      "integrity": "sha512-iaSFtQcGo4SSgDw5Aes5p4VTrA5jCGSA7sGmhPIcOloBlgI1VktM2MUrk2IHHjbNagckXlPz+HWq1vAAPrcYxA==",
-      "dev": true,
-      "requires": {
-        "clone-deep": "2.0.2",
-        "loader-utils": "1.1.0",
-        "lodash.tail": "4.1.1",
-        "neo-async": "2.5.1",
-        "pify": "3.0.0"
-      }
-    },
-    "saucelabs": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
-      "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
-      "dev": true,
-      "requires": {
-        "https-proxy-agent": "2.2.1"
-      }
-    },
-    "sax": {
-      "version": "0.5.8",
-      "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
-      "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
-      "dev": true
-    },
-    "schema-utils": {
-      "version": "0.4.5",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz",
-      "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==",
-      "dev": true,
-      "requires": {
-        "ajv": "6.4.0",
-        "ajv-keywords": "3.2.0"
-      }
-    },
-    "scss-tokenizer": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
-      "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "js-base64": "2.4.5",
-        "source-map": "0.4.4"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "amdefine": "1.0.1"
-          }
-        }
-      }
-    },
-    "select-hose": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-      "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
-      "dev": true
-    },
-    "selenium-webdriver": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
-      "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
-      "dev": true,
-      "requires": {
-        "jszip": "3.1.5",
-        "rimraf": "2.6.2",
-        "tmp": "0.0.30",
-        "xml2js": "0.4.19"
-      },
-      "dependencies": {
-        "tmp": {
-          "version": "0.0.30",
-          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
-          "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
-          "dev": true,
-          "requires": {
-            "os-tmpdir": "1.0.2"
-          }
-        }
-      }
-    },
-    "selfsigned": {
-      "version": "1.10.3",
-      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.3.tgz",
-      "integrity": "sha512-vmZenZ+8Al3NLHkWnhBQ0x6BkML1eCP2xEi3JE+f3D9wW9fipD9NNJHYtE9XJM4TsPaHGZJIamrSI6MTg1dU2Q==",
-      "dev": true,
-      "requires": {
-        "node-forge": "0.7.5"
-      }
-    },
-    "semver": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
-      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
-      "dev": true
-    },
-    "semver-dsl": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
-      "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
-      "dev": true,
-      "requires": {
-        "semver": "5.5.0"
-      }
-    },
-    "semver-intersect": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.1.tgz",
-      "integrity": "sha1-j6hKnhAovSOeRTDRo+GB5pjYhLo=",
-      "dev": true,
-      "requires": {
-        "semver": "5.5.0"
-      }
-    },
-    "send": {
-      "version": "0.16.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
-      "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "depd": "1.1.2",
-        "destroy": "1.0.4",
-        "encodeurl": "1.0.2",
-        "escape-html": "1.0.3",
-        "etag": "1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "1.6.3",
-        "mime": "1.4.1",
-        "ms": "2.0.0",
-        "on-finished": "2.3.0",
-        "range-parser": "1.2.0",
-        "statuses": "1.4.0"
-      },
-      "dependencies": {
-        "mime": {
-          "version": "1.4.1",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
-          "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
-          "dev": true
-        }
-      }
-    },
-    "serialize-javascript": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
-      "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==",
-      "dev": true
-    },
-    "serve-index": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-      "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
-      "dev": true,
-      "requires": {
-        "accepts": "1.3.5",
-        "batch": "0.6.1",
-        "debug": "2.6.9",
-        "escape-html": "1.0.3",
-        "http-errors": "1.6.3",
-        "mime-types": "2.1.18",
-        "parseurl": "1.3.2"
-      }
-    },
-    "serve-static": {
-      "version": "1.13.2",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
-      "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
-      "dev": true,
-      "requires": {
-        "encodeurl": "1.0.2",
-        "escape-html": "1.0.3",
-        "parseurl": "1.3.2",
-        "send": "0.16.2"
-      }
-    },
-    "set-blocking": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
-      "dev": true
-    },
-    "set-immediate-shim": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
-      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
-      "dev": true
-    },
-    "set-value": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
-      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "2.0.1",
-        "is-extendable": "0.1.1",
-        "is-plain-object": "2.0.4",
-        "split-string": "3.1.0"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        }
-      }
-    },
-    "setimmediate": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
-      "dev": true
-    },
-    "setprototypeof": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
-      "dev": true
-    },
-    "sha.js": {
-      "version": "2.4.11",
-      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
-      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "shallow-clone": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
-      "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
-      "dev": true,
-      "requires": {
-        "is-extendable": "0.1.1",
-        "kind-of": "5.1.0",
-        "mixin-object": "2.0.1"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
-        }
-      }
-    },
-    "shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
-      "dev": true,
-      "requires": {
-        "shebang-regex": "1.0.0"
-      }
-    },
-    "shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-      "dev": true
-    },
-    "signal-exit": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
-      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
-      "dev": true
-    },
-    "silent-error": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/silent-error/-/silent-error-1.1.0.tgz",
-      "integrity": "sha1-IglwbxyFCp8dENDYQJGLRvJuG8k=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9"
-      }
-    },
-    "slash": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
-      "dev": true
-    },
-    "slide": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
-      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
-      "dev": true
-    },
-    "snapdragon": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
-      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
-      "dev": true,
-      "requires": {
-        "base": "0.11.2",
-        "debug": "2.6.9",
-        "define-property": "0.2.5",
-        "extend-shallow": "2.0.1",
-        "map-cache": "0.2.2",
-        "source-map": "0.5.7",
-        "source-map-resolve": "0.5.2",
-        "use": "3.1.0"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        },
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        }
-      }
-    },
-    "snapdragon-node": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
-      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
-      "dev": true,
-      "requires": {
-        "define-property": "1.0.0",
-        "isobject": "3.0.1",
-        "snapdragon-util": "3.0.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "1.0.2"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "1.0.0",
-            "is-data-descriptor": "1.0.0",
-            "kind-of": "6.0.2"
-          }
-        }
-      }
-    },
-    "snapdragon-util": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
-      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "sntp": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
-      "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
-      "dev": true,
-      "requires": {
-        "hoek": "2.16.3"
-      }
-    },
-    "socket.io": {
-      "version": "1.7.3",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz",
-      "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=",
-      "dev": true,
-      "requires": {
-        "debug": "2.3.3",
-        "engine.io": "1.8.3",
-        "has-binary": "0.1.7",
-        "object-assign": "4.1.0",
-        "socket.io-adapter": "0.5.0",
-        "socket.io-client": "1.7.3",
-        "socket.io-parser": "2.3.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
-          "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.2"
-          }
-        },
-        "ms": {
-          "version": "0.7.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-          "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
-          "dev": true
-        },
-        "object-assign": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
-          "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=",
-          "dev": true
-        }
-      }
-    },
-    "socket.io-adapter": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz",
-      "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=",
-      "dev": true,
-      "requires": {
-        "debug": "2.3.3",
-        "socket.io-parser": "2.3.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
-          "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.2"
-          }
-        },
-        "ms": {
-          "version": "0.7.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-          "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
-          "dev": true
-        }
-      }
-    },
-    "socket.io-client": {
-      "version": "1.7.3",
-      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz",
-      "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=",
-      "dev": true,
-      "requires": {
-        "backo2": "1.0.2",
-        "component-bind": "1.0.0",
-        "component-emitter": "1.2.1",
-        "debug": "2.3.3",
-        "engine.io-client": "1.8.3",
-        "has-binary": "0.1.7",
-        "indexof": "0.0.1",
-        "object-component": "0.0.3",
-        "parseuri": "0.0.5",
-        "socket.io-parser": "2.3.1",
-        "to-array": "0.1.4"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
-          "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.2"
-          }
-        },
-        "ms": {
-          "version": "0.7.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-          "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
-          "dev": true
-        }
-      }
-    },
-    "socket.io-parser": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz",
-      "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=",
-      "dev": true,
-      "requires": {
-        "component-emitter": "1.1.2",
-        "debug": "2.2.0",
-        "isarray": "0.0.1",
-        "json3": "3.3.2"
-      },
-      "dependencies": {
-        "component-emitter": {
-          "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
-          "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=",
-          "dev": true
-        },
-        "debug": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
-          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
-          "dev": true,
-          "requires": {
-            "ms": "0.7.1"
-          }
-        },
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "ms": {
-          "version": "0.7.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
-          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
-          "dev": true
-        }
-      }
-    },
-    "sockjs": {
-      "version": "0.3.19",
-      "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
-      "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
-      "dev": true,
-      "requires": {
-        "faye-websocket": "0.10.0",
-        "uuid": "3.2.1"
-      }
-    },
-    "sockjs-client": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
-      "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "eventsource": "0.1.6",
-        "faye-websocket": "0.11.1",
-        "inherits": "2.0.3",
-        "json3": "3.3.2",
-        "url-parse": "1.4.1"
-      },
-      "dependencies": {
-        "faye-websocket": {
-          "version": "0.11.1",
-          "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
-          "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
-          "dev": true,
-          "requires": {
-            "websocket-driver": "0.7.0"
-          }
-        }
-      }
-    },
-    "source-list-map": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
-      "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
-      "dev": true
-    },
-    "source-map": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-      "dev": true
-    },
-    "source-map-resolve": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
-      "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
-      "dev": true,
-      "requires": {
-        "atob": "2.1.1",
-        "decode-uri-component": "0.2.0",
-        "resolve-url": "0.2.1",
-        "source-map-url": "0.4.0",
-        "urix": "0.1.0"
-      }
-    },
-    "source-map-support": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz",
-      "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==",
-      "dev": true,
-      "requires": {
-        "buffer-from": "1.1.0",
-        "source-map": "0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "source-map-url": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
-      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
-      "dev": true
-    },
-    "spdx-correct": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
-      "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
-      "dev": true,
-      "requires": {
-        "spdx-expression-parse": "3.0.0",
-        "spdx-license-ids": "3.0.0"
-      }
-    },
-    "spdx-exceptions": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
-      "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
-      "dev": true
-    },
-    "spdx-expression-parse": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
-      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
-      "dev": true,
-      "requires": {
-        "spdx-exceptions": "2.1.0",
-        "spdx-license-ids": "3.0.0"
-      }
-    },
-    "spdx-license-ids": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
-      "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
-      "dev": true
-    },
-    "spdy": {
-      "version": "3.4.7",
-      "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
-      "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "handle-thing": "1.2.5",
-        "http-deceiver": "1.2.7",
-        "safe-buffer": "5.1.2",
-        "select-hose": "2.0.0",
-        "spdy-transport": "2.1.0"
-      }
-    },
-    "spdy-transport": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz",
-      "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "detect-node": "2.0.3",
-        "hpack.js": "2.1.6",
-        "obuf": "1.1.2",
-        "readable-stream": "2.3.6",
-        "safe-buffer": "5.1.2",
-        "wbuf": "1.7.3"
-      }
-    },
-    "split-string": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
-      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "3.0.2"
-      }
-    },
-    "sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-      "dev": true
-    },
-    "sshpk": {
-      "version": "1.14.2",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
-      "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
-      "dev": true,
-      "requires": {
-        "asn1": "0.2.3",
-        "assert-plus": "1.0.0",
-        "bcrypt-pbkdf": "1.0.1",
-        "dashdash": "1.14.1",
-        "ecc-jsbn": "0.1.1",
-        "getpass": "0.1.7",
-        "jsbn": "0.1.1",
-        "safer-buffer": "2.1.2",
-        "tweetnacl": "0.14.5"
-      }
-    },
-    "ssri": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
-      "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "static-extend": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
-      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
-      "dev": true,
-      "requires": {
-        "define-property": "0.2.5",
-        "object-copy": "0.1.0"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        }
-      }
-    },
-    "stats-webpack-plugin": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.6.2.tgz",
-      "integrity": "sha1-LFlJtTHgf4eojm6k3PrFOqjHWis=",
-      "dev": true,
-      "requires": {
-        "lodash": "4.17.10"
-      }
-    },
-    "statuses": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-      "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
-      "dev": true
-    },
-    "stdout-stream": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz",
-      "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "readable-stream": "2.3.6"
-      }
-    },
-    "stream-browserify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
-      "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "stream-each": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz",
-      "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
-      "dev": true,
-      "requires": {
-        "end-of-stream": "1.4.1",
-        "stream-shift": "1.0.0"
-      }
-    },
-    "stream-http": {
-      "version": "2.8.3",
-      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
-      "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
-      "dev": true,
-      "requires": {
-        "builtin-status-codes": "3.0.0",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6",
-        "to-arraybuffer": "1.0.1",
-        "xtend": "4.0.1"
-      }
-    },
-    "stream-shift": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
-      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
-      "dev": true
-    },
-    "string-width": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-      "dev": true,
-      "requires": {
-        "code-point-at": "1.1.0",
-        "is-fullwidth-code-point": "1.0.0",
-        "strip-ansi": "3.0.1"
-      }
-    },
-    "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "stringstream": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
-      "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==",
-      "dev": true
-    },
-    "strip-ansi": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "2.1.1"
-      }
-    },
-    "strip-bom": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
-      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
-      "dev": true,
-      "requires": {
-        "is-utf8": "0.2.1"
-      }
-    },
-    "strip-eof": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
-      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
-      "dev": true
-    },
-    "strip-indent": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
-      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
-      "dev": true,
-      "requires": {
-        "get-stdin": "4.0.1"
-      }
-    },
-    "style-loader": {
-      "version": "0.21.0",
-      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz",
-      "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "schema-utils": "0.4.5"
-      }
-    },
-    "stylus": {
-      "version": "0.54.5",
-      "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
-      "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
-      "dev": true,
-      "requires": {
-        "css-parse": "1.7.0",
-        "debug": "2.6.9",
-        "glob": "7.0.6",
-        "mkdirp": "0.5.1",
-        "sax": "0.5.8",
-        "source-map": "0.1.43"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "7.0.6",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
-          "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "1.0.0",
-            "inflight": "1.0.6",
-            "inherits": "2.0.3",
-            "minimatch": "3.0.4",
-            "once": "1.4.0",
-            "path-is-absolute": "1.0.1"
-          }
-        },
-        "source-map": {
-          "version": "0.1.43",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
-          "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
-          "dev": true,
-          "requires": {
-            "amdefine": "1.0.1"
-          }
-        }
-      }
-    },
-    "stylus-loader": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
-      "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "lodash.clonedeep": "4.5.0",
-        "when": "3.6.4"
-      }
-    },
-    "supports-color": {
-      "version": "5.4.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
-      "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
-      "dev": true,
-      "requires": {
-        "has-flag": "3.0.0"
-      }
-    },
-    "symbol-observable": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
-      "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
-      "dev": true
-    },
-    "tapable": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz",
-      "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==",
-      "dev": true
-    },
-    "tar": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
-      "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "block-stream": "0.0.9",
-        "fstream": "1.0.11",
-        "inherits": "2.0.3"
-      }
-    },
-    "through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
-      "dev": true
-    },
-    "through2": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
-      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
-      "dev": true,
-      "requires": {
-        "readable-stream": "2.3.6",
-        "xtend": "4.0.1"
-      }
-    },
-    "thunky": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz",
-      "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=",
-      "dev": true
-    },
-    "timers-browserify": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
-      "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
-      "dev": true,
-      "requires": {
-        "setimmediate": "1.0.5"
-      }
-    },
-    "tmp": {
-      "version": "0.0.31",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
-      "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=",
-      "dev": true,
-      "requires": {
-        "os-tmpdir": "1.0.2"
-      }
-    },
-    "to-array": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
-      "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
-      "dev": true
-    },
-    "to-arraybuffer": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
-      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
-      "dev": true
-    },
-    "to-fast-properties": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
-      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
-      "dev": true
-    },
-    "to-object-path": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
-      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
-      "dev": true,
-      "requires": {
-        "kind-of": "3.2.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
-        }
-      }
-    },
-    "to-regex": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
-      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
-      "dev": true,
-      "requires": {
-        "define-property": "2.0.2",
-        "extend-shallow": "3.0.2",
-        "regex-not": "1.0.2",
-        "safe-regex": "1.1.0"
-      }
-    },
-    "to-regex-range": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
-      "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
-      "dev": true,
-      "requires": {
-        "is-number": "3.0.0",
-        "repeat-string": "1.6.1"
-      }
-    },
-    "toposort": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
-      "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
-      "dev": true
-    },
-    "tough-cookie": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
-      "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
-      "dev": true,
-      "requires": {
-        "punycode": "1.4.1"
-      },
-      "dependencies": {
-        "punycode": {
-          "version": "1.4.1",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
-          "dev": true
-        }
-      }
-    },
-    "tree-kill": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz",
-      "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==",
-      "dev": true
-    },
-    "trim-newlines": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
-      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
-      "dev": true
-    },
-    "trim-right": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
-      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
-      "dev": true
-    },
-    "true-case-path": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
-      "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "glob": "6.0.4"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "6.0.4",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
-          "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "inflight": "1.0.6",
-            "inherits": "2.0.3",
-            "minimatch": "3.0.4",
-            "once": "1.4.0",
-            "path-is-absolute": "1.0.1"
-          }
-        }
-      }
-    },
-    "ts-node": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz",
-      "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==",
-      "dev": true,
-      "requires": {
-        "arrify": "1.0.1",
-        "chalk": "2.4.1",
-        "diff": "3.5.0",
-        "make-error": "1.3.4",
-        "minimist": "1.2.0",
-        "mkdirp": "0.5.1",
-        "source-map-support": "0.5.6",
-        "yn": "2.0.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "2.4.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
-          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "3.2.1",
-            "escape-string-regexp": "1.0.5",
-            "supports-color": "5.4.0"
-          }
-        },
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "tsickle": {
-      "version": "0.29.0",
-      "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.29.0.tgz",
-      "integrity": "sha512-JpID0Lv8/irRtPmqJJxb5fCwfZhjZeKmav9Zna7UjqVuJoSbI49Wue/c2PPybX1SbRrjl7bbI/JsCl0dSUJygA==",
-      "dev": true,
-      "requires": {
-        "minimist": "1.2.0",
-        "mkdirp": "0.5.1",
-        "source-map": "0.6.1",
-        "source-map-support": "0.5.6"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "tslib": {
-      "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz",
-      "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw=="
-    },
-    "tslint": {
-      "version": "5.9.1",
-      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz",
-      "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=",
-      "dev": true,
-      "requires": {
-        "babel-code-frame": "6.26.0",
-        "builtin-modules": "1.1.1",
-        "chalk": "2.4.1",
-        "commander": "2.15.1",
-        "diff": "3.5.0",
-        "glob": "7.1.2",
-        "js-yaml": "3.12.0",
-        "minimatch": "3.0.4",
-        "resolve": "1.7.1",
-        "semver": "5.5.0",
-        "tslib": "1.9.2",
-        "tsutils": "2.29.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "2.4.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
-          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "3.2.1",
-            "escape-string-regexp": "1.0.5",
-            "supports-color": "5.4.0"
-          }
-        }
-      }
-    },
-    "tsutils": {
-      "version": "2.29.0",
-      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-      "dev": true,
-      "requires": {
-        "tslib": "1.9.2"
-      }
-    },
-    "tty-browserify": {
-      "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
-      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
-      "dev": true
-    },
-    "tunnel-agent": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.2"
-      }
-    },
-    "tweetnacl": {
-      "version": "0.14.5",
-      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-      "dev": true,
-      "optional": true
-    },
-    "type-check": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
-      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "1.1.2"
-      }
-    },
-    "type-is": {
-      "version": "1.6.16",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
-      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
-      "dev": true,
-      "requires": {
-        "media-typer": "0.3.0",
-        "mime-types": "2.1.18"
-      }
-    },
-    "typedarray": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
-      "dev": true
-    },
-    "typescript": {
-      "version": "2.7.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz",
-      "integrity": "sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw==",
-      "dev": true
-    },
-    "uglify-js": {
-      "version": "3.3.28",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz",
-      "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==",
-      "dev": true,
-      "requires": {
-        "commander": "2.15.1",
-        "source-map": "0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "uglify-to-browserify": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
-      "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
-      "dev": true,
-      "optional": true
-    },
-    "uglifyjs-webpack-plugin": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz",
-      "integrity": "sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==",
-      "dev": true,
-      "requires": {
-        "cacache": "10.0.4",
-        "find-cache-dir": "1.0.0",
-        "schema-utils": "0.4.5",
-        "serialize-javascript": "1.5.0",
-        "source-map": "0.6.1",
-        "uglify-es": "3.3.9",
-        "webpack-sources": "1.1.0",
-        "worker-farm": "1.6.0"
-      },
-      "dependencies": {
-        "commander": {
-          "version": "2.13.0",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
-          "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
-          "dev": true
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        },
-        "uglify-es": {
-          "version": "3.3.9",
-          "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
-          "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
-          "dev": true,
-          "requires": {
-            "commander": "2.13.0",
-            "source-map": "0.6.1"
-          }
-        }
-      }
-    },
-    "ultron": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
-      "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=",
-      "dev": true
-    },
-    "union-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
-      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
-      "dev": true,
-      "requires": {
-        "arr-union": "3.1.0",
-        "get-value": "2.0.6",
-        "is-extendable": "0.1.1",
-        "set-value": "0.4.3"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        },
-        "set-value": {
-          "version": "0.4.3",
-          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
-          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "2.0.1",
-            "is-extendable": "0.1.1",
-            "is-plain-object": "2.0.4",
-            "to-object-path": "0.3.0"
-          }
-        }
-      }
-    },
-    "unique-filename": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz",
-      "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=",
-      "dev": true,
-      "requires": {
-        "unique-slug": "2.0.0"
-      }
-    },
-    "unique-slug": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
-      "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
-      "dev": true,
-      "requires": {
-        "imurmurhash": "0.1.4"
-      }
-    },
-    "unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
-      "dev": true
-    },
-    "unset-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
-      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
-      "dev": true,
-      "requires": {
-        "has-value": "0.3.1",
-        "isobject": "3.0.1"
-      },
-      "dependencies": {
-        "has-value": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
-          "dev": true,
-          "requires": {
-            "get-value": "2.0.6",
-            "has-values": "0.1.4",
-            "isobject": "2.1.0"
-          },
-          "dependencies": {
-            "isobject": {
-              "version": "2.1.0",
-              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-              "dev": true,
-              "requires": {
-                "isarray": "1.0.0"
-              }
-            }
-          }
-        },
-        "has-values": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
-          "dev": true
-        }
-      }
-    },
-    "upath": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
-      "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
-      "dev": true
-    },
-    "upper-case": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
-      "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
-      "dev": true
-    },
-    "uri-js": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz",
-      "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=",
-      "dev": true,
-      "requires": {
-        "punycode": "2.1.1"
-      }
-    },
-    "urix": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
-      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
-      "dev": true
-    },
-    "url": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
-      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
-      "dev": true,
-      "requires": {
-        "punycode": "1.3.2",
-        "querystring": "0.2.0"
-      },
-      "dependencies": {
-        "punycode": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
-          "dev": true
-        }
-      }
-    },
-    "url-join": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz",
-      "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=",
-      "dev": true
-    },
-    "url-loader": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.0.1.tgz",
-      "integrity": "sha512-rAonpHy7231fmweBKUFe0bYnlGDty77E+fm53NZdij7j/YOpyGzc7ttqG1nAXl3aRs0k41o0PC3TvGXQiw2Zvw==",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "mime": "2.3.1",
-        "schema-utils": "0.4.5"
-      },
-      "dependencies": {
-        "mime": {
-          "version": "2.3.1",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
-          "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
-          "dev": true
-        }
-      }
-    },
-    "url-parse": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.1.tgz",
-      "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==",
-      "dev": true,
-      "requires": {
-        "querystringify": "2.0.0",
-        "requires-port": "1.0.0"
-      }
-    },
-    "use": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
-      "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==",
-      "dev": true,
-      "requires": {
-        "kind-of": "6.0.2"
-      }
-    },
-    "useragent": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
-      "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
-      "dev": true,
-      "requires": {
-        "lru-cache": "4.1.3",
-        "tmp": "0.0.31"
-      }
-    },
-    "util": {
-      "version": "0.10.4",
-      "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
-      "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3"
-      }
-    },
-    "util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-      "dev": true
-    },
-    "util.promisify": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
-      "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2",
-        "object.getownpropertydescriptors": "2.0.3"
-      }
-    },
-    "utila": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
-      "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
-      "dev": true
-    },
-    "utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
-      "dev": true
-    },
-    "uuid": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
-      "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
-      "dev": true
-    },
-    "validate-npm-package-license": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
-      "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
-      "dev": true,
-      "requires": {
-        "spdx-correct": "3.0.0",
-        "spdx-expression-parse": "3.0.0"
-      }
-    },
-    "validate-npm-package-name": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
-      "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
-      "dev": true,
-      "requires": {
-        "builtins": "1.0.3"
-      }
-    },
-    "vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
-      "dev": true
-    },
-    "verror": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0",
-        "core-util-is": "1.0.2",
-        "extsprintf": "1.3.0"
-      }
-    },
-    "vm-browserify": {
-      "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
-      "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
-      "dev": true,
-      "requires": {
-        "indexof": "0.0.1"
-      }
-    },
-    "void-elements": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
-      "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
-      "dev": true
-    },
-    "watchpack": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
-      "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
-      "dev": true,
-      "requires": {
-        "chokidar": "2.0.3",
-        "graceful-fs": "4.1.11",
-        "neo-async": "2.5.1"
-      }
-    },
-    "wbuf": {
-      "version": "1.7.3",
-      "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
-      "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
-      "dev": true,
-      "requires": {
-        "minimalistic-assert": "1.0.1"
-      }
-    },
-    "webassemblyjs": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/webassemblyjs/-/webassemblyjs-1.4.3.tgz",
-      "integrity": "sha512-4lOV1Lv6olz0PJkDGQEp82HempAn147e6BXijWDzz9g7/2nSebVP9GVg62Fz5ZAs55mxq13GA0XLyvY8XkyDjg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/validation": "1.4.3",
-        "@webassemblyjs/wasm-parser": "1.4.3",
-        "@webassemblyjs/wast-parser": "1.4.3",
-        "long": "3.2.0"
-      }
-    },
-    "webdriver-js-extender": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz",
-      "integrity": "sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=",
-      "dev": true,
-      "requires": {
-        "@types/selenium-webdriver": "2.53.43",
-        "selenium-webdriver": "2.53.3"
-      },
-      "dependencies": {
-        "sax": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz",
-          "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=",
-          "dev": true
-        },
-        "selenium-webdriver": {
-          "version": "2.53.3",
-          "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
-          "integrity": "sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=",
-          "dev": true,
-          "requires": {
-            "adm-zip": "0.4.4",
-            "rimraf": "2.6.2",
-            "tmp": "0.0.24",
-            "ws": "1.1.2",
-            "xml2js": "0.4.4"
-          }
-        },
-        "tmp": {
-          "version": "0.0.24",
-          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz",
-          "integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=",
-          "dev": true
-        },
-        "xml2js": {
-          "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
-          "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=",
-          "dev": true,
-          "requires": {
-            "sax": "0.6.1",
-            "xmlbuilder": "9.0.7"
-          }
-        }
-      }
-    },
-    "webpack": {
-      "version": "4.8.3",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.8.3.tgz",
-      "integrity": "sha512-/hfAjBISycdK597lxONjKEFX7dSIU1PsYwC3XlXUXoykWBlv9QV5HnO+ql3HvrrgfBJ7WXdnjO9iGPR2aAc5sw==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.4.3",
-        "@webassemblyjs/wasm-edit": "1.4.3",
-        "@webassemblyjs/wasm-parser": "1.4.3",
-        "acorn": "5.6.2",
-        "acorn-dynamic-import": "3.0.0",
-        "ajv": "6.4.0",
-        "ajv-keywords": "3.2.0",
-        "chrome-trace-event": "0.1.3",
-        "enhanced-resolve": "4.0.0",
-        "eslint-scope": "3.7.1",
-        "loader-runner": "2.3.0",
-        "loader-utils": "1.1.0",
-        "memory-fs": "0.4.1",
-        "micromatch": "3.1.10",
-        "mkdirp": "0.5.1",
-        "neo-async": "2.5.1",
-        "node-libs-browser": "2.1.0",
-        "schema-utils": "0.4.5",
-        "tapable": "1.0.0",
-        "uglifyjs-webpack-plugin": "1.2.5",
-        "watchpack": "1.6.0",
-        "webpack-sources": "1.1.0"
-      }
-    },
-    "webpack-core": {
-      "version": "0.6.9",
-      "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
-      "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
-      "dev": true,
-      "requires": {
-        "source-list-map": "0.1.8",
-        "source-map": "0.4.4"
-      },
-      "dependencies": {
-        "source-list-map": {
-          "version": "0.1.8",
-          "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
-          "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=",
-          "dev": true
-        },
-        "source-map": {
-          "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
-          "dev": true,
-          "requires": {
-            "amdefine": "1.0.1"
-          }
-        }
-      }
-    },
-    "webpack-dev-middleware": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz",
-      "integrity": "sha512-I6Mmy/QjWU/kXwCSFGaiOoL5YEQIVmbb0o45xMoCyQAg/mClqZVTcsX327sPfekDyJWpCxb+04whNyLOIxpJdQ==",
-      "dev": true,
-      "requires": {
-        "loud-rejection": "1.6.0",
-        "memory-fs": "0.4.1",
-        "mime": "2.3.1",
-        "path-is-absolute": "1.0.1",
-        "range-parser": "1.2.0",
-        "url-join": "4.0.0",
-        "webpack-log": "1.2.0"
-      },
-      "dependencies": {
-        "mime": {
-          "version": "2.3.1",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
-          "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
-          "dev": true
-        }
-      }
-    },
-    "webpack-dev-server": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.4.tgz",
-      "integrity": "sha512-itcIUDFkHuj1/QQxzUFOEXXmxOj5bku2ScLEsOFPapnq2JRTm58gPdtnBphBJOKL2+M3p6+xygL64bI+3eyzzw==",
-      "dev": true,
-      "requires": {
-        "ansi-html": "0.0.7",
-        "array-includes": "3.0.3",
-        "bonjour": "3.5.0",
-        "chokidar": "2.0.3",
-        "compression": "1.7.2",
-        "connect-history-api-fallback": "1.5.0",
-        "debug": "3.1.0",
-        "del": "3.0.0",
-        "express": "4.16.3",
-        "html-entities": "1.2.1",
-        "http-proxy-middleware": "0.18.0",
-        "import-local": "1.0.0",
-        "internal-ip": "1.2.0",
-        "ip": "1.1.5",
-        "killable": "1.0.0",
-        "loglevel": "1.6.1",
-        "opn": "5.3.0",
-        "portfinder": "1.0.13",
-        "selfsigned": "1.10.3",
-        "serve-index": "1.9.1",
-        "sockjs": "0.3.19",
-        "sockjs-client": "1.1.4",
-        "spdy": "3.4.7",
-        "strip-ansi": "3.0.1",
-        "supports-color": "5.4.0",
-        "webpack-dev-middleware": "3.1.3",
-        "webpack-log": "1.2.0",
-        "yargs": "11.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "camelcase": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-          "dev": true
-        },
-        "cliui": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
-          "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
-          "dev": true,
-          "requires": {
-            "string-width": "2.1.1",
-            "strip-ansi": "4.0.0",
-            "wrap-ansi": "2.1.0"
-          },
-          "dependencies": {
-            "strip-ansi": {
-              "version": "4.0.0",
-              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-              "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-              "dev": true,
-              "requires": {
-                "ansi-regex": "3.0.0"
-              }
-            }
-          }
-        },
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "is-fullwidth-code-point": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-          "dev": true
-        },
-        "os-locale": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
-          "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
-          "dev": true,
-          "requires": {
-            "execa": "0.7.0",
-            "lcid": "1.0.0",
-            "mem": "1.1.0"
-          }
-        },
-        "string-width": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-          "dev": true,
-          "requires": {
-            "is-fullwidth-code-point": "2.0.0",
-            "strip-ansi": "4.0.0"
-          },
-          "dependencies": {
-            "strip-ansi": {
-              "version": "4.0.0",
-              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-              "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-              "dev": true,
-              "requires": {
-                "ansi-regex": "3.0.0"
-              }
-            }
-          }
-        },
-        "which-module": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
-          "dev": true
-        },
-        "y18n": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
-          "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
-          "dev": true
-        },
-        "yargs": {
-          "version": "11.0.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz",
-          "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==",
-          "dev": true,
-          "requires": {
-            "cliui": "4.1.0",
-            "decamelize": "1.2.0",
-            "find-up": "2.1.0",
-            "get-caller-file": "1.0.2",
-            "os-locale": "2.1.0",
-            "require-directory": "2.1.1",
-            "require-main-filename": "1.0.1",
-            "set-blocking": "2.0.0",
-            "string-width": "2.1.1",
-            "which-module": "2.0.0",
-            "y18n": "3.2.1",
-            "yargs-parser": "9.0.2"
-          }
-        },
-        "yargs-parser": {
-          "version": "9.0.2",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
-          "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
-          "dev": true,
-          "requires": {
-            "camelcase": "4.1.0"
-          }
-        }
-      }
-    },
-    "webpack-log": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz",
-      "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==",
-      "dev": true,
-      "requires": {
-        "chalk": "2.2.2",
-        "log-symbols": "2.2.0",
-        "loglevelnext": "1.0.5",
-        "uuid": "3.2.1"
-      }
-    },
-    "webpack-merge": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.3.tgz",
-      "integrity": "sha512-zxwAIGK7nKdu5CIZL0BjTQoq3elV0t0MfB7rUC1zj668geid52abs6hN/ACwZdK6LeMS8dC9B6WmtF978zH5mg==",
-      "dev": true,
-      "requires": {
-        "lodash": "4.17.10"
-      }
-    },
-    "webpack-sources": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
-      "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
-      "dev": true,
-      "requires": {
-        "source-list-map": "2.0.0",
-        "source-map": "0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "webpack-subresource-integrity": {
-      "version": "1.1.0-rc.4",
-      "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.4.tgz",
-      "integrity": "sha1-xcTj1pD50vZKlVDgeodn+Xlqpdg=",
-      "dev": true,
-      "requires": {
-        "webpack-core": "0.6.9"
-      }
-    },
-    "websocket-driver": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
-      "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
-      "dev": true,
-      "requires": {
-        "http-parser-js": "0.4.13",
-        "websocket-extensions": "0.1.3"
-      }
-    },
-    "websocket-extensions": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
-      "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
-      "dev": true
-    },
-    "when": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
-      "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
-      "dev": true
-    },
-    "which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "requires": {
-        "isexe": "2.0.0"
-      }
-    },
-    "which-module": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
-      "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
-      "dev": true,
-      "optional": true
-    },
-    "wide-align": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
-      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-      "dev": true,
-      "requires": {
-        "string-width": "1.0.2"
-      }
-    },
-    "window-size": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
-      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
-      "dev": true,
-      "optional": true
-    },
-    "wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
-      "dev": true
-    },
-    "worker-farm": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
-      "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
-      "dev": true,
-      "requires": {
-        "errno": "0.1.7"
-      }
-    },
-    "wrap-ansi": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
-      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
-      "dev": true,
-      "requires": {
-        "string-width": "1.0.2",
-        "strip-ansi": "3.0.1"
-      }
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "dev": true
-    },
-    "ws": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz",
-      "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=",
-      "dev": true,
-      "requires": {
-        "options": "0.0.6",
-        "ultron": "1.0.2"
-      }
-    },
-    "wtf-8": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz",
-      "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
-      "dev": true
-    },
-    "xml2js": {
-      "version": "0.4.19",
-      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
-      "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
-      "dev": true,
-      "requires": {
-        "sax": "1.2.4",
-        "xmlbuilder": "9.0.7"
-      },
-      "dependencies": {
-        "sax": {
-          "version": "1.2.4",
-          "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
-          "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
-          "dev": true
-        }
-      }
-    },
-    "xmlbuilder": {
-      "version": "9.0.7",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
-      "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
-      "dev": true
-    },
-    "xmlhttprequest-ssl": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz",
-      "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=",
-      "dev": true
-    },
-    "xtend": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
-      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
-      "dev": true
-    },
-    "xxhashjs": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz",
-      "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==",
-      "dev": true,
-      "requires": {
-        "cuint": "0.2.2"
-      }
-    },
-    "y18n": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-      "dev": true
-    },
-    "yallist": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
-      "dev": true
-    },
-    "yargs": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
-      "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "camelcase": "1.2.1",
-        "cliui": "2.1.0",
-        "decamelize": "1.2.0",
-        "window-size": "0.1.0"
-      }
-    },
-    "yargs-parser": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
-      "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "camelcase": "3.0.0"
-      },
-      "dependencies": {
-        "camelcase": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
-          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "yeast": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
-      "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
-      "dev": true
-    },
-    "yn": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
-      "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
-      "dev": true
-    },
-    "zone.js": {
-      "version": "0.8.26",
-      "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.26.tgz",
-      "integrity": "sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA=="
-    }
-  }
-}
diff --git a/gae/frontend/package.json b/gae/frontend/package.json
deleted file mode 100644
index 1511ee3..0000000
--- a/gae/frontend/package.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "name": "frontend",
-  "version": "0.0.0",
-  "scripts": {
-    "ng": "ng",
-    "start": "ng serve",
-    "build": "ng build",
-    "test": "ng test",
-    "lint": "ng lint",
-    "e2e": "ng e2e"
-  },
-  "private": true,
-  "dependencies": {
-    "@angular/animations": "^6.0.6",
-    "@angular/cdk": "^6.2.1",
-    "@angular/common": "^6.0.6",
-    "@angular/compiler": "^6.0.6",
-    "@angular/core": "^6.0.6",
-    "@angular/flex-layout": "^6.0.0-beta.16",
-    "@angular/forms": "^6.0.6",
-    "@angular/http": "^6.0.6",
-    "@angular/material": "^6.2.1",
-    "@angular/platform-browser": "^6.0.6",
-    "@angular/platform-browser-dynamic": "^6.0.6",
-    "@angular/router": "^6.0.6",
-    "core-js": "^2.5.4",
-    "moment": "^2.22.2",
-    "moment-timezone": "^0.5.21",
-    "rxjs": "^6.0.0",
-    "zone.js": "^0.8.26"
-  },
-  "devDependencies": {
-    "@angular-devkit/build-angular": "~0.6.8",
-    "@angular/cli": "~6.0.8",
-    "@angular/compiler-cli": "^6.0.6",
-    "@angular/language-service": "^6.0.6",
-    "@types/jasmine": "~2.8.6",
-    "@types/jasminewd2": "~2.0.3",
-    "@types/node": "~8.9.4",
-    "codelyzer": "~4.2.1",
-    "jasmine-core": "~2.99.1",
-    "jasmine-spec-reporter": "~4.2.1",
-    "karma": "~1.7.1",
-    "karma-chrome-launcher": "~2.2.0",
-    "karma-coverage-istanbul-reporter": "~2.0.0",
-    "karma-jasmine": "~1.1.1",
-    "karma-jasmine-html-reporter": "^0.2.2",
-    "protractor": "~5.3.0",
-    "ts-node": "~5.0.1",
-    "tslint": "^5.9.1",
-    "typescript": "^2.7.2"
-  }
-}
diff --git a/gae/frontend/src/app/app.component.html b/gae/frontend/src/app/app.component.html
deleted file mode 100644
index 8f21391..0000000
--- a/gae/frontend/src/app/app.component.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<header>
-  <div>
-    <app-nav-bar id="nav-bar"></app-nav-bar>
-  </div>
-</header>
-<mat-sidenav-container>
-  <mat-sidenav-content>
-    <router-outlet id="router-outlet"></router-outlet>
-  </mat-sidenav-content>
-  <mat-sidenav #sidenav mode="over" position="end" [(opened)]="sideNavOpened">
-    <button mat-button (click)="sidenav.toggle()">
-      <mat-icon>clear</mat-icon>
-    </button>
-    <mat-list>
-      <mat-list-item *ngFor="let property of selectedEntity">
-        <h4 id="property-name" mat-line>{{property.name}}</h4>
-        <p id="property-value" mat-line *ngFor="let each of property.value">{{each}}</p>
-      </mat-list-item>
-    </mat-list>
-  </mat-sidenav>
-</mat-sidenav-container>
diff --git a/gae/frontend/src/app/app.component.scss b/gae/frontend/src/app/app.component.scss
deleted file mode 100644
index d818d0e..0000000
--- a/gae/frontend/src/app/app.component.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-mat-sidenav {
-  width: 400px;
-  padding: 30px 10px;
-}
-
-#property-name {
-  color: rgba(0, 0, 0, 0.66);
-  font-size: 12px;
-  margin-bottom: 2px;
-}
-
-#property-value {
-  font-size: 12px;
-}
-
-.mat-button {
-  position: absolute;
-  top: 10px;
-  right: 10px;
-  min-width: 28px;
-  width: 28px;
-  height: 28px;
-  padding: 0;
-  .mat-icon {
-    width: 24px;
-    height: 24px;
-  }
-}
diff --git a/gae/frontend/src/app/app.component.spec.ts b/gae/frontend/src/app/app.component.spec.ts
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/src/app/app.component.spec.ts
+++ /dev/null
diff --git a/gae/frontend/src/app/app.component.ts b/gae/frontend/src/app/app.component.ts
deleted file mode 100644
index 1a2ef06..0000000
--- a/gae/frontend/src/app/app.component.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { Component } from '@angular/core';
-
-import { AppService } from "./appservice";
-
-
-@Component({
-  selector: 'app-root',
-  templateUrl: './app.component.html',
-  styleUrls: ['./app.component.scss']
-})
-export class AppComponent {
-  _sideNavOpened = false;
-  get sideNavOpened(): boolean {
-    return this._sideNavOpened;
-  }
-  set sideNavOpened(value: boolean) {
-    this._sideNavOpened = value;
-    if (!value) {
-      this.selectedEntity = this.selectedEntity.slice();
-    }
-  }
-  selectedEntity: {name: string; value: any[]}[] = [];
-
-  constructor(private appService: AppService) {
-    appService.closeSideNavEmitter.subscribe(() => {this.sideNavOpened = false});
-    appService.showDetailsEmitter.subscribe(
-      (entity) => {
-        this.selectedEntity.length = 0;
-        if (entity) {
-          let self = this;
-          Object.keys(entity).forEach(function(value){
-            if (value !== 'urlsafe_key') {
-              self.selectedEntity.push({
-                name: value,
-                value: (entity[value] instanceof Array) ? entity[value] : [entity[value]]
-              });
-            }
-          });
-        }
-        this.sideNavOpened = !this.sideNavOpened;
-      },
-      (error) => {
-        console.log(error);
-      }
-    )
-  }
-}
diff --git a/gae/frontend/src/app/app.module.ts b/gae/frontend/src/app/app.module.ts
deleted file mode 100644
index ec940db..0000000
--- a/gae/frontend/src/app/app.module.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// Angular modules.
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { BrowserModule } from '@angular/platform-browser';
-import { FormsModule } from '@angular/forms';
-import { HttpClientModule } from '@angular/common/http';
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-
-// Angular Material modules
-import { MatButtonModule } from '@angular/material/button';
-import { MatCardModule } from '@angular/material/card';
-import { MatChipsModule } from '@angular/material/chips';
-import { MatExpansionModule } from '@angular/material/expansion';
-import { MatFormFieldModule } from '@angular/material/form-field';
-import { MatIconModule } from '@angular/material';
-import { MatInputModule } from '@angular/material/input';
-import { MatListModule } from '@angular/material/list';
-import { MatPaginatorModule } from '@angular/material/paginator';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatSnackBarModule } from '@angular/material/snack-bar';
-import { MatSelectModule } from '@angular/material/select';
-import { MatSidenavModule } from '@angular/material/sidenav';
-import { MatSortModule } from '@angular/material/sort';
-import { MatTableModule } from '@angular/material/table';
-import { MatTabsModule } from '@angular/material/tabs';
-
-// User components.
-import { AppComponent } from './app.component';
-import { BuildComponent } from './menu/build/build.component';
-import { DashboardComponent } from './menu/dashboard/dashboard.component';
-import { DeviceComponent } from './menu/device/device.component';
-import { FilterComponent } from './shared/filter/filter.component';
-import { JobComponent } from './menu/job/job.component';
-import { LabComponent } from './menu/lab/lab.component';
-import { ScheduleComponent } from './menu/schedule/schedule.component';
-
-// User modules.
-import { NavModule } from './shared/navbar/navbar';
-
-// Other dependencies.
-import { FlexLayoutModule } from '@angular/flex-layout';
-
-// User directives for CDK (Component Development Kit).
-import { CdkDetailRowDirective } from './menu/cdk-detail-row.directive';
-
-
-const appRoutes: Routes = [
-  { path: 'device', component: DeviceComponent },
-  { path: 'build', component: BuildComponent },
-  { path: 'job', component: JobComponent },
-  { path: 'lab', component: LabComponent },
-  { path: 'schedule', component: ScheduleComponent },
-  { path: '', component: DashboardComponent },
-  { path: '**', redirectTo: '/', pathMatch: 'full' }
-];
-
-
-@NgModule({
-  imports: [
-    MatButtonModule,
-    MatCardModule,
-    MatChipsModule,
-    MatExpansionModule,
-    MatFormFieldModule,
-    MatIconModule,
-    MatInputModule,
-    MatListModule,
-    MatPaginatorModule,
-    MatProgressSpinnerModule,
-    MatSnackBarModule,
-    MatSelectModule,
-    MatSidenavModule,
-    MatSortModule,
-    MatTableModule,
-    MatTabsModule,
-  ],
-  exports: [
-    MatButtonModule,
-    MatCardModule,
-    MatChipsModule,
-    MatExpansionModule,
-    MatFormFieldModule,
-    MatIconModule,
-    MatInputModule,
-    MatListModule,
-    MatPaginatorModule,
-    MatProgressSpinnerModule,
-    MatSnackBarModule,
-    MatSelectModule,
-    MatSidenavModule,
-    MatSortModule,
-    MatTableModule,
-    MatTabsModule,
-  ]
-})
-export class MaterialModule {}
-
-
-@NgModule({
-  declarations: [
-    AppComponent,
-    BuildComponent,
-    CdkDetailRowDirective,
-    DashboardComponent,
-    DeviceComponent,
-    FilterComponent,
-    JobComponent,
-    LabComponent,
-    ScheduleComponent,
-  ],
-  imports: [
-    BrowserAnimationsModule,
-    BrowserModule,
-    FlexLayoutModule,
-    FormsModule,
-    HttpClientModule,
-    MaterialModule,
-    NavModule,
-    RouterModule.forRoot(
-      appRoutes
-    ),
-  ],
-  providers: [],
-  bootstrap: [AppComponent]
-})
-export class AppModule { }
diff --git a/gae/frontend/src/app/appservice.ts b/gae/frontend/src/app/appservice.ts
deleted file mode 100644
index 6b303f0..0000000
--- a/gae/frontend/src/app/appservice.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {EventEmitter, Injectable, Output} from '@angular/core';
-
-
-@Injectable({
-  providedIn: 'root',
-})
-export class AppService {
-  @Output() closeSideNavEmitter = new EventEmitter();
-  @Output() showDetailsEmitter = new EventEmitter();
-  constructor() {
-  }
-
-  /** Emits an EventEmitter to display entity in the side nav window. */
-  showDetails(entity) {
-    this.showDetailsEmitter.emit(entity);
-  }
-
-  /** Emits an EventEmitter to close the side nav window. */
-  closeSideNav() {
-    this.closeSideNavEmitter.emit();
-  }
-}
diff --git a/gae/frontend/src/app/menu/build/build.component.html b/gae/frontend/src/app/menu/build/build.component.html
deleted file mode 100644
index d8ae525..0000000
--- a/gae/frontend/src/app/menu/build/build.component.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div class="entity-filter">
-  <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
-  <mat-table #table [dataSource]="dataSource">
-    <!-- Index Column -->
-    <ng-container matColumnDef="_index">
-      <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
-      <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
-    </ng-container>
-
-    <!-- Manifest Branch Column -->
-    <ng-container matColumnDef="artifact_type">
-      <mat-header-cell *matHeaderCellDef>Artifact Type</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.artifact_type}} </mat-cell>
-    </ng-container>
-
-    <!-- Manifest Branch Column -->
-    <ng-container matColumnDef="manifest_branch">
-      <mat-header-cell *matHeaderCellDef>Manifest Branch</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.manifest_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- Build ID Column -->
-    <ng-container matColumnDef="build_id">
-      <mat-header-cell *matHeaderCellDef>Build ID</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.build_id}} </mat-cell>
-    </ng-container>
-
-    <!-- Build Target Column -->
-    <ng-container matColumnDef="build_target">
-      <mat-header-cell *matHeaderCellDef>Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- Build Type Column -->
-    <ng-container matColumnDef="build_type">
-      <mat-header-cell *matHeaderCellDef>Build Type</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.build_type}} </mat-cell>
-    </ng-container>
-
-    <!-- Signed Column -->
-    <ng-container matColumnDef="signed">
-      <mat-header-cell *matHeaderCellDef>Signed</mat-header-cell>
-      <mat-cell *matCellDef="let build"> {{build.signed}} </mat-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
-    <mat-row *matRowDef="let row; columns: columnTitles;"></mat-row>
-  </mat-table>
-
-  <mat-paginator [length]="count"
-                 [pageSize]="pageSize"
-                 [pageSizeOptions]="pageSizeOptions"
-                 [pageIndex]="pageIndex"
-                 (page)="pageEvent = onPageEvent($event)">
-  </mat-paginator>
-</div>
-<div class="loading-spinner" *ngIf="loading">
-  <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/build/build.component.scss b/gae/frontend/src/app/menu/build/build.component.scss
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/src/app/menu/build/build.component.scss
+++ /dev/null
diff --git a/gae/frontend/src/app/menu/build/build.component.ts b/gae/frontend/src/app/menu/build/build.component.ts
deleted file mode 100644
index e4c7325..0000000
--- a/gae/frontend/src/app/menu/build/build.component.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Build } from '../../model/build';
-import { BuildService } from './build.service';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-
-
-/** Component that handles build menu. */
-@Component({
-  selector: 'app-build',
-  templateUrl: './build.component.html',
-  providers: [ BuildService ],
-  styleUrls: ['./build.component.scss'],
-})
-export class BuildComponent extends MenuBaseClass implements OnInit {
-  columnTitles = [
-    '_index',
-    'artifact_type',
-    'manifest_branch',
-    'build_id',
-    'build_target',
-    'build_type',
-    'signed'];
-  dataSource = new MatTableDataSource<Build>();
-  pageEvent: PageEvent;
-  appliedFilters: FilterItem[];
-
-  @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
-  constructor(private buildService: BuildService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  ngOnInit(): void {
-    this.filterComponent.setSelectorList(Build);
-    this.getCount();
-    this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
-  }
-
-  /** Gets a total count of builds. */
-  getCount(observer = this.getDefaultCountObservable()) {
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.buildService.getCount(filterJSON).subscribe(observer);
-  }
-
-  /** Gets builds.
-   * @param size A number, at most this many results will be returned.
-   * @param offset A Number of results to skip.
-   */
-  getBuilds(size = 0, offset = 0) {
-    this.loading = true;
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.buildService.getBuilds(size, offset, filterJSON, '', '')
-      .subscribe(
-        (response) => {
-          this.loading = false;
-          if (this.count >= 0) {
-            let length = 0;
-            if (response.builds) {
-              length = response.builds.length;
-            }
-            const total = length + offset;
-            if (response.has_next) {
-              if (length !== this.pageSize) {
-                this.showSnackbar('Received unexpected number of entities.');
-              } else if (this.count <= total) {
-                this.getCount();
-              }
-            } else {
-              if (this.count !== total) {
-                if (length !== this.count) {
-                  this.getCount();
-                } else if (this.count > total) {
-                  const countObservable = this.getDefaultCountObservable([
-                    () => {
-                      this.pageIndex = Math.floor(this.count / this.pageSize);
-                      this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
-                    }
-                  ]);
-                  this.getCount(countObservable);
-                }
-              }
-            }
-          }
-          this.dataSource.data = response.builds;
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Hooks a page event and handles properly. */
-  onPageEvent(event: PageEvent) {
-    this.pageSize = event.pageSize;
-    this.pageIndex = event.pageIndex;
-    this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
-    return event;
-  }
-
-  /** Applies a filter and get entities with it. */
-  applyFilters(filters) {
-    this.pageIndex = 0;
-    this.appliedFilters = filters;
-    this.getCount();
-    this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
-  }
-}
diff --git a/gae/frontend/src/app/menu/build/build.service.ts b/gae/frontend/src/app/menu/build/build.service.ts
deleted file mode 100644
index d60f790..0000000
--- a/gae/frontend/src/app/menu/build/build.service.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { BuildWrapper } from '../../model/build_wrapper';
-import { environment } from '../../../environments/environment';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class BuildService extends ServiceBase {
-  constructor(public httpClient: HttpClient) {
-    super(httpClient);
-    this.url = environment['baseURL'] + '/build/v1/';
-  }
-
-  getBuilds(size: number,
-            offset: number,
-            filterInfo: string,
-            sort: string,
-            direction: string): Observable<BuildWrapper> {
-    const url = this.url + 'get';
-    return this.httpClient.post<BuildWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
-      .pipe(catchError(this.handleError));
-  }
-}
diff --git a/gae/frontend/src/app/menu/cdk-detail-row.directive.ts b/gae/frontend/src/app/menu/cdk-detail-row.directive.ts
deleted file mode 100644
index 60b490a..0000000
--- a/gae/frontend/src/app/menu/cdk-detail-row.directive.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Directive, EventEmitter, HostBinding, HostListener, Input, Output, TemplateRef, ViewContainerRef} from '@angular/core';
-
-
-@Directive({
-  selector: '[appCdkDetailRow]'
-})
-export class CdkDetailRowDirective {
-  private row: any;
-  private tRef: TemplateRef<any>;
-  private opened: boolean;
-
-  @HostBinding('class.expanded')
-  get expended(): boolean {
-    return this.opened;
-  }
-
-  @Input()
-  set appCdkDetailRow(value: any) {
-    if (value !== this.row) {
-      this.row = value;
-      // this.render();
-    }
-  }
-
-  @Input('appCdkDetailRowTpl')
-  set template(value: TemplateRef<any>) {
-    if (value !== this.tRef) {
-      this.tRef = value;
-    }
-  }
-
-  @Output() toggleChange = new EventEmitter<CdkDetailRowDirective>();
-
-  constructor(public vcRef: ViewContainerRef) { }
-
-  @HostListener('click')
-  onClick(): void {
-    this.toggle();
-  }
-
-  toggle(): void {
-    if (this.opened) {
-      this.vcRef.clear();
-    } else {
-      this.render();
-    }
-    this.opened = this.vcRef.length > 0;
-    this.toggleChange.emit(this);
-  }
-
-  private render(): void {
-    this.vcRef.clear();
-    if (this.tRef && this.row) {
-      this.vcRef.createEmbeddedView(this.tRef, { $implicit: this.row });
-    }
-  }
-}
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.html b/gae/frontend/src/app/menu/dashboard/dashboard.component.html
deleted file mode 100644
index b91e80c..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div fxLayout="row">
-  <mat-card>
-    <mat-card-title>Build</mat-card-title>
-    <mat-card-subtitle>Last updated:  {{getRelativeTime(lastBuildUpdateTime)}}</mat-card-subtitle>
-    <button mat-raised-button (click)="getLatestBuild()">
-      <mat-icon>refresh</mat-icon>
-    </button>
-  </mat-card>
-  <mat-card>
-    <mat-card-title>Schedule</mat-card-title>
-    <mat-card-subtitle>Last updated:  {{getRelativeTime(lastScheduleUpdateTime)}}</mat-card-subtitle>
-    <button mat-raised-button (click)="getLastestSchedule()">
-      <mat-icon>refresh</mat-icon>
-    </button>
-  </mat-card>
-</div>
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.scss b/gae/frontend/src/app/menu/dashboard/dashboard.component.scss
deleted file mode 100644
index a17cb36..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-.mat-card {
-  width: 50%;
-
-  .mat-raised-button {
-    position: absolute;
-    top: 10px;
-    right: 10px;
-    min-width: 28px;
-    width: 28px;
-    height: 28px;
-    padding: 0;
-    .mat-icon {
-      width: 24px;
-      height: 24px;
-    }
-  }
-}
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.ts b/gae/frontend/src/app/menu/dashboard/dashboard.component.ts
deleted file mode 100644
index 0157ea8..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit } from '@angular/core';
-import { MatSnackBar } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { BuildService } from "../build/build.service";
-import { MenuBaseClass } from "../menu_base";
-import { ScheduleService } from "../schedule/schedule.service";
-
-/** Component that handles dashboard. */
-@Component({
-  selector: 'app-dashboard',
-  templateUrl: './dashboard.component.html',
-  providers: [ BuildService, ScheduleService ],
-  styleUrls: ['./dashboard.component.scss']
-})
-export class DashboardComponent extends MenuBaseClass implements OnInit {
-  lastBuildUpdateTime: any = '---';
-  lastScheduleUpdateTime: any = '---';
-
-  constructor(private buildService: BuildService,
-              private scheduleService: ScheduleService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  ngOnInit(): void {
-    this.getLatestBuild();
-    this.getLastestSchedule();
-  }
-
-  /** Fetches the most recently updated build and gets timestamp from it. */
-  getLatestBuild() {
-    this.lastBuildUpdateTime = '---';
-    this.buildService.getBuilds(1, 0, '', 'timestamp', 'desc')
-      .subscribe(
-        (response) => {
-          if (response.builds) {
-            this.lastBuildUpdateTime = response.builds[0].timestamp;
-          }
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Fetches the most recently updated schedule and gets timestamp from it. */
-  getLastestSchedule() {
-    this.lastScheduleUpdateTime = '---';
-    this.scheduleService.getSchedules(1, 0, '', 'timestamp', 'desc')
-      .subscribe(
-        (response) => {
-          if (response.schedules) {
-            this.lastScheduleUpdateTime = response.schedules[0].timestamp;
-          }
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-}
diff --git a/gae/frontend/src/app/menu/device/device.component.html b/gae/frontend/src/app/menu/device/device.component.html
deleted file mode 100644
index b36491e..0000000
--- a/gae/frontend/src/app/menu/device/device.component.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div class="entity-filter">
-  <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
-  <mat-table [dataSource]="dataSource" matSort matSortActive="hostname" matSortDirection="asc">
-    <!-- Index Column -->
-    <ng-container matColumnDef="_index">
-      <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
-      <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
-    </ng-container>
-
-    <!-- Host Name Column -->
-    <ng-container matColumnDef="hostname">
-      <mat-header-cell *matHeaderCellDef mat-sort-header disabled>Host Name</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{device.hostname}} </mat-cell>
-    </ng-container>
-
-    <!-- Product Column -->
-    <ng-container matColumnDef="product">
-      <mat-header-cell *matHeaderCellDef>Product</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{device.product}} </mat-cell>
-    </ng-container>
-
-    <!-- Serial Column -->
-    <ng-container matColumnDef="serial">
-      <mat-header-cell *matHeaderCellDef>Serial</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{device.serial}} </mat-cell>
-    </ng-container>
-
-    <!-- Status Column -->
-    <ng-container matColumnDef="status">
-      <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{deviceStatusEnum[device.status]}} </mat-cell>
-    </ng-container>
-
-    <!-- Scheduling Status Column -->
-    <ng-container matColumnDef="scheduling_status">
-      <mat-header-cell *matHeaderCellDef>Scheduling Status</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{schedulingStatusEnum[device.scheduling_status]}} </mat-cell>
-    </ng-container>
-
-    <!-- Equipment Column -->
-    <ng-container matColumnDef="device_equipment">
-      <mat-header-cell *matHeaderCellDef>Equipment</mat-header-cell>
-      <mat-cell *matCellDef="let device"> {{device.device_equipment ? device.device_equipment.join(", ") : "None"}} </mat-cell>
-    </ng-container>
-
-    <!-- Timestamp Column -->
-    <ng-container matColumnDef="timestamp">
-      <mat-header-cell *matHeaderCellDef>Timestamp</mat-header-cell>
-      <mat-cell *matCellDef="let device">{{getRelativeTime(device.timestamp)}}</mat-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
-    <mat-row *matRowDef="let row; columns: columnTitles;"></mat-row>
-  </mat-table>
-  <mat-paginator [length]="count"
-                 [pageSize]="pageSize"
-                 [pageSizeOptions]="pageSizeOptions"
-                 [pageIndex]="pageIndex"
-                 (page)="pageEvent = onPageEvent($event)">
-  </mat-paginator>
-</div>
-<div class="loading-spinner" *ngIf="loading">
-  <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/device/device.component.scss b/gae/frontend/src/app/menu/device/device.component.scss
deleted file mode 100644
index 165de43..0000000
--- a/gae/frontend/src/app/menu/device/device.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.mat-header-cell {
-  padding: 0 10px 0 10px;
-}
-
-.mat-cell {
-  padding: 0 10px 0 10px;
-}
diff --git a/gae/frontend/src/app/menu/device/device.component.ts b/gae/frontend/src/app/menu/device/device.component.ts
deleted file mode 100644
index 6258aed..0000000
--- a/gae/frontend/src/app/menu/device/device.component.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Device } from '../../model/device';
-import { DeviceService } from './device.service';
-import { DeviceStatus, SchedulingStatus } from '../../shared/vtslab_status';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-
-
-/** Component that handles device menu. */
-@Component({
-  selector: 'app-device',
-  templateUrl: './device.component.html',
-  providers: [ DeviceService ],
-  styleUrls: ['./device.component.scss'],
-})
-export class DeviceComponent extends MenuBaseClass implements OnInit {
-  columnTitles = [
-    '_index',
-    'hostname',
-    'product',
-    'serial',
-    'status',
-    'scheduling_status',
-    'device_equipment',
-    'timestamp',
-  ];
-  dataSource = new MatTableDataSource<Device>();
-  pageEvent: PageEvent;
-  deviceStatusEnum = DeviceStatus;
-  schedulingStatusEnum = SchedulingStatus;
-  appliedFilters: FilterItem[];
-
-  sort = '';
-  sortDirection = '';
-
-  @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
-  constructor(private deviceService: DeviceService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  ngOnInit(): void {
-    this.sort = 'hostname';
-    this.sortDirection = 'asc';
-
-    this.filterComponent.setSelectorList(Device);
-    this.getCount();
-    this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
-  }
-
-  /** Gets a total count of devices. */
-  getCount(observer = this.getDefaultCountObservable()) {
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.deviceService.getCount(filterJSON).subscribe(observer);
-  }
-
-  /** Gets devices.
-   * @param size A number, at most this many results will be returned.
-   * @param offset A Number of results to skip.
-   */
-  getDevices(size = 0, offset = 0) {
-    this.loading = true;
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.deviceService.getDevices(size, offset, filterJSON, this.sort, this.sortDirection)
-      .subscribe(
-        (response) => {
-          this.loading = false;
-          if (this.count >= 0) {
-            let length = 0;
-            if (response.devices) {
-              length = response.devices.length;
-            }
-            const total = length + offset;
-            if (response.has_next) {
-              if (length !== this.pageSize) {
-                this.showSnackbar('Received unexpected number of entities.');
-              } else if (this.count <= total) {
-                this.getCount();
-              }
-            } else {
-              if (this.count !== total) {
-                if (length !== this.count) {
-                  this.getCount();
-                } else if (this.count > total) {
-                  const countObservable = this.getDefaultCountObservable([
-                    () => {
-                      this.pageIndex = Math.floor(this.count / this.pageSize);
-                      this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
-                    }
-                  ]);
-                  this.getCount(countObservable);
-                }
-              }
-            }
-          }
-          this.dataSource.data = response.devices;
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Hooks a page event and handles properly. */
-  onPageEvent(event: PageEvent) {
-    this.pageSize = event.pageSize;
-    this.pageIndex = event.pageIndex;
-    this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
-    return event;
-  }
-
-  /** Applies a filter and get entities with it. */
-  applyFilters(filters) {
-    this.pageIndex = 0;
-    this.appliedFilters = filters;
-    this.getCount();
-    this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
-  }
-}
diff --git a/gae/frontend/src/app/menu/device/device.service.ts b/gae/frontend/src/app/menu/device/device.service.ts
deleted file mode 100644
index 2a465ff..0000000
--- a/gae/frontend/src/app/menu/device/device.service.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { DeviceWrapper } from '../../model/device_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class DeviceService extends ServiceBase {
-  constructor(public httpClient: HttpClient) {
-    super(httpClient);
-    this.url = environment['baseURL'] + '/host/v1/';
-  }
-
-  getDevices(size: number,
-             offset: number,
-             filterInfo: string,
-             sort: string,
-             direction: string): Observable<DeviceWrapper> {
-    const url = this.url + 'get';
-    return this.httpClient.post<DeviceWrapper>(url,  {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
-      .pipe(catchError(this.handleError));
-  }
-}
diff --git a/gae/frontend/src/app/menu/job/_job-theme.scss b/gae/frontend/src/app/menu/job/_job-theme.scss
deleted file mode 100644
index 084f1fb..0000000
--- a/gae/frontend/src/app/menu/job/_job-theme.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@mixin schedule-theme($theme) {
-  $primary: map-get($theme, primary);
-  $accent: map-get($theme, accent);
-  $warn: map-get($theme, warn);
-  $background: map-get($theme, background);
-  $foreground: map-get($theme, foreground);
-}
diff --git a/gae/frontend/src/app/menu/job/job.component.html b/gae/frontend/src/app/menu/job/job.component.html
deleted file mode 100644
index 634402d..0000000
--- a/gae/frontend/src/app/menu/job/job.component.html
+++ /dev/null
@@ -1,192 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div class="statistics-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
-  <mat-table [dataSource]="statDataSource">
-    <ng-container matColumnDef="hours">
-      <mat-header-cell *matHeaderCellDef>Stats</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.hours}} </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="created">
-      <mat-header-cell *matHeaderCellDef>Created</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.created}} </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="completed">
-      <mat-header-cell *matHeaderCellDef>Completed</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.completed}} ({{stat.created > 0 ? (stat.completed/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="running">
-      <mat-header-cell *matHeaderCellDef>Running/Ready</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.running}} ({{stat.created > 0 ? (stat.running/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="bootup_err">
-      <mat-header-cell *matHeaderCellDef>Boot-up Error</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.bootup_err}} ({{stat.created > 0 ? (stat.bootup_err/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="infra_err">
-      <mat-header-cell *matHeaderCellDef>Infra Error</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.infra_err}} ({{stat.created > 0 ? (stat.infra_err/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="expired">
-      <mat-header-cell *matHeaderCellDef>Expired</mat-header-cell>
-      <mat-cell *matCellDef="let stat"> {{stat.expired}} ({{stat.created > 0 ? (stat.expired/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="statColumnTitles"></mat-header-row>
-    <mat-row *matRowDef="let row; columns: statColumnTitles;"></mat-row>
-  </mat-table>
-</div>
-<div class="entity-filter">
-  <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
-  <mat-table [dataSource]="dataSource" matSort matSortActive="timestamp" matSortDirection="desc">
-  <!-- Index Column -->
-    <ng-container matColumnDef="_index">
-      <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
-      <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Type Column -->
-    <ng-container matColumnDef="test_type">
-      <mat-header-cell *matHeaderCellDef>Test Type</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{getTestTypeText(job.test_type)}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Name Column -->
-    <ng-container matColumnDef="test_name">
-      <mat-header-cell *matHeaderCellDef>Test Name</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.test_name}} </mat-cell>
-    </ng-container>
-
-    <!-- Host Name Column -->
-    <ng-container matColumnDef="hostname">
-      <mat-header-cell *matHeaderCellDef>Hostname</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.hostname}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Column -->
-    <ng-container matColumnDef="device">
-      <mat-header-cell *matHeaderCellDef>Device</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.device}} </mat-cell>
-    </ng-container>
-
-    <!-- Serial Column -->
-    <ng-container matColumnDef="serial">
-      <mat-header-cell *matHeaderCellDef>Serial</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.serial ? job.serial.join('\n') : ""}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Branch Column -->
-    <ng-container matColumnDef="manifest_branch">
-      <mat-header-cell *matHeaderCellDef>Device Branch</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.manifest_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Build Target Column -->
-    <ng-container matColumnDef="build_target">
-      <mat-header-cell *matHeaderCellDef>Device Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Build ID Column -->
-    <ng-container matColumnDef="build_id">
-      <mat-header-cell *matHeaderCellDef>Device Build ID</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.build_id}} </mat-cell>
-    </ng-container>
-
-    <!-- GSI Branch Column -->
-    <ng-container matColumnDef="gsi_branch">
-      <mat-header-cell *matHeaderCellDef>GSI Branch</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.gsi_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- GSI Build Target Column -->
-    <ng-container matColumnDef="gsi_build_target">
-      <mat-header-cell *matHeaderCellDef>GSI Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.gsi_build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Build ID Column -->
-    <ng-container matColumnDef="gsi_build_id">
-      <mat-header-cell *matHeaderCellDef>GSI Build ID</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.gsi_build_id}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Branch Column -->
-    <ng-container matColumnDef="test_branch">
-      <mat-header-cell *matHeaderCellDef>Test Branch</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.test_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Build Target Column -->
-    <ng-container matColumnDef="test_build_target">
-      <mat-header-cell *matHeaderCellDef>Test Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.test_build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Build ID Column -->
-    <ng-container matColumnDef="test_build_id">
-      <mat-header-cell *matHeaderCellDef>Test Build ID</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{job.test_build_id}} </mat-cell>
-    </ng-container>
-
-    <!-- Status Column -->
-    <ng-container matColumnDef="status">
-      <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{jobStatusEnum[job.status]}} </mat-cell>
-    </ng-container>
-
-    <!-- Timestamp Column -->
-    <ng-container matColumnDef="timestamp">
-      <mat-header-cell *matHeaderCellDef mat-sort-header disabled>Timestamp</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{getRelativeTime(job.timestamp)}} </mat-cell>
-    </ng-container>
-
-    <!-- Heartbeat stamp Column -->
-    <ng-container matColumnDef="heartbeat_stamp">
-      <mat-header-cell *matHeaderCellDef>Heartbeat</mat-header-cell>
-      <mat-cell *matCellDef="let job"> {{getRelativeTime(job.heartbeat_stamp)}} </mat-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
-    <mat-row *matRowDef="let row; columns: columnTitles;"
-             matRipple
-             class="element-row"
-             [appCdkDetailRow]="row" [appCdkDetailRowTpl]="job_detail"></mat-row>
-  </mat-table>
-  <mat-paginator [length]="count"
-                 [pageSize]="pageSize"
-                 [pageSizeOptions]="pageSizeOptions"
-                 [pageIndex]="pageIndex"
-                 (page)="pageEvent = onPageEvent($event)">
-  </mat-paginator>
-</div>
-<ng-template #job_detail let-job>
-  <div class="mat-row div-expandable" [@detailExpand] style="overflow: hidden">
-    <a href="{{job.infra_log_url}}" download><button mat-raised-button [disabled]="(!job.infra_log_url)">Download Infra Log</button></a>
-    <button mat-raised-button (click)="onShowDetailsClicked(job)">
-      Show Details
-    </button>
-  </div>
-</ng-template>
-<div class="loading-spinner" *ngIf="loading">
-  <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/job/job.component.scss b/gae/frontend/src/app/menu/job/job.component.scss
deleted file mode 100644
index c8aee00..0000000
--- a/gae/frontend/src/app/menu/job/job.component.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.mat-header-cell {
-  padding: 0 10px 0 10px;
-}
-
-.mat-cell {
-  padding: 0 10px 0 10px;
-}
-
-.element-row {
-  position: relative;
-  overflow: hidden;
-}
-
-.element-row:not(.expanded) {
-  cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
-  background: #f5f5f5;
-}
-
-.element-row.expanded {
-  border-bottom-color: transparent;
-}
diff --git a/gae/frontend/src/app/menu/job/job.component.ts b/gae/frontend/src/app/menu/job/job.component.ts
deleted file mode 100644
index 4375581..0000000
--- a/gae/frontend/src/app/menu/job/job.component.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-import { animate, state, style, transition, trigger } from '@angular/animations';
-
-import { AppService } from '../../appservice';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterCondition } from '../../model/filter_condition';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-import { Job } from '../../model/job';
-import { JobService } from './job.service';
-import { JobStatus, TestType } from '../../shared/vtslab_status';
-
-import * as moment from 'moment-timezone';
-
-
-/** Component that handles job menu. */
-@Component({
-  selector: 'app-job',
-  templateUrl: './job.component.html',
-  providers: [ JobService ],
-  styleUrls: ['./job.component.scss'],
-  animations: [
-    trigger('detailExpand', [
-      state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})),
-      state('*', style({height: '*', visibility: 'visible'})),
-      transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
-    ]),
-  ],
-})
-export class JobComponent extends MenuBaseClass implements OnInit {
-  columnTitles = [
-    '_index',
-    'test_type',
-    'test_name',
-    'hostname',
-    'device',
-    'serial',
-    'manifest_branch',
-    'build_target',
-    'build_id',
-    'gsi_branch',
-    'gsi_build_target',
-    'gsi_build_id',
-    'test_branch',
-    'test_build_target',
-    'test_build_id',
-    'status',
-    'timestamp',
-    'heartbeat_stamp',
-  ];
-  statColumnTitles = [
-    'hours',
-    'created',
-    'completed',
-    'running',
-    'bootup_err',
-    'infra_err',
-    'expired',
-  ];
-  dataSource = new MatTableDataSource<Job>();
-  statDataSource = new MatTableDataSource();
-  pageEvent: PageEvent;
-  jobStatusEnum = JobStatus;
-  appliedFilters: FilterItem[];
-
-  @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
-  sort = '';
-  sortDirection = '';
-
-  constructor(private jobService: JobService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  ngOnInit(): void {
-    // By default, job page requires list in desc order by timestamp.
-    this.sort = 'timestamp';
-    this.sortDirection = 'desc';
-
-    this.filterComponent.setSelectorList(Job);
-    this.getCount();
-    this.getStatistics();
-    this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
-  }
-
-  /** Gets a total count of jobs. */
-  getCount(observer = this.getDefaultCountObservable()) {
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.jobService.getCount(filterJSON).subscribe(observer);
-  }
-
-  /** Gets jobs.
-   * @param size A number, at most this many results will be returned.
-   * @param offset A Number of results to skip.
-   */
-  getJobs(size = 0, offset = 0) {
-    this.loading = true;
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.jobService.getJobs(size, offset, filterJSON, this.sort, this.sortDirection)
-      .subscribe(
-        (response) => {
-          this.loading = false;
-          if (this.count >= 0) {
-            let length = 0;
-            if (response.jobs) {
-              length = response.jobs.length;
-            }
-            const total = length + offset;
-            if (response.has_next) {
-              if (length !== this.pageSize) {
-                this.showSnackbar('Received unexpected number of entities.');
-              } else if (this.count <= total) {
-                this.getCount();
-              }
-            } else {
-              if (this.count !== total) {
-                if (length !== this.count) {
-                  this.getCount();
-                } else if (this.count > total) {
-                  const countObservable = this.getDefaultCountObservable([
-                    () => {
-                      this.pageIndex = Math.floor(this.count / this.pageSize);
-                      this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
-                    }
-                  ]);
-                  this.getCount(countObservable);
-                }
-              }
-            }
-          }
-          this.dataSource.data = response.jobs;
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Hooks a page event and handles properly. */
-  onPageEvent(event: PageEvent) {
-    this.pageSize = event.pageSize;
-    this.pageIndex = event.pageIndex;
-    this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
-    return event;
-  }
-
-  /** Gets the recent jobs and calculate statistics */
-  getStatistics() {
-    const timeFilter = new FilterItem();
-    timeFilter.key = 'timestamp';
-    timeFilter.method = FilterCondition.GreaterThan;
-    timeFilter.value = '72';
-    const timeFilterString = JSON.stringify([timeFilter]);
-    this.jobService.getJobs(0, 0, timeFilterString, '', '')
-      .subscribe(
-        (response) => {
-          const stats_72hrs = this.buildStatisticsData('72 Hours', response.jobs);
-          const jobs_24hrs = (response.jobs == null || response.jobs.length === 0) ? undefined : response.jobs.filter(
-            job => (moment() - moment.tz(job.timestamp, 'YYYY-MM-DDThh:mm:ss', 'UTC')) / 3600000 < 24);
-          const stats_24hrs = this.buildStatisticsData('24 Hours', jobs_24hrs);
-          this.statDataSource.data = [stats_24hrs, stats_72hrs];
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Builds statistics from given jobs list */
-  buildStatisticsData(title, jobs) {
-    if (jobs == null || jobs.length === 0) {
-      return { hours: title, created: 0, completed: 0, running: 0, bootup_err: 0, infra_err: 0, expired: 0 };
-    }
-    return {
-      hours: title,
-      created: jobs.length,
-      completed: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Complete).length,
-      running: jobs.filter(job => job.status != null &&
-        (Number(job.status) === JobStatus.Leased || Number(job.status) === JobStatus.Ready)).length,
-      bootup_err: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Bootup_err).length,
-      infra_err: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Infra_err).length,
-      expired: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Expired).length,
-    };
-  }
-
-  /** Generates text to represent in HTML with given test type. */
-  getTestTypeText(status: number) {
-    if (status === undefined || status & TestType.Unknown) {
-      return TestType[TestType.Unknown];
-    }
-
-    const text_list = [];
-    [TestType.ToT, TestType.OTA, TestType.Signed, TestType.Manual].forEach(function (value) {
-      if (status & value) { text_list.push(TestType[value]); }
-    });
-
-    return text_list.join(', ');
-  }
-
-  /** Applies a filter and get entities with it. */
-  applyFilters(filters) {
-    this.pageIndex = 0;
-    this.appliedFilters = filters;
-    this.getCount();
-    this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
-  }
-}
diff --git a/gae/frontend/src/app/menu/job/job.service.ts b/gae/frontend/src/app/menu/job/job.service.ts
deleted file mode 100644
index 71b5417..0000000
--- a/gae/frontend/src/app/menu/job/job.service.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { JobWrapper } from '../../model/job_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class JobService extends ServiceBase {
-  // url: string;
-  constructor(public httpClient: HttpClient) {
-    super(httpClient);
-    this.url = environment['baseURL'] + '/job/v1/';
-  }
-
-  getJobs(size: number,
-          offset: number,
-          filterInfo: string,
-          sort: string,
-          direction: string): Observable<JobWrapper> {
-    const url = this.url + 'get';
-    return this.httpClient.post<JobWrapper>(url,  {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
-      .pipe(catchError(this.handleError));
-  }
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.component.html b/gae/frontend/src/app/menu/lab/lab.component.html
deleted file mode 100644
index 0392e2d..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<mat-tab-group>
-  <mat-tab label="Lab">
-    <div class="mat-elevation-z2 entity-table">
-      <mat-table #table [dataSource]="labDataSource">
-        <!-- Index Column -->
-        <ng-container matColumnDef="_index">
-          <mat-header-cell *matHeaderCellDef class="index-column">No.</mat-header-cell>
-          <mat-cell *matCellDef="let i = index" class="index-column"> {{i+1+pageSize*labPageIndex}} </mat-cell>
-        </ng-container>
-
-        <!-- Name Column -->
-        <ng-container matColumnDef="name">
-          <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
-          <mat-cell *matCellDef="let lab"> {{lab.name}} </mat-cell>
-        </ng-container>
-
-        <!-- Owner Column -->
-        <ng-container matColumnDef="owner">
-          <mat-header-cell *matHeaderCellDef>Owner</mat-header-cell>
-          <mat-cell *matCellDef="let lab"> {{lab.owner}} </mat-cell>
-        </ng-container>
-
-        <!-- Admin Column -->
-        <ng-container matColumnDef="admin">
-          <mat-header-cell *matHeaderCellDef>Admin</mat-header-cell>
-          <mat-cell *matCellDef="let lab"> {{lab.admin ? lab.admin.join(", ") : "None"}} </mat-cell>
-        </ng-container>
-
-        <!-- Host Count Column -->
-        <ng-container matColumnDef="hostCount">
-          <mat-header-cell *matHeaderCellDef># of Host</mat-header-cell>
-          <mat-cell *matCellDef="let lab"> {{ lab.hosts.length }} </mat-cell>
-        </ng-container>
-
-        <mat-header-row *matHeaderRowDef="labColumnTitles"></mat-header-row>
-        <mat-row *matRowDef="let row; columns: labColumnTitles;"></mat-row>
-      </mat-table>
-      <mat-paginator [length]="labCount"
-                     [pageSizeOptions]="pageSizeOptions"
-                     [pageIndex]="labPageIndex">
-      </mat-paginator>
-    </div>
-  </mat-tab>
-  <mat-tab label="Host">
-    <div class="mat-elevation-z2 entity-table">
-      <mat-table #table [dataSource]="hostDataSource">
-        <!-- Index Column -->
-        <ng-container matColumnDef="_index">
-          <mat-header-cell *matHeaderCellDef class="index-column">No.</mat-header-cell>
-          <mat-cell *matCellDef="let i = index" class="index-column"> {{i+1+pageSize*pageIndex}} </mat-cell>
-        </ng-container>
-
-        <!-- Lab Column -->
-        <ng-container matColumnDef="name">
-          <mat-header-cell *matHeaderCellDef>Lab</mat-header-cell>
-          <mat-cell *matCellDef="let host"> {{host.name}} </mat-cell>
-        </ng-container>
-
-        <!-- Hostname Column -->
-        <ng-container matColumnDef="hostname">
-          <mat-header-cell *matHeaderCellDef>Hostname</mat-header-cell>
-          <mat-cell *matCellDef="let host"> {{host.hostname}} </mat-cell>
-        </ng-container>
-
-        <!-- IP Column -->
-        <ng-container matColumnDef="ip">
-          <mat-header-cell *matHeaderCellDef>IP</mat-header-cell>
-          <mat-cell *matCellDef="let host"> {{host.ip}} </mat-cell>
-        </ng-container>
-
-        <!-- Host Equipment Column -->
-        <ng-container matColumnDef="host_equipment">
-          <mat-header-cell *matHeaderCellDef>Equipment</mat-header-cell>
-          <mat-cell *matCellDef="let host"> {{host.host_equipment}} </mat-cell>
-        </ng-container>
-
-        <!-- Version Column -->
-        <ng-container matColumnDef="vtslab_version">
-          <mat-header-cell *matHeaderCellDef>Version</mat-header-cell>
-          <mat-cell *matCellDef="let host"> {{host.vtslab_version}} </mat-cell>
-        </ng-container>
-
-        <mat-header-row *matHeaderRowDef="hostColumnTitles"></mat-header-row>
-        <mat-row *matRowDef="let row; columns: hostColumnTitles;"></mat-row>
-      </mat-table>
-      <mat-paginator [length]="count"
-                     [pageSizeOptions]="pageSizeOptions"
-                     [pageIndex]="labPageIndex">
-      </mat-paginator>
-    </div>
-  </mat-tab>
-</mat-tab-group>
-<div class="loading-spinner" *ngIf="loading">
-  <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/lab/lab.component.scss b/gae/frontend/src/app/menu/lab/lab.component.scss
deleted file mode 100644
index fed2fb6..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-.mat-table {
-  overflow: auto;
-}
-
-.entity-table {
-  display: flex;
-  flex-direction: column;
-}
-
-.mat-header-cell {
-  padding: 0 10px 0 10px;
-}
-
-.index-column {
-  max-width: 40px;
-}
-
-.mat-cell {
-  padding: 0 10px 0 10px;
-}
-
-.element-row {
-  position: relative;
-  overflow: hidden;
-}
-
-.element-row:not(.expanded) {
-  cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
-  background: #f5f5f5;
-}
-
-.element-row.expanded {
-  border-bottom-color: transparent;
-}
-
-.div-expandable {
-  padding: 10px 20px 30px 20px;
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.component.ts b/gae/frontend/src/app/menu/lab/lab.component.ts
deleted file mode 100644
index bb7543b..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Host } from '../../model/host';
-import { Lab } from '../../model/lab';
-import { LabService } from './lab.service';
-import { MenuBaseClass } from '../menu_base';
-
-/** Component that handles lab and host menu. */
-@Component({
-  selector: 'app-lab',
-  templateUrl: './lab.component.html',
-  providers: [ LabService ],
-  styleUrls: ['./lab.component.scss'],
-})
-export class LabComponent extends MenuBaseClass implements OnInit {
-  labColumnTitles = [
-    '_index',
-    'name',
-    'owner',
-    'admin',
-    'hostCount',
-  ];
-  hostColumnTitles = [
-    '_index',
-    'name',
-    'hostname',
-    'ip',
-    'host_equipment',
-    'vtslab_version',
-  ];
-  labCount = -1;
-  labPageIndex = 0;
-
-  constructor(private labService: LabService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  labDataSource = new MatTableDataSource<Lab>();
-  hostDataSource = new MatTableDataSource<Host>();
-
-  ngOnInit(): void {
-    // For labs and hosts, it does not use query pagination.
-    this.getHosts();
-  }
-
-  /** Gets hosts.
-   * @param size A number, at most this many results will be returned.
-   * @param offset A Number of results to skip.
-   */
-  getHosts(size = 0, offset = 0) {
-    this.loading = true;
-    // Labs will not use filter for query.
-    const filterJSON = '';
-    this.labService.getLabs(size, offset, filterJSON, '', '')
-      .subscribe(
-        (response) => {
-          this.loading = false;
-          if (response.labs) {
-            this.count = response.labs.length;
-            this.hostDataSource.data = response.labs;
-            this.setLabs(response.labs);
-          }
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Sets labs from given hosts.
-   * @param hosts A list of Host instances.
-   */
-  setLabs(hosts: Host[]) {
-    if (hosts == null || hosts.length === 0) { return; }
-    const labMap = new Map();
-    hosts.forEach(function(host) {
-      if (labMap.has(host.name)) {
-        labMap.get(host.name).hosts.push(host);
-      } else {
-        labMap.set(host.name, {name: host.name, owner: host.owner, admin: host.admin, hosts: [host]});
-      }
-    });
-    const labs: Lab[] = [];
-    labMap.forEach((value) => labs.push(value));
-    this.labDataSource.data = labs;
-  }
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.service.ts b/gae/frontend/src/app/menu/lab/lab.service.ts
deleted file mode 100644
index 2d677b1..0000000
--- a/gae/frontend/src/app/menu/lab/lab.service.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { HostWrapper } from '../../model/host_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class LabService extends ServiceBase {
-  // url: string;
-  constructor(public httpClient: HttpClient) {
-    super(httpClient);
-    this.url = environment['baseURL'] + '/lab/v1/';
-  }
-
-  getLabs(size: number,
-          offset: number,
-          filterInfo: string,
-          sort: string,
-          direction: string): Observable<HostWrapper> {
-    const url = this.url + 'get';
-    return this.httpClient.post<HostWrapper>(url,  {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
-      .pipe(catchError(this.handleError));
-  }
-}
diff --git a/gae/frontend/src/app/menu/menu-items.ts b/gae/frontend/src/app/menu/menu-items.ts
deleted file mode 100644
index a544366..0000000
--- a/gae/frontend/src/app/menu/menu-items.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export const MENUS = {
-  ['VTSLab Scheduler']: '/',
-  ['build']: '/build',
-  ['device']: '/device',
-  ['lab']: '/lab',
-  ['schedule']: '/schedule',
-  ['job']: '/job',
-};
diff --git a/gae/frontend/src/app/menu/menu_base.ts b/gae/frontend/src/app/menu/menu_base.ts
deleted file mode 100644
index 4d68f03..0000000
--- a/gae/frontend/src/app/menu/menu_base.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** This class defines and/or implements the common properties and methods
- * used among menus.
- */
-import { AppService } from '../appservice';
-import { MatSnackBar } from '@angular/material';
-import moment from 'moment-timezone';
-
-
-export abstract class MenuBaseClass {
-  count = -1;
-
-  loading = false;
-  pageSizeOptions = [20, 50, 100, 200];
-  pageSize = 100;
-  pageIndex = 0;
-
-  protected constructor(private appService: AppService,
-                        public snackBar: MatSnackBar) {
-    this.appService.closeSideNav();
-    this.snackBar.dismiss();
-  }
-
-  /** Returns an Observable which handles a response of count API.
-   * @param additionalOperations A list of lambda functions.
-   */
-  getDefaultCountObservable(additionalOperations: any[] = []) {
-    return {
-      next: (response) => {
-        this.count = response.count;
-        for (const operation of additionalOperations) {
-          operation(response);
-        }
-      },
-      error: (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-    };
-  }
-
-  getRelativeTime(timeString) {
-    return (moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC').isValid() ?
-      moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC').fromNow() : '---');
-  }
-
-  /** Checks whether timeString is expired from current time. */
-  isExpired(timeString, hours=72) {
-    let currentTime = moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC');
-    if (!currentTime.isValid()) { return false; }
-
-    let diff = moment().diff(currentTime);
-    let duration = moment.duration(diff);
-    return duration.asHours() > hours;
-  }
-
-  /** Displays a snackbar notification. */
-  showSnackbar(message = 'Error', duration = 5000) {
-    this.loading = false;
-    this.snackBar.open(message, 'DISMISS', {duration});
-  }
-
-  /** Displays a side nav window and lists all properties of selected entity. */
-  onShowDetailsClicked(entity) {
-    this.appService.showDetails(entity);
-  }
-}
diff --git a/gae/frontend/src/app/menu/schedule/_schedule-theme.scss b/gae/frontend/src/app/menu/schedule/_schedule-theme.scss
deleted file mode 100644
index 084f1fb..0000000
--- a/gae/frontend/src/app/menu/schedule/_schedule-theme.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@mixin schedule-theme($theme) {
-  $primary: map-get($theme, primary);
-  $accent: map-get($theme, accent);
-  $warn: map-get($theme, warn);
-  $background: map-get($theme, background);
-  $foreground: map-get($theme, foreground);
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.html b/gae/frontend/src/app/menu/schedule/schedule.component.html
deleted file mode 100644
index 910d45b..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.html
+++ /dev/null
@@ -1,121 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div class="entity-filter">
-  <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
-  <mat-table [dataSource]="dataSource">
-    <!-- Index Column -->
-    <ng-container matColumnDef="_index">
-      <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
-      <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Name Column -->
-    <ng-container matColumnDef="test_name">
-      <mat-header-cell *matHeaderCellDef>Test Name</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.test_name}} </mat-cell>
-    </ng-container>
-
-    <!-- Device Column -->
-    <ng-container matColumnDef="device">
-      <mat-header-cell *matHeaderCellDef>Device</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.device ? schedule.device.join('\n') : ""}} </mat-cell>
-    </ng-container>
-
-    <!-- Manifest Branch Column -->
-    <ng-container matColumnDef="manifest_branch">
-      <mat-header-cell *matHeaderCellDef>Manifest Branch</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.manifest_branch}}</mat-cell>
-    </ng-container>
-
-    <!-- Build Target Column -->
-    <ng-container matColumnDef="build_target">
-      <mat-header-cell *matHeaderCellDef>Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- GSI Branch Column -->
-    <ng-container matColumnDef="gsi_branch">
-      <mat-header-cell *matHeaderCellDef>GSI Branch</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.gsi_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- GSI Build Target Column -->
-    <ng-container matColumnDef="gsi_build_target">
-      <mat-header-cell *matHeaderCellDef>GSI Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.gsi_build_target}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Branch Column -->
-    <ng-container matColumnDef="test_branch">
-      <mat-header-cell *matHeaderCellDef>Test Branch</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.test_branch}} </mat-cell>
-    </ng-container>
-
-    <!-- Test Build Target Column -->
-    <ng-container matColumnDef="test_build_target">
-      <mat-header-cell *matHeaderCellDef>Test Build Target</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.test_build_target}}</mat-cell>
-    </ng-container>
-
-    <!-- Period Column -->
-    <ng-container matColumnDef="period">
-      <mat-header-cell *matHeaderCellDef>Period</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{schedule.period}}</mat-cell>
-    </ng-container>
-
-    <!-- Status Column -->
-    <ng-container matColumnDef="status">
-      <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"
-                [ngStyle]="{color: (schedule.suspended || isExpired(schedule.timestamp)) ? '#FF0000' : '#000000'}">
-        {{schedule.suspended ? "Suspended" : (isExpired(schedule.timestamp) ? "Expired" : "Active")}}
-      </mat-cell>
-    </ng-container>
-
-    <!-- Timestamp Column -->
-    <ng-container matColumnDef="timestamp">
-      <mat-header-cell *matHeaderCellDef>Timestamp</mat-header-cell>
-      <mat-cell *matCellDef="let schedule"> {{getRelativeTime(schedule.timestamp)}}</mat-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
-    <mat-row *matRowDef="let row; columns: columnTitles;"
-             matRipple
-             class="element-row"
-             [appCdkDetailRow]="row" [appCdkDetailRowTpl]="schedule_detail"></mat-row>
-  </mat-table>
-
-  <mat-paginator [length]="count"
-                 [pageSize]="pageSize"
-                 [pageSizeOptions]="pageSizeOptions"
-                 [pageIndex]="pageIndex"
-                 (page)="pageEvent = onPageEvent($event)">
-  </mat-paginator>
-</div>
-<ng-template #schedule_detail let-schedule>
-  <div class="mat-row div-expandable" [@detailExpand] style="overflow: hidden">
-    <button mat-raised-button (click)="suspendSchedule([{urlsafe_key: schedule.urlsafe_key, suspend: !schedule.suspended}])">
-      {{(schedule.suspended ? "Resume" : "Suspend")}}
-    </button>
-    <button mat-raised-button (click)="onShowDetailsClicked(schedule)">
-      Show Details
-    </button>
-  </div>
-</ng-template>
-<div class="loading-spinner" *ngIf="loading">
-  <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.scss b/gae/frontend/src/app/menu/schedule/schedule.component.scss
deleted file mode 100644
index c8aee00..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.mat-header-cell {
-  padding: 0 10px 0 10px;
-}
-
-.mat-cell {
-  padding: 0 10px 0 10px;
-}
-
-.element-row {
-  position: relative;
-  overflow: hidden;
-}
-
-.element-row:not(.expanded) {
-  cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
-  background: #f5f5f5;
-}
-
-.element-row.expanded {
-  border-bottom-color: transparent;
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.ts b/gae/frontend/src/app/menu/schedule/schedule.component.ts
deleted file mode 100644
index 5c1740e..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-import { animate, state, style, transition, trigger } from "@angular/animations";
-
-import { AppService } from '../../appservice';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-import { Schedule, ScheduleSuspendResponse } from '../../model/schedule';
-import { ScheduleService } from './schedule.service';
-
-
-/** Component that handles schedule menu. */
-@Component({
-  selector: 'app-schedule',
-  templateUrl: './schedule.component.html',
-  providers: [ ScheduleService ],
-  styleUrls: ['./schedule.component.scss'],
-  animations: [
-    trigger('detailExpand', [
-      state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})),
-      state('*', style({height: '*', visibility: 'visible'})),
-      transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
-    ]),
-  ],
-})
-export class ScheduleComponent extends MenuBaseClass implements OnInit {
-  columnTitles = [
-    '_index',
-    'test_name',
-    'device',
-    'manifest_branch',
-    'build_target',
-    'gsi_branch',
-    'gsi_build_target',
-    'test_branch',
-    'test_build_target',
-    'period',
-    'status',
-    'timestamp',
-  ];
-  dataSource = new MatTableDataSource<Schedule>();
-  pageEvent: PageEvent;
-  appliedFilters: FilterItem[];
-
-  @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
-  constructor(private scheduleService: ScheduleService,
-              appService: AppService,
-              snackBar: MatSnackBar) {
-    super(appService, snackBar);
-  }
-
-  ngOnInit(): void {
-    this.filterComponent.setSelectorList(Schedule);
-    this.getCount();
-    this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
-  }
-
-  /** Gets a total count of schedules. */
-  getCount(observer = this.getDefaultCountObservable()) {
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.scheduleService.getCount(filterJSON).subscribe(observer);
-  }
-
-  /** Gets schedules.
-   * @param size A number, at most this many results will be returned.
-   * @param offset A Number of results to skip.
-   */
-  getSchedules(size = 0, offset = 0) {
-    this.loading = true;
-    const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
-    this.scheduleService.getSchedules(size, offset, filterJSON, '', '')
-      .subscribe(
-        (response) => {
-          this.loading = false;
-          if (this.count >= 0) {
-            let length = 0;
-            if (response.schedules) {
-              length = response.schedules.length;
-            }
-            const total = length + offset;
-            if (response.has_next) {
-              if (length !== this.pageSize) {
-                this.showSnackbar('Received unexpected number of entities.');
-              } else if (this.count <= total) {
-                this.getCount();
-              }
-            } else {
-              if (this.count !== total) {
-                if (length !== this.count) {
-                  this.getCount();
-                } else if (this.count > total) {
-                  const countObservable = this.getDefaultCountObservable([
-                    () => {
-                      this.pageIndex = Math.floor(this.count / this.pageSize);
-                      this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
-                    }
-                  ]);
-                  this.getCount(countObservable);
-                }
-              }
-            }
-          }
-          this.dataSource.data = response.schedules;
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Toggles a schedule from suspend to resume, or vice versa. */
-  suspendSchedule(schedules: ScheduleSuspendResponse[]) {
-    this.scheduleService.suspendSchedule(schedules)
-      .subscribe(
-        (response) => {
-          if (response.schedules) {
-            let self = this;
-            response.schedules.forEach(function(schedule) {
-                const original = self.dataSource.data.filter(x => x.urlsafe_key === schedule.urlsafe_key);
-                if (original) {
-                  original[0].suspended = schedule.suspend;
-                }
-              })
-          }
-        },
-        (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
-      );
-  }
-
-  /** Hooks a page event and handles properly. */
-  onPageEvent(event: PageEvent) {
-    this.pageSize = event.pageSize;
-    this.pageIndex = event.pageIndex;
-    this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
-    return event;
-  }
-
-  /** Applies a filter and get entities with it. */
-  applyFilters(filters) {
-    this.pageIndex = 0;
-    this.appliedFilters = filters;
-    this.getCount();
-    this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
-  }
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.service.ts b/gae/frontend/src/app/menu/schedule/schedule.service.ts
deleted file mode 100644
index ae534dd..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.service.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { ScheduleWrapper } from '../../model/schedule_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-import { ScheduleSuspendResponse, ScheduleSuspendResponseWrapper } from '../../model/schedule';
-
-
-@Injectable()
-export class ScheduleService extends ServiceBase {
-  // url: string;
-  constructor(public httpClient: HttpClient) {
-    super(httpClient);
-    this.url = environment['baseURL'] + '/schedule/v1/';
-  }
-
-  getSchedules(size: number,
-               offset: number,
-               filterInfo: string,
-               sort: string,
-               direction: string): Observable<ScheduleWrapper> {
-    const url = this.url + 'get';
-    return this.httpClient.post<ScheduleWrapper>(url,  {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
-      .pipe(catchError(this.handleError));
-  }
-
-  suspendSchedule(schedules: ScheduleSuspendResponse[]): Observable<ScheduleSuspendResponseWrapper> {
-    const url = this.url + 'suspend';
-    return this.httpClient.post<ScheduleSuspendResponseWrapper>(url, {schedules: schedules})
-      .pipe(catchError(this.handleError));
-  }
-}
diff --git a/gae/frontend/src/app/model/build.ts b/gae/frontend/src/app/model/build.ts
deleted file mode 100644
index bf32a4a..0000000
--- a/gae/frontend/src/app/model/build.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Build {
-  manifest_branch: string = void 0;
-  build_id: string = void 0;
-  build_target: string = void 0;
-  build_type: string = void 0;
-  artifact_type: string = void 0;
-  artifacts: string[] = void 0;
-  signed: boolean = void 0;
-  timestamp: any = void 0;
-}
diff --git a/gae/frontend/src/app/model/build_wrapper.ts b/gae/frontend/src/app/model/build_wrapper.ts
deleted file mode 100644
index 797d097..0000000
--- a/gae/frontend/src/app/model/build_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Build} from './build';
-
-export interface BuildWrapper {
-  builds: Build[];
-  has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/device.ts b/gae/frontend/src/app/model/device.ts
deleted file mode 100644
index 21fdfb7..0000000
--- a/gae/frontend/src/app/model/device.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Device {
-  serial: string = void 0;
-  product: string = void 0;
-  status: number = void 0;
-  scheduling_status: number = void 0;
-  hostname: string = void 0;
-  device_equipment: string[] = void 0;
-  timestamp: any = void 0;
-}
diff --git a/gae/frontend/src/app/model/device_wrapper.ts b/gae/frontend/src/app/model/device_wrapper.ts
deleted file mode 100644
index af18dce..0000000
--- a/gae/frontend/src/app/model/device_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Device} from './device';
-
-export interface DeviceWrapper {
-  devices: Device[];
-  has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/filter_condition.ts b/gae/frontend/src/app/model/filter_condition.ts
deleted file mode 100644
index 9f76de9..0000000
--- a/gae/frontend/src/app/model/filter_condition.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export enum FilterCondition {
-  EqualTo = 1,
-  LessThan,
-  GreaterThan,
-  LessThanOrEqualTo,
-  GreaterThanOrEqualTo,
-  NotEqualTo,
-  Has,
-}
diff --git a/gae/frontend/src/app/model/filter_item.ts b/gae/frontend/src/app/model/filter_item.ts
deleted file mode 100644
index de457a1..0000000
--- a/gae/frontend/src/app/model/filter_item.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {FilterCondition} from './filter_condition';
-
-export class FilterItem {
-  key: string;
-  method: FilterCondition;
-  value: string;  // back-end should handle type-casting.
-}
diff --git a/gae/frontend/src/app/model/host.ts b/gae/frontend/src/app/model/host.ts
deleted file mode 100644
index 3836c30..0000000
--- a/gae/frontend/src/app/model/host.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Host {
-  name: string = void 0;  // lab name
-  owner: string = void 0;
-  admin: string[] = void 0;
-  hostname: string = void 0;
-  ip: string = void 0;
-  devices: string = void 0;
-  vtslab_version: string = void 0;
-  host_equipment: string[] = void 0;
-}
diff --git a/gae/frontend/src/app/model/host_wrapper.ts b/gae/frontend/src/app/model/host_wrapper.ts
deleted file mode 100644
index ae18a04..0000000
--- a/gae/frontend/src/app/model/host_wrapper.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Host} from './host';
-
-export interface HostWrapper {
-   // Back-end stores each host information as LabModel entity, so it sends
-   // host information as 'labs'.
-  labs: Host[];
-  has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/job.ts b/gae/frontend/src/app/model/job.ts
deleted file mode 100644
index 69e45b7..0000000
--- a/gae/frontend/src/app/model/job.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Job {
-  test_type: number = void 0;
-
-  hostname: string = void 0;
-  priority: string = void 0;
-  test_name: string = void 0;
-  require_signed_device_build: boolean = void 0;
-  has_bootloader_img: boolean = void 0;
-  has_radio_img: boolean = void 0;
-  device: string = void 0;
-  serial: string = void 0;
-
-  // device image information
-  build_storage_type: number = void 0;
-  manifest_branch: string = void 0;
-  build_target: string = void 0;
-  build_id: string = void 0;
-  pab_account_id: string = void 0;
-
-  shards: number = void 0;
-  param: string = void 0;
-  status: number = void 0;
-  period: number = void 0;
-
-  // GSI information
-  gsi_storage_type: number = void 0;
-  gsi_branch: string = void 0;
-  gsi_build_target: string = void 0;
-  gsi_build_id: string = void 0;
-  gsi_pab_account_id: string = void 0;
-  gsi_vendor_version: string = void 0;
-
-  // test suite information
-  test_storage_type: number = void 0;
-  test_branch: string = void 0;
-  test_build_target: string = void 0;
-  test_build_id: string = void 0;
-  test_pab_account_id: string = void 0;
-
-  retry_count: number = void 0;
-
-  infra_log_url: string = void 0;
-
-  image_package_repo_base: string = void 0;
-
-  report_bucket: string = void 0;
-  report_spreadsheet_id: string = void 0;
-
-  timestamp = void 0;
-  heartbeat_stamp = void 0;
-}
diff --git a/gae/frontend/src/app/model/job_wrapper.ts b/gae/frontend/src/app/model/job_wrapper.ts
deleted file mode 100644
index 5a1f915..0000000
--- a/gae/frontend/src/app/model/job_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Job} from './job';
-
-export interface JobWrapper {
-  jobs: Job[];
-  has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/lab.ts b/gae/frontend/src/app/model/lab.ts
deleted file mode 100644
index 0f98360..0000000
--- a/gae/frontend/src/app/model/lab.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Host} from './host';
-
-export class Lab {
-  name: string = void 0;
-  owner: string = void 0;
-  admin: string[] = void 0;
-  hosts: Host[] = void 0;
-}
diff --git a/gae/frontend/src/app/model/schedule.ts b/gae/frontend/src/app/model/schedule.ts
deleted file mode 100644
index 9115a97..0000000
--- a/gae/frontend/src/app/model/schedule.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Schedule {
-  name: string = void 0;
-  schedule_type: string = void 0;
-
-  // device image information
-  build_storage_type: number = void 0;
-  manifest_branch: string = void 0;
-  build_target: string = void 0;
-  device_pab_account_id: string = void 0;
-  require_signed_device_build: boolean = void 0;
-  has_bootloader_img: boolean = void 0;
-  has_radio_img: boolean = void 0;
-
-  // GSI information
-  gsi_storage_type: number = void 0;
-  gsi_branch: string = void 0;
-  gsi_build_target: string = void 0;
-  gsi_pab_account_id: string = void 0;
-  gsi_vendor_version: string = void 0;
-
-  // test suite information
-  test_storage_type: number = void 0;
-  test_branch: string = void 0;
-  test_build_target: string = void 0;
-  test_pab_account_id: string = void 0;
-
-  test_name: string = void 0;
-  period: number = void 0;
-  schedule: string = void 0;
-  priority: string = void 0;
-  device: string[] = void 0;
-  shards: number = void 0;
-  param: string[] = void 0;
-  retry_count: number = void 0;
-
-  required_host_equipment: string[] = void 0;
-  required_device_equipment: string[] = void 0;
-
-  report_bucket: string[] = void 0;
-  report_spreadsheet_id: string[] = void 0;
-  report_persistent_url: string[] = void 0;
-  report_reference_url: string[] = void 0;
-
-  image_package_repo_base: string = void 0;
-  timestamp = void 0;
-  owner: string[] = void 0;
-
-  error_count: number = void 0;
-  suspended: boolean = void 0;
-  urlsafe_key: string = void 0;
-}
-
-export interface ScheduleSuspendResponseWrapper {
-  schedules: ScheduleSuspendResponse[];
-}
-
-export interface ScheduleSuspendResponse {
-  urlsafe_key: string;
-  suspend: boolean;
-}
diff --git a/gae/frontend/src/app/model/schedule_wrapper.ts b/gae/frontend/src/app/model/schedule_wrapper.ts
deleted file mode 100644
index 2dae800..0000000
--- a/gae/frontend/src/app/model/schedule_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Schedule} from './schedule';
-
-export interface ScheduleWrapper {
-  schedules: Schedule[];
-  has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/tslint.json b/gae/frontend/src/app/model/tslint.json
deleted file mode 100644
index eb9bcd8..0000000
--- a/gae/frontend/src/app/model/tslint.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "extends": "../../tslint.json",
-  "rules": {
-    "variable-name": [
-      true,
-      "allow-snake-case"
-    ]
-  }
-}
diff --git a/gae/frontend/src/app/shared/dict.pipe.ts b/gae/frontend/src/app/shared/dict.pipe.ts
deleted file mode 100644
index 44f5933..0000000
--- a/gae/frontend/src/app/shared/dict.pipe.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Pipe, PipeTransform} from '@angular/core';
-
-@Pipe({name: 'dict'})
-export class DictPipe implements PipeTransform {
-  transform(value: Object): any {
-    const dict = [];
-    for (const key in value) {
-      if (value.hasOwnProperty(key)) {
-        dict.push({key: key, value: value[key]});
-      }
-    }
-    return dict;
-  }
-}
diff --git a/gae/frontend/src/app/shared/filter/filter.component.html b/gae/frontend/src/app/shared/filter/filter.component.html
deleted file mode 100644
index 7381359..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<div fxLayout="column" id="filter-wrapper">
-  <mat-expansion-panel id="expansion-panel" (opened)="panelOpenState = true" (closed)="panelOpenState = false" [ngStyle]="{'padding-bottom': (panelOpenState) ? '20px' : '0' }">
-    <mat-expansion-panel-header>
-      <mat-panel-title>
-        Filter
-      </mat-panel-title>
-      <mat-panel-description>
-        {{ panelOpenState ? "" : appliedFilters.length + " filters are applied." }}
-      </mat-panel-description>
-    </mat-expansion-panel-header>
-    <mat-form-field>
-      <mat-select placeholder="Key" [(value)]="currentFilter.key">
-        <mat-option *ngFor="let key of selectorList" [value]="key">
-          {{ key }}
-        </mat-option>
-      </mat-select>
-    </mat-form-field>
-    <mat-form-field>
-      <mat-select [(value)]="currentFilter.method">
-        <mat-option *ngFor="let method of filterMethods" [value]="method.value">
-          {{ method.text }}
-        </mat-option>
-      </mat-select>
-    </mat-form-field>
-    <mat-form-field>
-      <input matInput [(ngModel)]="currentFilter.value">
-    </mat-form-field>
-    <button mat-icon-button (click)="addFilter()" [disabled]="!currentFilter.key || !currentFilter.method || !currentFilter.value">
-      <mat-icon>done</mat-icon>
-    </button>
-    <button mat-icon-button (click)="clearCurrentFilter()">
-      <mat-icon>clear</mat-icon>
-    </button>
-    <mat-chip-list>
-      <mat-chip *ngFor="let filter of applyingFilters" [removable]="true" (removed)="removed(filter)">
-        {{ filter.key }} {{ getSign(filter) }} {{ filter.value }}
-        <mat-icon matChipRemove>cancel</mat-icon>
-      </mat-chip>
-    </mat-chip-list>
-    <div fxLayout="row" id="row_buttons">
-      <button mat-stroked-button (click)="onApplyClicked()" [disabled]="!applyingFilterChanged">
-        <span>Apply</span>
-      </button>
-      <button mat-stroked-button (click)="onCancelChangesClicked()" [disabled]="!applyingFilterChanged">
-        <span>Cancel Changes</span>
-      </button>
-      <button mat-stroked-button (click)="onClearAllClicked()" [disabled]="appliedFilters.length == 0">
-        <span>Clear All</span>
-      </button>
-    </div>
-  </mat-expansion-panel>
-</div>
diff --git a/gae/frontend/src/app/shared/filter/filter.component.scss b/gae/frontend/src/app/shared/filter/filter.component.scss
deleted file mode 100644
index 88ae569..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#filter-wrapper {
-  position: relative;
-
-  mat-form-field {
-    margin-right: 20px;
-  }
-}
-
-#row_buttons {
-  float: right;
-}
-
-.mat-stroked-button {
-  min-width: 80px;
-  min-height: 15px;
-  padding-left: 15px;
-  padding-right: 15px;
-  font-size: 12px;
-  margin-right: 15px;
-}
diff --git a/gae/frontend/src/app/shared/filter/filter.component.ts b/gae/frontend/src/app/shared/filter/filter.component.ts
deleted file mode 100644
index 0ce66fe..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { FilterItem } from '../../model/filter_item';
-import { FilterCondition } from '../../model/filter_condition';
-
-@Component({
-  selector: 'app-filter',
-  templateUrl: './filter.component.html',
-  styleUrls: ['./filter.component.scss']
-})
-export class FilterComponent implements OnInit {
-  currentFilter: FilterItem;
-  applyingFilters: FilterItem[] = [];
-  applyingFilterChanged = false;
-  appliedFilters: FilterItem[] = [];
-  selectorList: string[];
-
-  filterMethods = [
-    {value: FilterCondition.EqualTo, text: 'is equal to', sign: '='},
-    {value: FilterCondition.LessThan, text: 'is less than', sign: '<'},
-    {value: FilterCondition.GreaterThan, text: 'is greater than', sign: '>'},
-    {value: FilterCondition.LessThanOrEqualTo, text: 'is less than or equal to', sign: '<='},
-    {value: FilterCondition.GreaterThanOrEqualTo, text: 'is greater than or equal to', sign: '>='},
-    {value: FilterCondition.NotEqualTo, text: 'is not equal to', sign: '!='},
-    {value: FilterCondition.Has, text: 'has', sign: 'has'},
-  ];
-
-  @Output() applyFilters = new EventEmitter();
-  @Input() disabled: boolean;
-
-  panelOpenState = false;
-
-  ngOnInit(): void {
-    this.currentFilter = new FilterItem();
-    this.currentFilter.value = '';
-  }
-
-  /** Sets a filter key list with the given class. */
-  setSelectorList(typeOfClass: any) {
-    const instance = new typeOfClass();
-    this.selectorList = Object.getOwnPropertyNames(instance);
-  }
-
-  /** Adds the current filter to the list of filters to be applied. */
-  addFilter() {
-    this.applyingFilters.push(this.currentFilter);
-    this.currentFilter = new FilterItem();
-    this.currentFilter.value = '';
-    this.applyingFilterChanged = true;
-  }
-
-  /** Clears the current filter. */
-  clearCurrentFilter() {
-    this.currentFilter.key = undefined;
-    this.currentFilter.method = undefined;
-    this.currentFilter.value = '';
-  }
-
-  /** Removes the selected filter from the list of filters to be applied. */
-  removed(filter: FilterItem) {
-    const index = this.applyingFilters.indexOf(filter);
-    if (index >= 0) {
-      this.applyingFilters.splice(index, 1);
-      this.applyingFilterChanged = true;
-    }
-  }
-
-  /** Gets a filter sign with method value. */
-  getSign(filter: FilterItem) {
-    return this.filterMethods.find((x) => x.value === filter.method).sign;
-  }
-
-  /** Applies the list of filters. */
-  onApplyClicked() {
-    this.applyFilters.emit(this.applyingFilters);
-    this.appliedFilters = this.applyingFilters.slice();
-    this.applyingFilterChanged = false;
-  }
-
-  /** Cancels the current changes and roll back to the last applied filters. */
-  onCancelChangesClicked() {
-    this.applyingFilters = this.appliedFilters.slice();
-    this.applyingFilterChanged = false;
-  }
-
-  /** Reset all filters. */
-  onClearAllClicked() {
-    this.applyingFilters = [];
-    this.appliedFilters = [];
-    this.applyFilters.emit(this.appliedFilters);
-    this.applyingFilterChanged = false;
-  }
-}
diff --git a/gae/frontend/src/app/shared/navbar/_navbar-theme.scss b/gae/frontend/src/app/shared/navbar/_navbar-theme.scss
deleted file mode 100644
index bba0989..0000000
--- a/gae/frontend/src/app/shared/navbar/_navbar-theme.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@mixin nav-bar-theme($theme) {
-  $primary: map-get($theme, primary);
-  $accent: map-get($theme, accent);
-  $warn: map-get($theme, warn);
-  $background: map-get($theme, background);
-  $foreground: map-get($theme, foreground);
-
-  mat-toolbar.main-toolbar {
-    .mat-list-item {
-      color: mat-color($primary, '600-contrast') !important;
-    }
-  }
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.html b/gae/frontend/src/app/shared/navbar/navbar.component.html
deleted file mode 100644
index 7719d56..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<mat-toolbar class="mat-elevation-z6 main-toolbar" color="primary">
-  <mat-nav-list>
-    <a mat-list-item *ngFor="let menu of (menus | dict)" [routerLink]="menu.value">{{ menu.key }}</a>
-  </mat-nav-list>
-  <span class="flex-spacer"></span>
-</mat-toolbar>
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.scss b/gae/frontend/src/app/shared/navbar/navbar.component.scss
deleted file mode 100644
index 5b6dc86..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-mat-toolbar {
-  .mat-list-item {
-    font-family: 'Google Sans', Roboto, sans-serif;
-    text-transform: capitalize;
-  }
-}
-
-.mat-list-item {
-  float: left;
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.ts b/gae/frontend/src/app/shared/navbar/navbar.component.ts
deleted file mode 100644
index 3efe93f..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component } from '@angular/core';
-
-import { MENUS } from '../../menu/menu-items';
-
-@Component({
-  selector: 'app-nav-bar',
-  templateUrl: './navbar.component.html',
-  styleUrls: ['./navbar.component.scss']
-})
-export class NavBarComponent {
-  get menus() {
-    return MENUS;
-  }
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.ts b/gae/frontend/src/app/shared/navbar/navbar.ts
deleted file mode 100644
index 805dcc5..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// Angular modules.
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
-import { RouterModule } from '@angular/router';
-
-// Angular Material modules.
-import { MatButtonModule } from '@angular/material/button';
-import { MatListModule } from '@angular/material/list';
-import { MatToolbarModule } from '@angular/material/toolbar';
-
-// User modules.
-import { DictPipe } from '../dict.pipe';
-import { NavBarComponent } from './navbar.component';
-
-@NgModule({
-  declarations: [
-    DictPipe,
-    NavBarComponent,
-  ],
-  imports: [
-    BrowserModule,
-    MatButtonModule,
-    MatToolbarModule,
-    MatListModule,
-    RouterModule,
-  ],
-  exports: [
-    NavBarComponent,
-  ],
-  providers: [],
-})
-export class NavModule { }
diff --git a/gae/frontend/src/app/shared/servicebase.ts b/gae/frontend/src/app/shared/servicebase.ts
deleted file mode 100644
index 9eaecf8..0000000
--- a/gae/frontend/src/app/shared/servicebase.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient, HttpErrorResponse, HttpParams, HttpResponse } from '@angular/common/http';
-import { Observable, throwError } from 'rxjs';
-
-export class ServiceBase {
-  url: string;
-  protected constructor(public httpClient: HttpClient) {
-  }
-  protected handleError(error: HttpErrorResponse) {
-    if (error.error instanceof ErrorEvent) {
-      // A client-side or network error occurred. Handle it accordingly.
-      console.error('An error occurred:', error.error.message);
-    } else {
-      // The backend returned an unsuccessful response code.
-      // The response body may contain clues as to what went wrong,
-      console.error(
-        `Backend returned code ${error.status}, ` +
-        `body was: ${error.error}`);
-    }
-    // return an observable with a user-facing error message
-    return throwError(error);
-  }
-  public getCount(filterInfo: string): Observable<number> {
-    const url = this.url + 'count';
-    return this.httpClient.post<number>(url, {filter: filterInfo});
-  }
-}
diff --git a/gae/frontend/src/app/shared/vtslab_status.ts b/gae/frontend/src/app/shared/vtslab_status.ts
deleted file mode 100644
index 2836f97..0000000
--- a/gae/frontend/src/app/shared/vtslab_status.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export enum JobStatus {
-  Ready = 0,
-  Leased,
-  Complete,
-  Infra_err,
-  Expired,
-  Bootup_err,
-}
-
-export enum DeviceStatus {
-  Unknown = 0,
-  Fastboot,
-  Online,
-  Ready,
-  Use,
-  Error,
-  No_response,
-}
-
-export enum SchedulingStatus {
-  Free = 0,
-  Reserved,
-  Use,
-}
-
-/**
- * bit 0-1  : version related test type
- *            00 - Unknown
- *            01 - ToT
- *            10 - OTA
- * bit 2    : device signed build
- * bit 3-4  : reserved for gerrit related test type
- *            01 - pre-submit
- * bit 5    : manually created test job
- */
-export enum TestType {
-  Unknown = 0,
-  ToT = 1,
-  OTA = 1 << 1,
-  Signed = 1 << 2,
-  Presubmit = 1 << 3,
-  Manual = 1 << 5,
-}
diff --git a/gae/frontend/src/browserslist b/gae/frontend/src/browserslist
deleted file mode 100644
index 3206b4e..0000000
--- a/gae/frontend/src/browserslist
+++ /dev/null
@@ -1,5 +0,0 @@
-# For autoprefixer to adjust CSS to support the below specified browsers
-> 0.5%
-last 2 versions
-Firefox ESR
-not dead
diff --git a/gae/frontend/src/environments/environment.prod.ts b/gae/frontend/src/environments/environment.prod.ts
deleted file mode 100644
index 8b051e6..0000000
--- a/gae/frontend/src/environments/environment.prod.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const environment = {
-  production: true,
-  baseURL: '/_ah/api',
-};
diff --git a/gae/frontend/src/environments/environment.ts b/gae/frontend/src/environments/environment.ts
deleted file mode 100644
index 387543e..0000000
--- a/gae/frontend/src/environments/environment.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const environment = {
-  production: false,
-  baseURL: 'http://localhost:8080/_ah/api',
-};
diff --git a/gae/frontend/src/favicon.ico b/gae/frontend/src/favicon.ico
deleted file mode 100644
index 8081c7c..0000000
--- a/gae/frontend/src/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/gae/frontend/src/index.html b/gae/frontend/src/index.html
deleted file mode 100644
index 3234be2..0000000
--- a/gae/frontend/src/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html lang="en">
-<head>
-  <meta charset="utf-8">
-  <title>VTSLab Scheduler</title>
-  <base href="/">
-
-  <meta name="viewport" content="width=device-width, initial-scale=1">
-  <link rel="icon" type="image/x-icon" href="favicon.ico">
-  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
-  <link href="https://fonts.googleapis.com/css?family=Google+Sans" rel="stylesheet">
-</head>
-<body>
-  <app-root>Loading...</app-root>
-</body>
-</html>
diff --git a/gae/frontend/src/karma.conf.js b/gae/frontend/src/karma.conf.js
deleted file mode 100644
index b6e0042..0000000
--- a/gae/frontend/src/karma.conf.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Karma configuration file, see link for more information
-// https://karma-runner.github.io/1.0/config/configuration-file.html
-
-module.exports = function (config) {
-  config.set({
-    basePath: '',
-    frameworks: ['jasmine', '@angular-devkit/build-angular'],
-    plugins: [
-      require('karma-jasmine'),
-      require('karma-chrome-launcher'),
-      require('karma-jasmine-html-reporter'),
-      require('karma-coverage-istanbul-reporter'),
-      require('@angular-devkit/build-angular/plugins/karma')
-    ],
-    client: {
-      clearContext: false // leave Jasmine Spec Runner output visible in browser
-    },
-    coverageIstanbulReporter: {
-      dir: require('path').join(__dirname, '../coverage'),
-      reports: ['html', 'lcovonly'],
-      fixWebpackSourcePaths: true
-    },
-    reporters: ['progress', 'kjhtml'],
-    port: 9876,
-    colors: true,
-    logLevel: config.LOG_INFO,
-    autoWatch: true,
-    browsers: ['Chrome'],
-    singleRun: false
-  });
-};
\ No newline at end of file
diff --git a/gae/frontend/src/main.ts b/gae/frontend/src/main.ts
deleted file mode 100644
index 91ec6da..0000000
--- a/gae/frontend/src/main.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { enableProdMode } from '@angular/core';
-import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
-
-import { AppModule } from './app/app.module';
-import { environment } from './environments/environment';
-
-if (environment.production) {
-  enableProdMode();
-}
-
-platformBrowserDynamic().bootstrapModule(AppModule)
-  .catch(err => console.log(err));
diff --git a/gae/frontend/src/polyfills.ts b/gae/frontend/src/polyfills.ts
deleted file mode 100644
index 25a0787..0000000
--- a/gae/frontend/src/polyfills.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// Evergreen browsers require these.
-import 'core-js/es7/reflect';
-
-// Zone JS is required by default for Angular itself.
-import 'zone.js/dist/zone';
diff --git a/gae/frontend/src/styles.scss b/gae/frontend/src/styles.scss
deleted file mode 100644
index 574f294..0000000
--- a/gae/frontend/src/styles.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-@import '~@angular/material/theming';
-@import 'styles/app-theme';
-
-body {
-  margin: 0;
-  font-family: Roboto, sans-serif;
-}
-
-.entity-filter {
-  margin: 20px 20px 0 20px;
-
-  filter {
-    width: 100%;
-  }
-}
-
-.statistics-table {
-  margin: 10px 20px 20px 20px;
-
-  table {
-    width: 100%;
-  }
-}
-
-.mat-card {
-  margin: 20px;
-}
-
-.entity-table {
-  margin: 10px 20px 20px 20px;
-
-  table {
-    width: 100%;
-  }
-}
-
-.loading-spinner {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  top: 0;
-  left: 0;
-  bottom: 0;
-  right: 0;
-  position: fixed;
-}
-
-.div-expandable {
-  padding: 10px 20px 30px 20px;
-
-  button {
-    margin-right: 20px;
-  }
-}
diff --git a/gae/frontend/src/styles/_app-theme.scss b/gae/frontend/src/styles/_app-theme.scss
deleted file mode 100644
index 6c18f48..0000000
--- a/gae/frontend/src/styles/_app-theme.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-@import '~@angular/material/theming';
-@import 'apply-theme';
-@import 'blue-theme';
-
-@include mat-core();
-
-$main-theme: $blue-theme;
-
-$primary: mat-palette($main-theme, 600, 100, 900);
-$accent:  mat-palette($main-theme, A200, A100, A400);
-$app-theme:   mat-light-theme($primary, $accent);
-
-@include angular-material-theme($app-theme);
-@include apply-theme($app-theme);
diff --git a/gae/frontend/src/styles/_apply-theme.scss b/gae/frontend/src/styles/_apply-theme.scss
deleted file mode 100644
index fd5173f..0000000
--- a/gae/frontend/src/styles/_apply-theme.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@import '../app/shared/navbar/navbar-theme';
-
-@mixin apply-theme($theme) {
-  @include nav-bar-theme($theme);
-}
diff --git a/gae/frontend/src/styles/_blue-theme.scss b/gae/frontend/src/styles/_blue-theme.scss
deleted file mode 100644
index 53fd744..0000000
--- a/gae/frontend/src/styles/_blue-theme.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@import '~@angular/material/theming';
-
-$blue-theme: (
-  50: #e8f0fe,
-  100: #d2e3fc,
-  200: #a1c2fa,
-  300: #7baaf7,
-  400: #5e97f6,
-  500: #4285f4,
-  600: #1a73e8,
-  700: #1967d2,
-  800: #185abc,
-  900: #174ea6,
-  A100: #82b1ff,
-  A200: #448aff,
-  A400: #2979ff,
-  A700: #2962ff,
-  contrast: (
-    50: #1a73e8,
-    100: #1a73e8,
-    200: $black-87-opacity,
-    300: $black-87-opacity,
-    400: $black-87-opacity,
-    500: white,
-    600: white,
-    700: white,
-    800: white,
-    900: white,
-    A100: $black-87-opacity,
-    A200: white,
-    A400: white,
-    A700: white,
-  )
-);
diff --git a/gae/frontend/src/test.ts b/gae/frontend/src/test.ts
deleted file mode 100644
index 1631789..0000000
--- a/gae/frontend/src/test.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'zone.js/dist/zone-testing';
-import { getTestBed } from '@angular/core/testing';
-import {
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
-
-declare const require: any;
-
-// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting()
-);
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().map(context);
diff --git a/gae/frontend/src/tsconfig.app.json b/gae/frontend/src/tsconfig.app.json
deleted file mode 100644
index 722c370..0000000
--- a/gae/frontend/src/tsconfig.app.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "extends": "../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "../out-tsc/app",
-    "module": "es2015",
-    "types": []
-  },
-  "exclude": [
-    "src/test.ts",
-    "**/*.spec.ts"
-  ]
-}
diff --git a/gae/frontend/src/tsconfig.spec.json b/gae/frontend/src/tsconfig.spec.json
deleted file mode 100644
index 8f7cede..0000000
--- a/gae/frontend/src/tsconfig.spec.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "extends": "../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "../out-tsc/spec",
-    "module": "commonjs",
-    "types": [
-      "jasmine",
-      "node"
-    ]
-  },
-  "files": [
-    "test.ts",
-    "polyfills.ts"
-  ],
-  "include": [
-    "**/*.spec.ts",
-    "**/*.d.ts"
-  ]
-}
diff --git a/gae/frontend/src/tslint.json b/gae/frontend/src/tslint.json
deleted file mode 100644
index 52e2c1a..0000000
--- a/gae/frontend/src/tslint.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "extends": "../tslint.json",
-    "rules": {
-        "directive-selector": [
-            true,
-            "attribute",
-            "app",
-            "camelCase"
-        ],
-        "component-selector": [
-            true,
-            "element",
-            "app",
-            "kebab-case"
-        ]
-    }
-}
diff --git a/gae/frontend/tsconfig.json b/gae/frontend/tsconfig.json
deleted file mode 100644
index ef44e28..0000000
--- a/gae/frontend/tsconfig.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "compileOnSave": false,
-  "compilerOptions": {
-    "baseUrl": "./",
-    "outDir": "./dist/out-tsc",
-    "sourceMap": true,
-    "declaration": false,
-    "moduleResolution": "node",
-    "emitDecoratorMetadata": true,
-    "experimentalDecorators": true,
-    "target": "es5",
-    "typeRoots": [
-      "node_modules/@types"
-    ],
-    "lib": [
-      "es2017",
-      "dom"
-    ]
-  }
-}
diff --git a/gae/frontend/tslint.json b/gae/frontend/tslint.json
deleted file mode 100644
index 259320f..0000000
--- a/gae/frontend/tslint.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
-  "rulesDirectory": [
-    "node_modules/codelyzer"
-  ],
-  "rules": {
-    "arrow-return-shorthand": true,
-    "callable-types": true,
-    "class-name": true,
-    "comment-format": [
-      true,
-      "check-space"
-    ],
-    "curly": true,
-    "deprecation": {
-      "severity": "warn"
-    },
-    "eofline": true,
-    "forin": true,
-    "import-blacklist": [
-      true,
-      "rxjs/Rx"
-    ],
-    "import-spacing": true,
-    "indent": [
-      true,
-      "spaces"
-    ],
-    "interface-over-type-literal": true,
-    "label-position": true,
-    "max-line-length": [
-      true,
-      140
-    ],
-    "member-access": false,
-    "member-ordering": [
-      true,
-      {
-        "order": [
-          "static-field",
-          "instance-field",
-          "static-method",
-          "instance-method"
-        ]
-      }
-    ],
-    "no-arg": true,
-    "no-bitwise": false,
-    "no-console": [
-      true,
-      "debug",
-      "info",
-      "time",
-      "timeEnd",
-      "trace"
-    ],
-    "no-construct": true,
-    "no-debugger": true,
-    "no-duplicate-super": true,
-    "no-empty": false,
-    "no-empty-interface": true,
-    "no-eval": true,
-    "no-inferrable-types": [
-      true,
-      "ignore-params"
-    ],
-    "no-misused-new": true,
-    "no-non-null-assertion": true,
-    "no-shadowed-variable": true,
-    "no-string-literal": false,
-    "no-string-throw": true,
-    "no-switch-case-fall-through": true,
-    "no-trailing-whitespace": true,
-    "no-unnecessary-initializer": true,
-    "no-unused-expression": true,
-    "no-use-before-declare": true,
-    "no-var-keyword": true,
-    "object-literal-sort-keys": false,
-    "one-line": [
-      true,
-      "check-open-brace",
-      "check-catch",
-      "check-else",
-      "check-whitespace"
-    ],
-    "prefer-const": true,
-    "quotemark": [
-      true,
-      "single"
-    ],
-    "radix": true,
-    "semicolon": [
-      true,
-      "always"
-    ],
-    "triple-equals": [
-      true,
-      "allow-null-check"
-    ],
-    "typedef-whitespace": [
-      true,
-      {
-        "call-signature": "nospace",
-        "index-signature": "nospace",
-        "parameter": "nospace",
-        "property-declaration": "nospace",
-        "variable-declaration": "nospace"
-      }
-    ],
-    "unified-signatures": true,
-    "variable-name": false,
-    "whitespace": [
-      true,
-      "check-branch",
-      "check-decl",
-      "check-operator",
-      "check-separator",
-      "check-type"
-    ],
-    "no-output-on-prefix": true,
-    "use-input-property-decorator": true,
-    "use-output-property-decorator": true,
-    "use-host-property-decorator": true,
-    "no-input-rename": true,
-    "no-output-rename": true,
-    "use-life-cycle-interface": true,
-    "use-pipe-transform-interface": true,
-    "component-class-suffix": true,
-    "directive-class-suffix": true
-  }
-}
diff --git a/gae/hostv1openapi.json b/gae/hostv1openapi.json
deleted file mode 100644
index 35116b2..0000000
--- a/gae/hostv1openapi.json
+++ /dev/null
@@ -1,243 +0,0 @@
-{
-  "basePath": "/_ah/api",
-  "consumes": [
-    "application/json"
-  ],
-  "definitions": {
-    "WebappSrcProtoModelBuildInfoMessage": {
-      "properties": {
-        "artifact_type": {
-          "type": "string"
-        },
-        "artifacts": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "build_id": {
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "build_type": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "signed": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelBuildResponseMessage": {
-      "properties": {
-        "builds": {
-          "description": "A message for representing an individual build entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountRequestMessage": {
-      "properties": {
-        "filter": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountResponseMessage": {
-      "properties": {
-        "count": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDefaultResponse": {
-      "properties": {
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceInfoMessage": {
-      "properties": {
-        "product": {
-          "type": "string"
-        },
-        "scheduling_status": {
-          "format": "int64",
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        },
-        "status": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceResponseMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelGetRequestMessage": {
-      "properties": {
-        "direction": {
-          "type": "string"
-        },
-        "filter": {
-          "type": "string"
-        },
-        "offset": {
-          "format": "int64",
-          "type": "string"
-        },
-        "size": {
-          "format": "int64",
-          "type": "string"
-        },
-        "sort": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelHostInfoMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "host": "vtslab-schedule-prod.appspot.com",
-  "info": {
-    "description": "Endpoint API for host_info.",
-    "title": "host",
-    "version": "v1"
-  },
-  "paths": {
-    "/host/v1/count": {
-      "post": {
-        "operationId": "HostInfoApi_count",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/host/v1/get": {
-      "post": {
-        "operationId": "HostInfoApi_get",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDeviceResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/host/v1/set": {
-      "post": {
-        "operationId": "HostInfoApi_set",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelHostInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    }
-  },
-  "produces": [
-    "application/json"
-  ],
-  "schemes": [
-    "https"
-  ],
-  "securityDefinitions": {
-    "google_id_token": {
-      "authorizationUrl": "",
-      "flow": "implicit",
-      "type": "oauth2",
-      "x-google-issuer": "https://accounts.google.com",
-      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
-    }
-  },
-  "swagger": "2.0",
-  "x-google-api-name": "host"
-}
\ No newline at end of file
diff --git a/gae/index.yaml b/gae/index.yaml
deleted file mode 100644
index edde291..0000000
--- a/gae/index.yaml
+++ /dev/null
@@ -1,112 +0,0 @@
-indexes:
-- kind: DeviceModel
-  ancestor: no
-  properties:
-  - name: hostname
-    direction: asc
-  - name: product
-  - name: serial
-  - name: status
-  - name: scheduling_status
-  - name: timestamp
-
-- kind: BuildModel
-  ancestor: no
-  properties:
-  - name: manifest_branch
-  - name: build_id
-    direction: desc
-  - name: build_target
-  - name: build_type
-  - name: artifact_type
-  - name: artifacts
-  - name: timestamp
-
-- kind: ScheduleModel
-  ancestor: no
-  properties:
-  - name: manifest_branch
-  - name: build_target
-  - name: test_name
-  - name: require_signed_device_build
-  - name: has_bootloader_img
-  - name: has_radio_img
-  - name: period
-  - name: priority
-  - name: priority_value
-  - name: device
-  - name: shards
-  - name: param
-  - name: retry_count
-  - name: gsi_branch
-  - name: gsi_build_target
-  - name: gsi_pab_account_id
-  - name: test_branch
-  - name: test_build_target
-  - name: test_pab_account_id
-  - name: timestamp
-  - name: children_jobs
-  - name: suspended
-  - name: error_count
-  - name: image_package_repo_base
-  - name: required_host_equipment
-  - name: required_device_equipment
-  - name: report_bucket
-  - name: report_spreadsheet_id
-  - name: report_persistent_url
-  - name: report_reference_url
-
-- kind: LabModel
-  ancestor: no
-  properties:
-  - name: name
-  - name: owner
-  - name: admin
-  - name: hostname
-  - name: ip
-  - name: script
-  - name: devices
-  - name: timestamp
-  - name: vtslab_version
-
-- kind: JobModel
-  ancestor: no
-  properties:
-  - name: hostname
-  - name: priority
-  - name: period
-  - name: retry_count
-  - name: test_name
-  - name: device
-  - name: serial
-  - name: manifest_branch
-  - name: build_target
-  - name: shards
-  - name: param
-  - name: build_id
-  - name: status
-  - name: gsi_branch
-  - name: gsi_build_target
-  - name: gsi_pab_account_id
-  - name: test_branch
-  - name: test_build_target
-  - name: test_pab_account_id
-  - name: infra_log_url
-  - name: timestamp
-    direction: desc
-  - name: parent_schedule
-  - name: test_type
-  - name: require_signed_device_build
-  - name: has_bootloader_img
-  - name: has_radio_img
-  - name: image_package_repo_base
-  - name: report_bucket
-  - name: report_spreadsheet_id
-  - name: report_persistent_url
-  - name: report_reference_url
-
-- kind: JobModel
-  properties:
-  - name: hostname
-  - name: timestamp
-    direction: desc
\ No newline at end of file
diff --git a/gae/jobv1openapi.json b/gae/jobv1openapi.json
deleted file mode 100644
index e2badde..0000000
--- a/gae/jobv1openapi.json
+++ /dev/null
@@ -1,718 +0,0 @@
-{
-  "basePath": "/_ah/api",
-  "consumes": [
-    "application/json"
-  ],
-  "definitions": {
-    "WebappSrcProtoModelBuildInfoMessage": {
-      "properties": {
-        "artifact_type": {
-          "type": "string"
-        },
-        "artifacts": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "build_id": {
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "build_type": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "signed": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelBuildResponseMessage": {
-      "properties": {
-        "builds": {
-          "description": "A message for representing an individual build entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountRequestMessage": {
-      "properties": {
-        "filter": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountResponseMessage": {
-      "properties": {
-        "count": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDefaultResponse": {
-      "properties": {
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceInfoMessage": {
-      "properties": {
-        "product": {
-          "type": "string"
-        },
-        "scheduling_status": {
-          "format": "int64",
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        },
-        "status": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceResponseMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelGetRequestMessage": {
-      "properties": {
-        "direction": {
-          "type": "string"
-        },
-        "filter": {
-          "type": "string"
-        },
-        "offset": {
-          "format": "int64",
-          "type": "string"
-        },
-        "size": {
-          "format": "int64",
-          "type": "string"
-        },
-        "sort": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelHostInfoMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelJobLeaseResponse": {
-      "properties": {
-        "jobs": {
-          "description": "A message for representing an individual job entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
-          },
-          "type": "array"
-        },
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelJobMessage": {
-      "properties": {
-        "build_id": {
-          "type": "string"
-        },
-        "build_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "device": {
-          "type": "string"
-        },
-        "gsi_branch": {
-          "type": "string"
-        },
-        "gsi_build_id": {
-          "type": "string"
-        },
-        "gsi_build_target": {
-          "type": "string"
-        },
-        "gsi_pab_account_id": {
-          "type": "string"
-        },
-        "gsi_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "gsi_vendor_version": {
-          "type": "string"
-        },
-        "has_bootloader_img": {
-          "type": "boolean"
-        },
-        "has_radio_img": {
-          "type": "boolean"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "image_package_repo_base": {
-          "type": "string"
-        },
-        "infra_log_url": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "pab_account_id": {
-          "type": "string"
-        },
-        "param": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "period": {
-          "format": "int64",
-          "type": "string"
-        },
-        "priority": {
-          "type": "string"
-        },
-        "report_bucket": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_persistent_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_reference_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_spreadsheet_id": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "require_signed_device_build": {
-          "type": "boolean"
-        },
-        "retry_count": {
-          "format": "int64",
-          "type": "string"
-        },
-        "serial": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "shards": {
-          "format": "int64",
-          "type": "string"
-        },
-        "status": {
-          "format": "int64",
-          "type": "string"
-        },
-        "test_branch": {
-          "type": "string"
-        },
-        "test_build_id": {
-          "type": "string"
-        },
-        "test_build_target": {
-          "type": "string"
-        },
-        "test_name": {
-          "type": "string"
-        },
-        "test_pab_account_id": {
-          "type": "string"
-        },
-        "test_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "test_type": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelJobResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "jobs": {
-          "description": "A message for representing an individual job entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabDeviceInfoMessage": {
-      "properties": {
-        "device_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "product": {
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabHostInfoMessage": {
-      "properties": {
-        "device": {
-          "description": "A message for representing an individual lab host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "script": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabInfoMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "host": {
-          "description": "A message for representing an individual lab's host entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabHostInfoMessage"
-          },
-          "type": "array"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "devices": {
-          "type": "string"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "labs": {
-          "description": "A model for representing a LabModel entity.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelScheduleInfoMessage": {
-      "properties": {
-        "build_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "device": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "device_pab_account_id": {
-          "type": "string"
-        },
-        "gsi_branch": {
-          "type": "string"
-        },
-        "gsi_build_target": {
-          "type": "string"
-        },
-        "gsi_pab_account_id": {
-          "type": "string"
-        },
-        "gsi_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "gsi_vendor_version": {
-          "type": "string"
-        },
-        "has_bootloader_img": {
-          "type": "boolean"
-        },
-        "has_radio_img": {
-          "type": "boolean"
-        },
-        "image_package_repo_base": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "param": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "period": {
-          "format": "int64",
-          "type": "string"
-        },
-        "priority": {
-          "type": "string"
-        },
-        "report_bucket": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_persistent_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_reference_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_spreadsheet_id": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "require_signed_device_build": {
-          "type": "boolean"
-        },
-        "required_device_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "required_host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "retry_count": {
-          "format": "int64",
-          "type": "string"
-        },
-        "schedule": {
-          "type": "string"
-        },
-        "schedule_type": {
-          "type": "string"
-        },
-        "shards": {
-          "format": "int64",
-          "type": "string"
-        },
-        "test_branch": {
-          "type": "string"
-        },
-        "test_build_target": {
-          "type": "string"
-        },
-        "test_name": {
-          "type": "string"
-        },
-        "test_pab_account_id": {
-          "type": "string"
-        },
-        "test_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "timestamp": {
-          "format": "date-time",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelScheduleResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "schedules": {
-          "description": "A message for representing an individual schedule entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelScheduleInfoMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "host": "vtslab-schedule-prod.appspot.com",
-  "info": {
-    "description": "Endpoint API for job_queue.",
-    "title": "job",
-    "version": "v1"
-  },
-  "paths": {
-    "/job/v1/count": {
-      "post": {
-        "operationId": "JobQueueApi_count",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/job/v1/get": {
-      "post": {
-        "operationId": "JobQueueApi_get",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelJobResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/job/v1/heartbeat": {
-      "post": {
-        "operationId": "JobQueueApi_heartbeat",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelJobLeaseResponse"
-            }
-          }
-        }
-      }
-    },
-    "/job/v1/lease": {
-      "post": {
-        "operationId": "JobQueueApi_lease",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelJobLeaseResponse"
-            }
-          }
-        }
-      }
-    }
-  },
-  "produces": [
-    "application/json"
-  ],
-  "schemes": [
-    "https"
-  ],
-  "securityDefinitions": {
-    "google_id_token": {
-      "authorizationUrl": "",
-      "flow": "implicit",
-      "type": "oauth2",
-      "x-google-issuer": "https://accounts.google.com",
-      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
-    }
-  },
-  "swagger": "2.0",
-  "x-google-api-name": "job"
-}
\ No newline at end of file
diff --git a/gae/labv1openapi.json b/gae/labv1openapi.json
deleted file mode 100644
index 37f31d2..0000000
--- a/gae/labv1openapi.json
+++ /dev/null
@@ -1,408 +0,0 @@
-{
-  "basePath": "/_ah/api",
-  "consumes": [
-    "application/json"
-  ],
-  "definitions": {
-    "WebappSrcProtoModelBuildInfoMessage": {
-      "properties": {
-        "artifact_type": {
-          "type": "string"
-        },
-        "artifacts": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "build_id": {
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "build_type": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "signed": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelBuildResponseMessage": {
-      "properties": {
-        "builds": {
-          "description": "A message for representing an individual build entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountRequestMessage": {
-      "properties": {
-        "filter": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountResponseMessage": {
-      "properties": {
-        "count": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDefaultResponse": {
-      "properties": {
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceInfoMessage": {
-      "properties": {
-        "product": {
-          "type": "string"
-        },
-        "scheduling_status": {
-          "format": "int64",
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        },
-        "status": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceResponseMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelGetRequestMessage": {
-      "properties": {
-        "direction": {
-          "type": "string"
-        },
-        "filter": {
-          "type": "string"
-        },
-        "offset": {
-          "format": "int64",
-          "type": "string"
-        },
-        "size": {
-          "format": "int64",
-          "type": "string"
-        },
-        "sort": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelHostInfoMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabDeviceInfoMessage": {
-      "properties": {
-        "device_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "product": {
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabHostInfoMessage": {
-      "properties": {
-        "device": {
-          "description": "A message for representing an individual lab host's device entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "script": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabInfoMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "host": {
-          "description": "A message for representing an individual lab's host entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelLabHostInfoMessage"
-          },
-          "type": "array"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "devices": {
-          "type": "string"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "labs": {
-          "description": "A model for representing a LabModel entity.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelLabMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "host": "vtslab-schedule-prod.appspot.com",
-  "info": {
-    "description": "Endpoint API for lab_info.",
-    "title": "lab",
-    "version": "v1"
-  },
-  "paths": {
-    "/lab/v1/clear": {
-      "post": {
-        "operationId": "LabInfoApi_clear",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelLabInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    },
-    "/lab/v1/count": {
-      "post": {
-        "operationId": "LabInfoApi_count",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/lab/v1/get": {
-      "post": {
-        "operationId": "LabInfoApi_get",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelLabResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/lab/v1/set": {
-      "post": {
-        "operationId": "LabInfoApi_set",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelLabInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    },
-    "/lab/v1/set_version": {
-      "post": {
-        "operationId": "LabInfoApi_setVersion",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelLabHostInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    }
-  },
-  "produces": [
-    "application/json"
-  ],
-  "schemes": [
-    "https"
-  ],
-  "securityDefinitions": {
-    "google_id_token": {
-      "authorizationUrl": "",
-      "flow": "implicit",
-      "type": "oauth2",
-      "x-google-issuer": "https://accounts.google.com",
-      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
-    }
-  },
-  "swagger": "2.0",
-  "x-google-api-name": "lab"
-}
\ No newline at end of file
diff --git a/gae/queue.yaml b/gae/queue.yaml
deleted file mode 100644
index b460b11..0000000
--- a/gae/queue.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-queue:
-- name: queue-schedule
-  mode: push
-  rate: 1/s
-  bucket_size: 5
-  max_concurrent_requests: 1
-  retry_parameters:
-    task_retry_limit: 2
-    min_backoff_seconds: 1
-
-- name: queue-indexing
-  mode: push
-  rate: 1/s
-  bucket_size: 5
-  max_concurrent_requests: 1
-  retry_parameters:
-    task_retry_limit: 7
-    min_backoff_seconds: 1
\ No newline at end of file
diff --git a/gae/requirements.txt b/gae/requirements.txt
deleted file mode 100644
index e8c00fc..0000000
--- a/gae/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-google-api-python-client
-google-endpoints
-
-pytz
-stripe
-
diff --git a/gae/schedulev1openapi.json b/gae/schedulev1openapi.json
deleted file mode 100644
index b1db4e9..0000000
--- a/gae/schedulev1openapi.json
+++ /dev/null
@@ -1,545 +0,0 @@
-{
-  "basePath": "/_ah/api",
-  "consumes": [
-    "application/json"
-  ],
-  "definitions": {
-    "WebappSrcProtoModelBuildInfoMessage": {
-      "properties": {
-        "artifact_type": {
-          "type": "string"
-        },
-        "artifacts": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "build_id": {
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "build_type": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "signed": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelBuildResponseMessage": {
-      "properties": {
-        "builds": {
-          "description": "A message for representing an individual build entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountRequestMessage": {
-      "properties": {
-        "filter": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelCountResponseMessage": {
-      "properties": {
-        "count": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDefaultResponse": {
-      "properties": {
-        "return_code": {
-          "enum": [
-            "SUCCESS",
-            "FAIL"
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceInfoMessage": {
-      "properties": {
-        "product": {
-          "type": "string"
-        },
-        "scheduling_status": {
-          "format": "int64",
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        },
-        "status": {
-          "format": "int64",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelDeviceResponseMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "has_next": {
-          "type": "boolean"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelGetRequestMessage": {
-      "properties": {
-        "direction": {
-          "type": "string"
-        },
-        "filter": {
-          "type": "string"
-        },
-        "offset": {
-          "format": "int64",
-          "type": "string"
-        },
-        "size": {
-          "format": "int64",
-          "type": "string"
-        },
-        "sort": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelHostInfoMessage": {
-      "properties": {
-        "devices": {
-          "description": "A message for representing an individual host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabDeviceInfoMessage": {
-      "properties": {
-        "device_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "product": {
-          "type": "string"
-        },
-        "serial": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabHostInfoMessage": {
-      "properties": {
-        "device": {
-          "description": "A message for representing an individual lab host's device entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
-          },
-          "type": "array"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "script": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabInfoMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "host": {
-          "description": "A message for representing an individual lab's host entry.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabHostInfoMessage"
-          },
-          "type": "array"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabMessage": {
-      "properties": {
-        "admin": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "devices": {
-          "type": "string"
-        },
-        "host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "ip": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "type": "string"
-        },
-        "vtslab_version": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelLabResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "labs": {
-          "description": "A model for representing a LabModel entity.",
-          "items": {
-            "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelScheduleInfoMessage": {
-      "properties": {
-        "build_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "build_target": {
-          "type": "string"
-        },
-        "device": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "device_pab_account_id": {
-          "type": "string"
-        },
-        "gsi_branch": {
-          "type": "string"
-        },
-        "gsi_build_target": {
-          "type": "string"
-        },
-        "gsi_pab_account_id": {
-          "type": "string"
-        },
-        "gsi_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "gsi_vendor_version": {
-          "type": "string"
-        },
-        "has_bootloader_img": {
-          "type": "boolean"
-        },
-        "has_radio_img": {
-          "type": "boolean"
-        },
-        "image_package_repo_base": {
-          "type": "string"
-        },
-        "manifest_branch": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "owner": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "param": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "period": {
-          "format": "int64",
-          "type": "string"
-        },
-        "priority": {
-          "type": "string"
-        },
-        "report_bucket": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_persistent_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_reference_url": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "report_spreadsheet_id": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "require_signed_device_build": {
-          "type": "boolean"
-        },
-        "required_device_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "required_host_equipment": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        },
-        "retry_count": {
-          "format": "int64",
-          "type": "string"
-        },
-        "schedule": {
-          "type": "string"
-        },
-        "schedule_type": {
-          "type": "string"
-        },
-        "shards": {
-          "format": "int64",
-          "type": "string"
-        },
-        "test_branch": {
-          "type": "string"
-        },
-        "test_build_target": {
-          "type": "string"
-        },
-        "test_name": {
-          "type": "string"
-        },
-        "test_pab_account_id": {
-          "type": "string"
-        },
-        "test_storage_type": {
-          "format": "int64",
-          "type": "string"
-        },
-        "timestamp": {
-          "format": "date-time",
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "WebappSrcProtoModelScheduleResponseMessage": {
-      "properties": {
-        "has_next": {
-          "type": "boolean"
-        },
-        "schedules": {
-          "description": "A message for representing an individual schedule entry.",
-          "items": {
-            "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "host": "vtslab-schedule-prod.appspot.com",
-  "info": {
-    "description": "Endpoint API for schedule_info.",
-    "title": "schedule",
-    "version": "v1"
-  },
-  "paths": {
-    "/schedule/v1/clear": {
-      "post": {
-        "operationId": "ScheduleInfoApi_clear",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    },
-    "/schedule/v1/count": {
-      "post": {
-        "operationId": "ScheduleInfoApi_count",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/schedule/v1/get": {
-      "post": {
-        "operationId": "ScheduleInfoApi_get",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelScheduleResponseMessage"
-            }
-          }
-        }
-      }
-    },
-    "/schedule/v1/set": {
-      "post": {
-        "operationId": "ScheduleInfoApi_set",
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "A successful response",
-            "schema": {
-              "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
-            }
-          }
-        }
-      }
-    }
-  },
-  "produces": [
-    "application/json"
-  ],
-  "schemes": [
-    "https"
-  ],
-  "securityDefinitions": {
-    "google_id_token": {
-      "authorizationUrl": "",
-      "flow": "implicit",
-      "type": "oauth2",
-      "x-google-issuer": "https://accounts.google.com",
-      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
-    }
-  },
-  "swagger": "2.0",
-  "x-google-api-name": "schedule"
-}
\ No newline at end of file
diff --git a/gae/script/build.sh b/gae/script/build.sh
deleted file mode 100755
index 6cc6a97..0000000
--- a/gae/script/build.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -ne 1 ]; then
-  echo "usage: build.sh prod|test|public"
-  exit 1
-fi
-
-if [ $1 = "prod" ]; then
-  SERVICE="vtslab-schedule-prod.appspot.com"
-elif [ $1 = "public" ]; then
-  SERVICE="vtslab-schedule.appspot.com"
-else
-  SERVICE="vtslab-schedule-test.appspot.com"
-fi
-
-echo "Building the webapp for $SERVICE ..."
-
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.build_info.BuildInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.host_info.HostInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.schedule_info.ScheduleInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.lab_info.LabInfoApi --hostname $SERVICE
-
-echo "Build complete."
diff --git a/gae/script/create-datastore.sh b/gae/script/create-datastore.sh
deleted file mode 100755
index 1101298..0000000
--- a/gae/script/create-datastore.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-gcloud datastore create-indexes index.yaml
diff --git a/gae/script/deploy-endpoint.sh b/gae/script/deploy-endpoint.sh
deleted file mode 100755
index a6cf10b..0000000
--- a/gae/script/deploy-endpoint.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -ne 1 ]; then
-  echo "usage: deploy-endpoint.sh prod|test|public"
-  exit 1
-fi
-
-if [ $1 = "public" ]; then
-  SERVICE="vtslab-schedule"
-else
-  SERVICE="vtslab-schedule-$1"
-fi
-
-echo "Creating OpenAPI spec files for $SERVICE.appspot.com ..."
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.build_info.BuildInfoApi webapp.src.endpoint.host_info.HostInfoApi webapp.src.endpoint.lab_info.LabInfoApi webapp.src.endpoint.schedule_info.ScheduleInfoApi webapp.src.endpoint.job_queue.JobQueueApi --hostname $SERVICE.appspot.com --x-google-api-name
-
-echo "Depolying the endpoint API implementation to $SERVICE ..."
-
-gcloud endpoints services deploy buildv1openapi.json hostv1openapi.json labv1openapi.json schedulev1openapi.json jobv1openapi.json --project=$SERVICE
-gcloud endpoints configs list --service=$SERVICE.appspot.com
-
-echo "Deployment done!"
diff --git a/gae/script/deploy-webapp.sh b/gae/script/deploy-webapp.sh
deleted file mode 100755
index 187ee7d..0000000
--- a/gae/script/deploy-webapp.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -lt 1 ]; then
-  echo "usage: deploy-webapp.sh prod|test|public|local [deploy options]"
-  exit 1
-fi
-
-NPM_PATH=$(which npm)
-NG_PATH=$(which ng)
-if [ ! -f "${NPM_PATH}" ]; then
-  echo "Cannot find npm in your PATH."
-  echo "Please install node.js and npm to deploy frontend."
-  exit 0
-fi
-if [ ! -f "${NG_PATH}" ]; then
-  echo "Cannot find Angular CLI in your PATH."
-  echo "Please install Angular CLI to deploy frontend."
-  exit 0
-fi
-
-pushd frontend
-echo "Installing frontend dependencies..."
-npm install
-
-echo "Removing files in dist directory..."
-rm -r dist/*
-
-echo "Building frontend codes..."
-if [ $1 = "local" ]; then
-  ng build
-else
-  ng build --prod
-fi
-popd
-
-echo "Copying frontend files to webapp/static directory..."
-rm -rf webapp/static/
-mkdir webapp/static
-cp -r frontend/dist/* webapp/static/
-
-if [ $1 = "public" ]; then
-  SERVICE="vtslab-schedule"
-elif [ $1 = "local" ]; then
-  dev_appserver.py ./
-  exit 0
-else
-  SERVICE="vtslab-schedule-$1"
-fi
-
-echo "Fetching endpoints service version of $SERVICE ..."
-ENDPOINTS=$(gcloud endpoints configs list --service=$SERVICE.appspot.com)
-arr=($ENDPOINTS)
-
-if [ ${#arr[@]} -lt 4 ]; then
-  echo "You need to deploy endpoints first."
-  exit 0
-else
-  VERSION=${arr[2]}
-  NAME=${arr[3]}
-  echo "ENDPOINTS_SERVICE_NAME: $NAME"
-  echo "ENDPOINTS_SERVICE_VERSION: $VERSION"
-fi
-
-echo "Updating app.yaml ..."
-if [ "$(uname)" == "Darwin" ]; then
-  sed -i "" "s/ENDPOINTS_SERVICE_NAME:.*/ENDPOINTS_SERVICE_NAME: $NAME/g" app.yaml
-  sed -i "" "s/ENDPOINTS_SERVICE_VERSION:.*/ENDPOINTS_SERVICE_VERSION: $VERSION/g" app.yaml
-else
-  sed -i "s/ENDPOINTS_SERVICE_NAME:.*/ENDPOINTS_SERVICE_NAME: $NAME/g" app.yaml
-  sed -i "s/ENDPOINTS_SERVICE_VERSION:.*/ENDPOINTS_SERVICE_VERSION: $VERSION/g" app.yaml
-fi
-
-echo "Deploying the web app to $SERVICE ..."
-
-gcloud app deploy app.yaml cron.yaml index.yaml queue.yaml worker.yaml --project=$SERVICE ${@:2}
-
-echo "Deployment done!"
diff --git a/gae/script/install-pip.sh b/gae/script/install-pip.sh
deleted file mode 100755
index 39601d6..0000000
--- a/gae/script/install-pip.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-pip install -t lib -r requirements.txt
diff --git a/gae/testing/README.md b/gae/testing/README.md
deleted file mode 100644
index e567288..0000000
--- a/gae/testing/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## E2E Test
-
-A Makefile is provided to deploy and run the e2e test.
-
-To run:
-
-     export GAE_PROJECT=your-project-id
-     make
-
-To manually run, install the requirements
-
-    pip install -r e2e/requirements-dev.txt
-
-Finally, run the test
-
-    python e2e/test_e2e.py
diff --git a/gae/testing/e2e_test.py b/gae/testing/e2e_test.py
deleted file mode 100644
index 3305862..0000000
--- a/gae/testing/e2e_test.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""App Engine local test runner.
-
-This program handles properly importing the App Engine SDK so that test modules
-can use google.appengine.* APIs and the Google App Engine testbed.
-
-Example invocation:
-
-    $ python testrunner.py [--sdk-path ~/google-cloud-sdk]
-"""
-
-import argparse
-import os
-import subprocess
-import sys
-import unittest
-
-
-def ExecuteOneShellCommand(cmd):
-    """Executes one shell command and returns (stdout, stderr, exit_code).
-
-    Args:
-        cmd: string, a shell command.
-
-    Returns:
-        tuple(string, string, int), containing stdout, stderr, exit_code of
-        the shell command.
-    """
-    p = subprocess.Popen(
-        str(cmd), shell=True,
-        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    stdout, stderr = p.communicate()
-    return (stdout, stderr, p.returncode)
-
-
-def fixup_paths(path):
-    """Adds GAE SDK path to system path and appends it to the google path
-    if that already exists."""
-    # Not all Google packages are inside namespace packages, which means
-    # there might be another non-namespace package named `google` already on
-    # the path and simply appending the App Engine SDK to the path will not
-    # work since the other package will get discovered and used first.
-    # This emulates namespace packages by first searching if a `google` package
-    # exists by importing it, and if so appending to its module search path.
-    try:
-        import google
-        google.__path__.append("{0}/google".format(path))
-    except ImportError:
-        pass
-
-    sys.path.insert(0, path)
-
-
-def main(sdk_path, test_path, test_pattern):
-
-    if not sdk_path:
-        # Get sdk path by running gcloud command.
-        stdout, stderr, _ = ExecuteOneShellCommand(
-            "gcloud info --format='value(installation.sdk_root)'")
-
-        if stderr:
-            print("Cannot find google cloud sdk path.")
-            return 1
-        sdk_path = str.strip(stdout)
-
-    # If the SDK path points to a Google Cloud SDK installation
-    # then we should alter it to point to the GAE platform location.
-    if os.path.exists(os.path.join(sdk_path, 'platform/google_appengine')):
-        sdk_path = os.path.join(sdk_path, 'platform/google_appengine')
-
-    # Make sure google.appengine.* modules are importable.
-    fixup_paths(sdk_path)
-
-    # Make sure all bundled third-party packages are available.
-    import dev_appserver
-    dev_appserver.fix_sys_path()
-
-    # Loading appengine_config from the current project ensures that any
-    # changes to configuration there are available to all tests (e.g.
-    # sys.path modifications, namespaces, etc.)
-    try:
-        import appengine_config
-        (appengine_config)
-    except ImportError:
-        print('Note: unable to import appengine_config.')
-
-    # Discover and run tests.
-    suite = unittest.loader.TestLoader().discover(test_path, test_pattern)
-    print('Suite', suite)
-    return unittest.TextTestRunner(verbosity=2).run(suite)
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser(
-        description=__doc__,
-        formatter_class=argparse.RawDescriptionHelpFormatter)
-    parser.add_argument(
-        '--sdk_path',
-        help='The path to the Google App Engine SDK or the Google Cloud SDK.',
-        default=None)
-    parser.add_argument(
-        '--test-path',
-        help='The path to look for tests, defaults to the current directory.',
-        default=os.getcwd())
-    parser.add_argument(
-        '--test-pattern',
-        help='The file pattern for test modules, defaults to *_test.py.',
-        default='*_test.py')
-
-    args = parser.parse_args()
-
-    result = main(args.sdk_path, args.test_path, args.test_pattern)
-
-    if not result.wasSuccessful():
-        sys.exit(1)
diff --git a/gae/testing/requirements-dev.txt b/gae/testing/requirements-dev.txt
deleted file mode 100644
index ca0dee4..0000000
--- a/gae/testing/requirements-dev.txt
+++ /dev/null
@@ -1 +0,0 @@
-requests==2.9.1
diff --git a/gae/testing/test-endpoint.sh b/gae/testing/test-endpoint.sh
deleted file mode 100755
index 66e5cfc..0000000
--- a/gae/testing/test-endpoint.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-curl -H "Content-Type: application/json" -X POST -d '{"devices": [{"serial": "123", "product": "myfish", "serial": "myserial", "status": 1}], "hostname": "hc1"}' https://vtslab-schedule-prod.appspot.com/_ah/api/host_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"manifest_branch": "master", "build_id": "a2131", "build_target": "sailfish", "build_type": "userdebug"}' https://vtslab-schedule-prod.appspot.com/_ah/api/build_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"device": [{"index": 1}], "host_name": "hc1"}' https://vtslab-schedule-prod.appspot.com/_ah/api/host_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"hostname": "vtslab-mtv43-2"}' https://vtslab-schedule-prod.appspot.com/_ah/api/job_queue/v1/get
diff --git a/gae/testing/test_e2e.py b/gae/testing/test_e2e.py
deleted file mode 100644
index 567c8ce..0000000
--- a/gae/testing/test_e2e.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-import requests
-
-URL = os.environ.get("URL")
-
-
-def test_e2e():
-    assert URL
-    print ("Running test against {}".format(URL))
-    r = requests.get(URL)
-    assert b'VTS' in r.content
-    print("Success")
-
-if __name__ == "__main__":
-    test_e2e()
diff --git a/gae/webapp/__init__.py b/gae/webapp/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/__init__.py b/gae/webapp/src/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/endpoint/__init__.py b/gae/webapp/src/endpoint/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/endpoint/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/endpoint/build_info.py b/gae/webapp/src/endpoint/build_info.py
deleted file mode 100644
index 0ba77bb..0000000
--- a/gae/webapp/src/endpoint/build_info.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Build Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-
-BUILD_INFO_RESOURCE = endpoints.ResourceContainer(model.BuildInfoMessage)
-
-
-@endpoints.api(name="build", version="v1")
-class BuildInfoApi(endpoint_base.EndpointBase):
-    """Endpoint API for build_info."""
-
-    @endpoints.method(
-        BUILD_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="set",
-        http_method="POST",
-        name="set")
-    def set(self, request):
-        """Sets the build info based on the `request`."""
-        build_query = model.BuildModel.query(
-            model.BuildModel.build_id == request.build_id,
-            model.BuildModel.build_target == request.build_target,
-            model.BuildModel.build_type == request.build_type,
-            model.BuildModel.artifact_type == request.artifact_type)
-        existing_builds = build_query.fetch()
-
-        if existing_builds and len(existing_builds) > 1:
-            logging.warning(
-                "Duplicated builds found for [build_id]{} "
-                "[build_target]{} [build_type]{} [artifact_type]{}".format(
-                    request.build_id, request.build_target, request.build_type,
-                    request.artifact_type))
-
-        if existing_builds:
-            build = existing_builds[0]
-            if request.signed:
-                # only signed builds need to overwrite the exist entities.
-                build.signed = request.signed
-        else:
-            build = model.BuildModel()
-            common_attributes = self.GetCommonAttributes(request,
-                                                         model.BuildModel)
-            for attr in common_attributes:
-                setattr(build, attr, getattr(request, attr))
-
-        build.timestamp = datetime.datetime.now()
-        build.put()
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        endpoint_base.GET_REQUEST_RESOURCE,
-        model.BuildResponseMessage,
-        path="get",
-        http_method="POST",
-        name="get")
-    def get(self, request):
-        """Gets the builds from datastore."""
-        return_list, more = self.Get(request=request,
-                                     metaclass=model.BuildModel,
-                                     message=model.BuildInfoMessage)
-        return model.BuildResponseMessage(builds=return_list, has_next=more)
-
-    @endpoints.method(
-        endpoint_base.COUNT_REQUEST_RESOURCE,
-        model.CountResponseMessage,
-        path="count",
-        http_method="POST",
-        name="count")
-    def count(self, request):
-        """Gets total number of BuildModel entities stored in datastore."""
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=model.BuildModel)
-        count = self.Count(metaclass=model.BuildModel, filters=filters)
-
-        return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/build_info_test.py b/gae/webapp/src/endpoint/build_info_test.py
deleted file mode 100644
index 8b70831..0000000
--- a/gae/webapp/src/endpoint/build_info_test.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src.endpoint import build_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class BuildInfoTest(unittest_base.UnitTestBase):
-    """A class to test build_info endpoint API."""
-
-    def setUp(self):
-        """Initializes test"""
-        super(BuildInfoTest, self).setUp()
-
-    def testSetNewBuildModel(self):
-        """Asserts build_info/set API receives a new build."""
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 0)
-        container = (
-            build_info.BUILD_INFO_RESOURCE.combined_message_class(
-                manifest_branch=self.GetRandomString(),
-                build_id=self.GetRandomString(),
-                build_target=self.GetRandomString(),
-                build_type=self.GetRandomString(),
-                artifact_type=self.GetRandomString(),
-            ))
-        api = build_info.BuildInfoApi()
-        response = api.set(container)
-
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 1)
-
-    def testSetDuplicatedBuildModel(self):
-        """Asserts build_info/set API receives a duplicated build."""
-        manifest_branch = self.GetRandomString()
-        build_id = self.GetRandomString()
-        build_target = self.GetRandomString()
-        build_type = self.GetRandomString()
-        artifact_type = self.GetRandomString()
-
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 0)
-        container = (
-            build_info.BUILD_INFO_RESOURCE.combined_message_class(
-                manifest_branch=manifest_branch,
-                build_id=build_id,
-                build_target=build_target,
-                build_type=build_type,
-                artifact_type=artifact_type,
-            ))
-        api = build_info.BuildInfoApi()
-        response = api.set(container)
-
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 1)
-
-        container = (
-            build_info.BUILD_INFO_RESOURCE.combined_message_class(
-                manifest_branch=manifest_branch,
-                build_id=build_id,
-                build_target=build_target,
-                build_type=build_type,
-                artifact_type=artifact_type,
-            ))
-        api = build_info.BuildInfoApi()
-        response = api.set(container)
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 1)
-
-    def testUpdateSignedBuildModel(self):
-        """Asserts build_info/set API receives a duplicated build."""
-        manifest_branch = self.GetRandomString()
-        build_id = self.GetRandomString()
-        build_target = self.GetRandomString()
-        build_type = self.GetRandomString()
-        artifact_type = self.GetRandomString()
-
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 0)
-        container = (
-            build_info.BUILD_INFO_RESOURCE.combined_message_class(
-                manifest_branch=manifest_branch,
-                build_id=build_id,
-                build_target=build_target,
-                build_type=build_type,
-                artifact_type=artifact_type,
-                signed=False,
-            ))
-        api = build_info.BuildInfoApi()
-        response = api.set(container)
-
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 1)
-
-        container = (
-            build_info.BUILD_INFO_RESOURCE.combined_message_class(
-                manifest_branch=manifest_branch,
-                build_id=build_id,
-                build_target=build_target,
-                build_type=build_type,
-                artifact_type=artifact_type,
-                signed=True
-            ))
-        api = build_info.BuildInfoApi()
-        response = api.set(container)
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-        builds = model.BuildModel.query().fetch()
-        self.assertEqual(len(builds), 1)
-        self.assertEqual(builds[0].signed, True)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint/endpoint_base.py b/gae/webapp/src/endpoint/endpoint_base.py
deleted file mode 100644
index d0dddd5..0000000
--- a/gae/webapp/src/endpoint/endpoint_base.py
+++ /dev/null
@@ -1,330 +0,0 @@
-# Copyright 2018 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import datetime
-import inspect
-import logging
-import json
-
-import endpoints
-from protorpc import messages
-from protorpc import remote
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-
-MAX_QUERY_SIZE = 1000
-
-COUNT_REQUEST_RESOURCE = endpoints.ResourceContainer(model.CountRequestMessage)
-GET_REQUEST_RESOURCE = endpoints.ResourceContainer(model.GetRequestMessage)
-
-
-class EndpointBase(remote.Service):
-    """A base class for endpoint implementation."""
-
-    def GetCommonAttributes(self, resource, reference):
-        """Gets a list of common attribute names.
-
-        This method finds the attributes assigned in 'resource' instance, and
-        filters out if the attributes are not a member of 'reference' class.
-
-        Args:
-            resource: either a protorpc.messages.Message instance,
-                      or a ndb.Model instance.
-            reference: either a protorpc.messages.Message class,
-                       or a ndb.Model class.
-
-        Returns:
-            a list of string, attribute names exist on resource and reference.
-
-        Raises:
-            ValueError if resource or reference is not supported class.
-        """
-        # check resource type and absorb list of assigned attributes.
-        resource_attrs = self.GetAttributes(resource, assigned_only=True)
-        reference_attrs = self.GetAttributes(reference)
-        return [x for x in resource_attrs if x in reference_attrs]
-
-    def GetAttributes(self, value, assigned_only=False):
-        """Gets a list of attributes.
-
-        Args:
-            value: a class instance or a class itself.
-            assigned_only: True to get only assigned attributes when value is
-                           an instance, False to get all attributes.
-
-        Raises:
-            ValueError if value is not supported class.
-        """
-        attrs = []
-        if inspect.isclass(value):
-            if assigned_only:
-                logging.warning(
-                    "Please use a class instance for 'resource' argument.")
-
-            if (issubclass(value, messages.Message)
-                    or issubclass(value, ndb.Model)):
-                attrs = [
-                    x[0] for x in value.__dict__.items()
-                    if not x[0].startswith("_")
-                ]
-            else:
-                raise ValueError("Only protorpc.messages.Message or ndb.Model "
-                                 "class are supported.")
-        else:
-            if isinstance(value, messages.Message):
-                attrs = [
-                    x.name for x in value.all_fields()
-                    if not assigned_only or (
-                        value.get_assigned_value(x.name) not in [None, []])
-                ]
-            elif isinstance(value, ndb.Model):
-                attrs = [
-                    x for x in list(value.to_dict())
-                    if not assigned_only or (
-                        getattr(value, x, None) not in [None, []])
-                ]
-            else:
-                raise ValueError("Only protorpc.messages.Message or ndb.Model "
-                                 "class are supported.")
-
-        return attrs
-
-    def Count(self, metaclass, filters=None):
-        """Counts entities from datastore with options.
-
-        Args:
-            metaclass: a metaclass for ndb model.
-            filters: a list of tuples. Each tuple consists of three values:
-                     key, method, and value.
-
-        Returns:
-            a number of entities.
-        """
-        query, _ = self.CreateQueryFilter(metaclass=metaclass, filters=filters)
-        return query.count()
-
-    def Fetch(self,
-              metaclass,
-              size,
-              offset=0,
-              filters=None,
-              sort_key="",
-              direction="asc"):
-        """Fetches entities from datastore with options.
-
-        Args:
-            metaclass: a metaclass for ndb model.
-            size: an integer, max number of entities to fetch at once.
-            offset: an integer, number of query results to skip.
-            filters: a list of filter tuple, a form of (key: string,
-                     method: integer, value: string).
-            sort_key: a string, key name to sort by.
-            direction: a string, "asc" for ascending order and "desc" for
-                       descending order.
-
-        Returns:
-            a list of fetched entities.
-            a boolean, True if there is next page or False if not.
-        """
-        query, empty_repeated_field = self.CreateQueryFilter(
-            metaclass=metaclass, filters=filters)
-        sorted_query = self.SortQuery(
-            query=query,
-            metaclass=metaclass,
-            sort_key=sort_key,
-            direction=direction)
-
-        if size:
-            entities, _, more = sorted_query.fetch_page(
-                page_size=size, offset=offset)
-        else:
-            entities = sorted_query.fetch()
-            more = False
-
-        if empty_repeated_field:
-            entities = [
-                x for x in entities
-                if all([not getattr(x, attr) for attr in empty_repeated_field])
-            ]
-
-        return entities, more
-
-    def CreateQueryFilter(self, metaclass, filters):
-        """Creates a query with the given filters.
-
-        Args:
-            metaclass: a metaclass for ndb model.
-            filters: a list of tuples. Each tuple consists of three values:
-                     key, method, and value.
-
-        Returns:
-            a filtered query for the given metaclass.
-            a list of strings that failed to create the query due to its empty
-            value for the repeated property.
-        """
-        empty_repeated_field = []
-        query = metaclass.query()
-        if not filters:
-            return query, empty_repeated_field
-
-        for _filter in filters:
-            property_key = _filter["key"]
-            method = _filter["method"]
-            value = _filter["value"]
-            if type(value) is str or type(value) is unicode:
-                if isinstance(metaclass._properties[property_key],
-                              ndb.BooleanProperty):
-                    value = value.lower() in ("yes", "true", "1")
-                elif isinstance(metaclass._properties[property_key],
-                                ndb.IntegerProperty):
-                    value = int(value)
-            if metaclass._properties[property_key]._repeated:
-                if value:
-                    value = [value]
-                    if method == Status.FILTER_METHOD[Status.FILTER_Has]:
-                        query = query.filter(
-                            getattr(metaclass, property_key).IN(value))
-                    else:
-                        logging.warning(
-                            "You cannot compare repeated "
-                            "properties except 'IN(has)' operation.")
-                else:
-                    logging.debug("Empty repeated list cannot be queried.")
-                    empty_repeated_field.append(value)
-            elif isinstance(metaclass._properties[property_key],
-                            ndb.DateTimeProperty):
-                if method == Status.FILTER_METHOD[Status.FILTER_LessThan]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) < datetime.datetime.
-                        now() - datetime.timedelta(hours=int(value)))
-                elif method == Status.FILTER_METHOD[Status.FILTER_GreaterThan]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) > datetime.datetime.
-                        now() - datetime.timedelta(hours=int(value)))
-                else:
-                    logging.debug("DateTimeProperty only allows <=(less than) "
-                                  "and >=(greater than) operation.")
-            else:
-                if method == Status.FILTER_METHOD[Status.FILTER_EqualTo]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) == value)
-                elif method == Status.FILTER_METHOD[Status.FILTER_LessThan]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) < value)
-                elif method == Status.FILTER_METHOD[Status.FILTER_GreaterThan]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) > value)
-                elif method == Status.FILTER_METHOD[
-                        Status.FILTER_LessThanOrEqualTo]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) <= value)
-                elif method == Status.FILTER_METHOD[
-                        Status.FILTER_GreaterThanOrEqualTo]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) >= value)
-                elif method == Status.FILTER_METHOD[Status.FILTER_NotEqualTo]:
-                    query = query.filter(
-                        getattr(metaclass, property_key) != value).order(
-                            getattr(metaclass, property_key), metaclass.key)
-                elif method == Status.FILTER_METHOD[Status.FILTER_Has]:
-                    query = query.filter(
-                        getattr(metaclass, property_key).IN(value)).order(
-                            getattr(metaclass, property_key), metaclass.key)
-                else:
-                    logging.warning(
-                        "{} is not supported filter method.".format(method))
-        return query, empty_repeated_field
-
-    def SortQuery(self, query, metaclass, sort_key, direction):
-        """Sorts the given query with sort_key and direction.
-
-        Args:
-            query: a ndb query to sort.
-            metaclass: a metaclass for ndb model.
-            sort_key: a string, key name to sort by.
-            direction: a string, "asc" for ascending order and "desc" for
-                       descending order.
-        """
-        if sort_key:
-            if direction == "desc":
-                query = query.order(-getattr(metaclass, sort_key))
-            else:
-                query = query.order(getattr(metaclass, sort_key))
-
-        return query
-
-    def CreateFilterList(self, filter_string, metaclass):
-        """Creates a list of filters.
-
-        Args:
-            filter_string: a string, stringified JSON which contains 'key',
-                           'method', 'value' to build filter information.
-            metaclass: a metaclass for ndb model.
-
-        Returns:
-            a list of tuples where each tuple consists of three values:
-            key, method, and value.
-        """
-        model_properties = self.GetAttributes(metaclass)
-        filters = []
-        if filter_string:
-            filters = json.loads(filter_string)
-            for _filter in filters:
-                if _filter["key"] not in model_properties:
-                    filters.remove(_filter)
-        return filters
-
-    def Get(self, request, metaclass, message):
-        """Handles a request through /get endpoints API to retrieves entities.
-
-        Args:
-            request: a request body message received through /get API.
-            metaclass: a metaclass for ndb model. This method will fetch the
-                       'metaclass' type of model from datastore.
-            message: a Protocol RPC message class. Fetched entities will be
-                     converted to this message class instances.
-
-        Returns:
-            a list of fetched entities.
-            a boolean, True if there is next page or False if not.
-        """
-        size = request.size if request.size else MAX_QUERY_SIZE
-        offset = request.offset if request.offset else 0
-
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=metaclass)
-
-        entities, more = self.Fetch(
-            metaclass=metaclass,
-            size=size,
-            filters=filters,
-            offset=offset,
-            sort_key=request.sort,
-            direction=request.direction,
-        )
-
-        return_list = []
-        for entity in entities:
-            entity_dict = {}
-            assigned_attributes = self.GetCommonAttributes(
-                resource=entity, reference=message)
-            for attr in assigned_attributes:
-                entity_dict[attr] = getattr(entity, attr, None)
-            if hasattr(message, "urlsafe_key"):
-                entity_dict["urlsafe_key"] = entity.key.urlsafe()
-            return_list.append(entity_dict)
-
-        return return_list, more
diff --git a/gae/webapp/src/endpoint/endpoint_base_test.py b/gae/webapp/src/endpoint/endpoint_base_test.py
deleted file mode 100644
index 2eb397a..0000000
--- a/gae/webapp/src/endpoint/endpoint_base_test.py
+++ /dev/null
@@ -1,256 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import endpoints
-import json
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class EndpointBaseTest(unittest_base.UnitTestBase):
-    """A class to test endpoint_base.EndpointBase class.
-
-    Attributes:
-        eb: An EndpointBase class instance.
-    """
-
-    def setUp(self):
-        """Initializes test"""
-        super(EndpointBaseTest, self).setUp()
-        self.eb = endpoint_base.EndpointBase()
-
-    def testGetAssignedMessagesAttributes(self):
-        attrs = ["hostname", "priority", "test_branch"]
-        job_message = model.JobMessage()
-        for attr in attrs:
-            setattr(job_message, attr, attr)
-        result = self.eb.GetAttributes(job_message, assigned_only=True)
-        self.assertEqual(set(attrs), set(result))
-
-    def testGetAssignedModelAttributes(self):
-        attrs = ["hostname", "priority", "test_branch"]
-        job = model.JobModel()
-        for attr in attrs:
-            setattr(job, attr, attr)
-        result = self.eb.GetAttributes(job, assigned_only=True)
-        self.assertEqual(set(attrs), set(result))
-
-    def testGetAllMessagesAttributes(self):
-        attrs = ["hostname", "priority", "test_branch"]
-        full_attrs = [
-            "test_type", "hostname", "priority", "test_name",
-            "require_signed_device_build", "has_bootloader_img",
-            "has_radio_img", "device", "serial", "build_storage_type",
-            "manifest_branch", "build_target", "build_id", "pab_account_id",
-            "shards", "param", "status", "period", "gsi_storage_type",
-            "gsi_branch", "gsi_build_target", "gsi_build_id",
-            "gsi_pab_account_id", "gsi_vendor_version", "test_storage_type",
-            "test_branch", "test_build_target", "test_build_id",
-            "test_pab_account_id", "retry_count", "infra_log_url",
-            "image_package_repo_base", "report_bucket",
-            "report_spreadsheet_id", "report_persistent_url",
-            "report_reference_url"
-        ]
-        job_message = model.JobMessage()
-        for attr in attrs:
-            setattr(job_message, attr, attr)
-        result = self.eb.GetAttributes(job_message, assigned_only=False)
-        self.assertTrue(set(full_attrs) <= set(result))
-
-    def testGetAllModelAttributes(self):
-        attrs = ["hostname", "priority", "test_branch"]
-        full_attrs = [
-            "test_type", "hostname", "priority", "test_name",
-            "require_signed_device_build", "has_bootloader_img",
-            "has_radio_img", "device", "serial", "build_storage_type",
-            "manifest_branch", "build_target", "build_id", "pab_account_id",
-            "shards", "param", "status", "period", "gsi_storage_type",
-            "gsi_branch", "gsi_build_target", "gsi_build_id",
-            "gsi_pab_account_id", "gsi_vendor_version", "test_storage_type",
-            "test_branch", "test_build_target", "test_build_id",
-            "test_pab_account_id", "timestamp", "heartbeat_stamp",
-            "retry_count", "infra_log_url", "parent_schedule",
-            "image_package_repo_base", "report_bucket",
-            "report_spreadsheet_id", "report_persistent_url",
-            "report_reference_url"
-        ]
-        job = model.JobModel()
-        for attr in attrs:
-            setattr(job, attr, attr)
-        result = self.eb.GetAttributes(job, assigned_only=False)
-        self.assertTrue(set(full_attrs) <= set(result))
-
-    def testGetSingleEntity(self):
-        """Asserts to get a single entity."""
-        device = self.GenerateDeviceModel()
-        device.put()
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=0,
-                offset=0,
-                filter="",
-                sort="",
-                direction="",
-            ))
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 1)
-        self.assertFalse(more)
-
-    def testGetHundredEntities(self):
-        """Asserts to get hundred entities."""
-        for _ in xrange(100):
-            device = self.GenerateDeviceModel()
-            device.put()
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=0,
-                offset=0,
-                filter="",
-                sort="",
-                direction="",
-            ))
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 100)
-        self.assertFalse(more)
-
-    def testGetEntitiesWithPagination(self):
-        """Asserts to get entities with pagination."""
-        for _ in xrange(100):
-            device = self.GenerateDeviceModel()
-            device.put()
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=60,
-                offset=0,
-                filter="",
-                sort="",
-                direction="",
-            ))
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 60)
-        self.assertTrue(more)
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=100,
-                offset=60,
-                filter="",
-                sort="",
-                direction="",
-            ))
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 40)
-        self.assertFalse(more)
-
-    def testGetWithFilter(self):
-        """Asserts to get entities with filter."""
-        for _ in xrange(50):
-            device = self.GenerateDeviceModel()
-            device.put()
-
-        for _ in xrange(50):
-            device = self.GenerateDeviceModel(product="product")
-            device.put()
-
-        filter = [{
-            "key": "product",
-            "method": Status.FILTER_METHOD[Status.FILTER_EqualTo],
-            "value": "product"
-        }]
-        filter_string = json.dumps(filter)
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=0,
-                offset=0,
-                filter=filter_string,
-                sort="",
-                direction="",
-            ))
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 50)
-        self.assertFalse(more)
-
-    def testGetWithSort(self):
-        """Asserts to get entities with sort."""
-        for _ in xrange(100):
-            device = self.GenerateDeviceModel()
-            device.put()
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=0,
-                offset=0,
-                filter="",
-                sort="serial",
-                direction="asc",
-            ))
-
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 100)
-        for i in xrange(len(result) - 1):
-            self.assertTrue(result[i]["serial"] < result[i + 1]["serial"])
-
-        request_body = (endpoints.ResourceContainer(
-            model.GetRequestMessage).combined_message_class(
-                size=0,
-                offset=0,
-                filter="",
-                sort="serial",
-                direction="desc",
-            ))
-
-        result, more = self.eb.Get(
-            request=request_body,
-            metaclass=model.DeviceModel,
-            message=model.DeviceInfoMessage)
-        self.assertEqual(len(result), 100)
-        for i in xrange(len(result) - 1):
-            self.assertTrue(result[i]["serial"] > result[i + 1]["serial"])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint/host_info.py b/gae/webapp/src/endpoint/host_info.py
deleted file mode 100644
index ac89a11..0000000
--- a/gae/webapp/src/endpoint/host_info.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Host Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from google.appengine.api import users
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-
-HOST_INFO_RESOURCE = endpoints.ResourceContainer(model.HostInfoMessage)
-
-# Product type name for null device.
-_NULL_DEVICE_PRODUCT_TYPE = "null"
-
-
-def AddNullDevices(hostname, null_device_count):
-    """Adds null devices to DeviceModel data store.
-
-    Args:
-        hostname: string, the host name.
-        null_device_count: integer, the number of null devices.
-    """
-    device_query = model.DeviceModel.query(
-        model.DeviceModel.hostname == hostname,
-        model.DeviceModel.product == _NULL_DEVICE_PRODUCT_TYPE
-    )
-    null_devices = device_query.fetch()
-    existing_null_device_count = len(null_devices)
-
-    if existing_null_device_count < null_device_count:
-        devices_to_put = []
-        for _ in range(null_device_count - existing_null_device_count):
-            device = model.DeviceModel()
-            device.hostname = hostname
-            device.serial = "n/a"
-            device.product = _NULL_DEVICE_PRODUCT_TYPE
-            device.status = Status.DEVICE_STATUS_DICT["ready"]
-            device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                "free"]
-            device.timestamp = datetime.datetime.now()
-            devices_to_put.append(device)
-        if devices_to_put:
-            ndb.put_multi(devices_to_put)
-
-
-@endpoints.api(name='host', version='v1')
-class HostInfoApi(endpoint_base.EndpointBase):
-    """Endpoint API for host_info."""
-
-    @endpoints.method(
-        HOST_INFO_RESOURCE,
-        model.DefaultResponse,
-        path='set',
-        http_method='POST',
-        name='set')
-    def set(self, request):
-        """Sets the host info based on the `request`."""
-        if users.get_current_user():
-            username = users.get_current_user().email()
-        else:
-            username = "anonymous"
-
-        devices_to_put = []
-        for request_device in request.devices:
-            device_query = model.DeviceModel.query(
-                model.DeviceModel.serial == request_device.serial
-            )
-            existing_device = device_query.fetch()
-            if existing_device:
-                device = existing_device[0]
-            else:
-                device = model.DeviceModel()
-                device.serial = request_device.serial
-                device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                    "free"]
-            if not device.product or request_device.product != "error":
-                device.product = request_device.product
-
-            device.username = username
-            device.hostname = request.hostname
-            device.status = request_device.status
-            device.timestamp = datetime.datetime.now()
-            devices_to_put.append(device)
-        if devices_to_put:
-            ndb.put_multi(devices_to_put)
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        endpoint_base.GET_REQUEST_RESOURCE,
-        model.DeviceResponseMessage,
-        path="get",
-        http_method="POST",
-        name="get")
-    def get(self, request):
-        """Gets the devices from datastore."""
-        return_list, more = self.Get(request=request,
-                                     metaclass=model.DeviceModel,
-                                     message=model.DeviceInfoMessage)
-
-        return model.DeviceResponseMessage(devices=return_list, has_next=more)
-
-    @endpoints.method(
-        endpoint_base.COUNT_REQUEST_RESOURCE,
-        model.CountResponseMessage,
-        path="count",
-        http_method="POST",
-        name="count")
-    def count(self, request):
-        """Gets total number of DeviceModel entities stored in datastore."""
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=model.DeviceModel)
-
-        count = self.Count(metaclass=model.DeviceModel, filters=filters)
-
-        return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/host_info_test.py b/gae/webapp/src/endpoint/host_info_test.py
deleted file mode 100644
index e41037c..0000000
--- a/gae/webapp/src/endpoint/host_info_test.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import host_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class HostInfoTest(unittest_base.UnitTestBase):
-    """A class to test host_info endpoint API."""
-
-    def setUp(self):
-        """Initializes test"""
-        super(HostInfoTest, self).setUp()
-
-
-    def testUpdateExistingDevice(self):
-        """Asserts that device update does not create a duplicate."""
-        hostname = self.GetRandomString()
-        serial = self.GetRandomString()
-        product = self.GetRandomString()
-        error_device = {
-            "serial": serial,
-            "product": "error",
-        }
-        container = (
-            host_info.HOST_INFO_RESOURCE.combined_message_class(
-                hostname=hostname,
-                devices=[error_device],
-            ))
-
-        api = host_info.HostInfoApi()
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        self.assertEqual(len(devices), 1)
-
-        # name "error" is allowed as initial name.
-        self.assertEqual(devices[0].product, "error")
-
-        correct_device = {
-            "serial": serial,
-            "product": product,
-        }
-        container = (
-            host_info.HOST_INFO_RESOURCE.combined_message_class(
-                hostname=hostname,
-                devices=[correct_device],
-            ))
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        self.assertEqual(len(devices), 1)
-        # correct product name (which is not "error") should be overwritten.
-        self.assertEqual(devices[0].product, product)
-
-        container = (
-            host_info.HOST_INFO_RESOURCE.combined_message_class(
-                hostname=hostname,
-                devices=[error_device],
-            ))
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        self.assertEqual(len(devices), 1)
-        # "error" should be ignored.
-        self.assertEqual(devices[0].product, product)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint/job_queue.py b/gae/webapp/src/endpoint/job_queue.py
deleted file mode 100644
index 7416f8c..0000000
--- a/gae/webapp/src/endpoint/job_queue.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Job Queue Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-import re
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import model_util
-
-from google.appengine.ext import ndb
-
-JOB_QUEUE_RESOURCE = endpoints.ResourceContainer(model.JobMessage)
-GCS_URL_PREFIX = "gs://"
-HTTP_HTTPS_REGEX = "^https?://"
-STORAGE_API_URL = "https://storage.cloud.google.com/"
-
-
-@endpoints.api(name='job', version='v1')
-class JobQueueApi(endpoint_base.EndpointBase):
-    """Endpoint API for job_queue."""
-
-    @endpoints.method(
-        JOB_QUEUE_RESOURCE,
-        model.JobLeaseResponse,
-        path='lease',
-        http_method='POST',
-        name='lease')
-    def lease(self, request):
-        """Gets the job(s) based on the condition specified in `request`."""
-        job_query = model.JobModel.query(
-            model.JobModel.hostname == request.hostname,
-            model.JobModel.status == Status.JOB_STATUS_DICT["ready"])
-        existing_jobs = job_query.fetch()
-
-        priority_sorted_jobs = sorted(
-            existing_jobs,
-            key=lambda x: (Status.GetPriorityValue(x.priority), x.timestamp))
-
-        if priority_sorted_jobs:
-            job = priority_sorted_jobs[0]
-            job.status = Status.JOB_STATUS_DICT["leased"]
-            job.put()
-
-            job_message = model.JobMessage()
-            common_attributes = self.GetCommonAttributes(job, model.JobMessage)
-            for attr in common_attributes:
-                setattr(job_message, attr, getattr(job, attr))
-
-            device_query = model.DeviceModel.query(
-                model.DeviceModel.serial.IN(job.serial))
-            devices = device_query.fetch()
-            devices_to_put = []
-            for device in devices:
-                device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                    "use"]
-                devices_to_put.append(device)
-            if devices_to_put:
-                ndb.put_multi(devices_to_put)
-
-            return model.JobLeaseResponse(
-                return_code=model.ReturnCodeMessage.SUCCESS,
-                jobs=[job_message])
-        else:
-            return model.JobLeaseResponse(
-                return_code=model.ReturnCodeMessage.FAIL, jobs=[])
-
-    @endpoints.method(
-        JOB_QUEUE_RESOURCE,
-        model.JobLeaseResponse,
-        path='heartbeat',
-        http_method='POST',
-        name='heartbeat')
-    def heartbeat(self, request):
-        """Processes the heartbeat signal from HC which leased queued job(s)."""
-        # minify jobs by query and confirm with serial from fetched jobs
-        job_query = model.JobModel.query(
-            model.JobModel.hostname == request.hostname,
-            model.JobModel.manifest_branch == request.manifest_branch,
-            model.JobModel.build_target == request.build_target,
-            model.JobModel.test_name == request.test_name,
-            model.JobModel.status == Status.JOB_STATUS_DICT["leased"])
-        existing_jobs = job_query.fetch()
-        same_jobs = [
-            x for x in existing_jobs if set(x.serial) == set(request.serial)
-        ]
-
-        if len(same_jobs) > 1:
-            logging.warning("[heartbeat] more than one job is found!")
-            logging.warning(
-                "[heartbeat] <hostname>{} <manifest_branch>{} "
-                "<build_target>{} <test_name>{} <serials>{}".format(
-                    request.hostname, request.manifest_branch,
-                    request.build_target, request.test_name, request.serial))
-
-        if same_jobs:
-            job = same_jobs[0]
-            job_message = model.JobMessage()
-            common_attributes = self.GetCommonAttributes(job, model.JobMessage)
-            for attr in common_attributes:
-                setattr(job_message, attr, getattr(job, attr))
-
-            device_query = model.DeviceModel.query(
-                model.DeviceModel.serial.IN(job.serial))
-            devices = device_query.fetch()
-            logging.debug("[heartbeat] heartbeat job: hostname={}, "
-                          "test_name={}, job creation time={}".format(
-                              job.hostname, job.test_name, job.timestamp))
-            logging.debug("[heartbeat] request status: {}".format(
-                request.status))
-            logging.debug("[heartbeat]  - devices = {}".format(
-                ", ".join([device.serial for device in devices])))
-            devices_to_put = []
-            if request.status == Status.JOB_STATUS_DICT["complete"]:
-                job.status = request.status
-                for device in devices:
-                    device.scheduling_status = (
-                        Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-                    devices_to_put.append(device)
-            elif (request.status in [
-                    Status.JOB_STATUS_DICT["infra-err"],
-                    Status.JOB_STATUS_DICT["bootup-err"]
-            ]):
-                job.status = request.status
-                email_util.send_job_notification(job)
-                for device in devices:
-                    device.scheduling_status = (
-                        Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-                    device.status = Status.DEVICE_STATUS_DICT["unknown"]
-                    devices_to_put.append(device)
-            elif request.status == Status.JOB_STATUS_DICT["leased"]:
-                job.status = request.status
-                for device in devices:
-                    device.timestamp = datetime.datetime.now()
-                    devices_to_put.append(device)
-            else:
-                logging.error(
-                    "[heartbeat] Unexpected job status is received. - {}".
-                    format(request.serial))
-            if devices_to_put:
-                ndb.put_multi(devices_to_put)
-
-            if request.infra_log_url:
-                if request.infra_log_url.startswith(GCS_URL_PREFIX):
-                    url = "{}{}".format(
-                        STORAGE_API_URL,
-                        request.infra_log_url[len(GCS_URL_PREFIX):])
-                    job.infra_log_url = url
-                elif re.match(HTTP_HTTPS_REGEX, request.infra_log_url):
-                    job.infra_log_url = request.infra_log_url
-                else:
-                    logging.debug("[heartbeat] Wrong infra_log_url address.")
-
-            job.heartbeat_stamp = datetime.datetime.now()
-            job.put()
-            model_util.UpdateParentSchedule(job, request.status)
-            return model.JobLeaseResponse(
-                return_code=model.ReturnCodeMessage.SUCCESS,
-                jobs=[job_message])
-
-        return model.JobLeaseResponse(
-            return_code=model.ReturnCodeMessage.FAIL, jobs=[])
-
-    @endpoints.method(
-        endpoint_base.GET_REQUEST_RESOURCE,
-        model.JobResponseMessage,
-        path="get",
-        http_method="POST",
-        name="get")
-    def get(self, request):
-        """Gets the jobs from datastore."""
-        return_list, more = self.Get(request=request,
-                                     metaclass=model.JobModel,
-                                     message=model.JobMessage)
-
-        return model.JobResponseMessage(jobs=return_list, has_next=more)
-
-    @endpoints.method(
-        endpoint_base.COUNT_REQUEST_RESOURCE,
-        model.CountResponseMessage,
-        path="count",
-        http_method="POST",
-        name="count")
-    def count(self, request):
-        """Gets total number of JobModel entities stored in datastore."""
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=model.JobModel)
-        count = self.Count(metaclass=model.JobModel, filters=filters)
-
-        return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/job_queue_test.py b/gae/webapp/src/endpoint/job_queue_test.py
deleted file mode 100644
index 140c4f4..0000000
--- a/gae/webapp/src/endpoint/job_queue_test.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import job_queue
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class JobQueueTest(unittest_base.UnitTestBase):
-    """A class to test job_queue endpoint API."""
-
-    def setUp(self):
-        """Initializes test"""
-        super(JobQueueTest, self).setUp()
-
-    def testGetJobModel(self):
-        """Asserts job_queue/get API receives a job lease request."""
-        test_values = {
-            "test_type": Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT],
-            "hostname": self.GetRandomString(),
-            "priority": self.GetRandomString(),
-            "test_name": self.GetRandomString(),
-            "require_signed_device_build": False,
-            "has_bootloader_img": True,
-            "has_radio_img": False,
-            "device": self.GetRandomString(),
-            "serial": ["serial01", "serial02"],
-            "build_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
-            "manifest_branch": self.GetRandomString(),
-            "build_target": self.GetRandomString(),
-            "build_id": self.GetRandomString(),
-            "pab_account_id": self.GetRandomString(),
-            "shards": 1,
-            "param": [""],
-            "status": Status.JOB_STATUS_DICT["ready"],
-            "period": 360,
-            "gsi_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
-            "gsi_branch": self.GetRandomString(),
-            "gsi_build_target": self.GetRandomString(),
-            "gsi_build_id": self.GetRandomString(),
-            "gsi_pab_account_id": self.GetRandomString(),
-            "gsi_vendor_version": self.GetRandomString(),
-            "test_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
-            "test_branch": self.GetRandomString(),
-            "test_build_target": self.GetRandomString(),
-            "test_build_id": self.GetRandomString(),
-            "test_pab_account_id": self.GetRandomString(),
-            "retry_count": 2,
-            "infra_log_url": self.GetRandomString(),
-            "image_package_repo_base": self.GetRandomString(),
-            "report_bucket": [self.GetRandomString()],
-            "report_spreadsheet_id": [self.GetRandomString()],
-            "report_persistent_url": [self.GetRandomString()],
-            "report_reference_url": [self.GetRandomString()],
-        }
-
-        for serial in test_values["serial"]:
-            self.GenerateDeviceModel(serial=serial).put()
-
-        job = model.JobModel()
-        for key in test_values:
-            setattr(job, key, test_values[key])
-        job.timestamp = datetime.datetime.now()
-        job.put()
-
-        container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
-            hostname=test_values["hostname"]))
-        api = job_queue.JobQueueApi()
-        response = api.lease(container)
-
-        self.assertEqual(response.return_code,
-                          model.ReturnCodeMessage.SUCCESS)
-        self.assertEqual(len(response.jobs), 1)
-        for key in test_values:
-            if key is "status":
-                self.assertEqual(
-                    getattr(response.jobs[0], key),
-                    Status.JOB_STATUS_DICT["leased"])
-            else:
-                self.assertEqual(
-                    getattr(response.jobs[0], key), test_values[key])
-
-        devices = model.DeviceModel.query().fetch()
-        for device in devices:
-            self.assertEqual(device.scheduling_status,
-                              Status.DEVICE_SCHEDULING_STATUS_DICT["use"])
-
-        # test job heartbeat api
-        container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
-            hostname=response.jobs[0].hostname,
-            manifest_branch=response.jobs[0].manifest_branch,
-            build_target=response.jobs[0].build_target,
-            test_name=response.jobs[0].test_name,
-            serial=response.jobs[0].serial,
-            status=response.jobs[0].status,
-        ))
-        api = job_queue.JobQueueApi()
-        response = api.heartbeat(container)
-        self.assertEqual(response.return_code,
-                          model.ReturnCodeMessage.SUCCESS)
-
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(len(jobs), 1)
-        self.assertEqual(jobs[0].status, Status.JOB_STATUS_DICT["leased"])
-        self.assertTrue(datetime.datetime.now() - jobs[0].heartbeat_stamp <
-                        datetime.timedelta(seconds=1))
-
-        # test job heartbeat api to complete the job
-        container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
-            hostname=response.jobs[0].hostname,
-            manifest_branch=response.jobs[0].manifest_branch,
-            build_target=response.jobs[0].build_target,
-            test_name=response.jobs[0].test_name,
-            serial=response.jobs[0].serial,
-            status=Status.JOB_STATUS_DICT["complete"],
-        ))
-        api = job_queue.JobQueueApi()
-        response = api.heartbeat(container)
-        self.assertEqual(response.return_code,
-                          model.ReturnCodeMessage.SUCCESS)
-
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(len(jobs), 1)
-        self.assertEqual(jobs[0].status, Status.JOB_STATUS_DICT["complete"])
-        self.assertTrue(datetime.datetime.now() - jobs[0].heartbeat_stamp <
-                        datetime.timedelta(seconds=1))
-
-        devices = model.DeviceModel.query().fetch()
-        for device in devices:
-            self.assertEqual(device.scheduling_status,
-                              Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint/lab_info.py b/gae/webapp/src/endpoint/lab_info.py
deleted file mode 100644
index d42148b..0000000
--- a/gae/webapp/src/endpoint/lab_info.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Lab Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.endpoint import host_info
-from webapp.src.proto import model
-
-LAB_INFO_RESOURCE = endpoints.ResourceContainer(model.LabInfoMessage)
-LAB_HOST_INFO_RESOURCE = endpoints.ResourceContainer(model.LabHostInfoMessage)
-
-
-@endpoints.api(name='lab', version='v1')
-class LabInfoApi(endpoint_base.EndpointBase):
-    """Endpoint API for lab_info."""
-
-    @endpoints.method(
-        LAB_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="clear",
-        http_method="POST",
-        name="clear")
-    def clear(self, request):
-        """Clears lab info in DB."""
-        lab_query = model.LabModel.query()
-        existing_labs = lab_query.fetch(keys_only=True)
-        if existing_labs and len(existing_labs) > 0:
-            ndb.delete_multi(existing_labs)
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        LAB_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="set",
-        http_method="POST",
-        name="set")
-    def set(self, request):
-        """Sets the lab info based on `request`."""
-        if "host" in [x.name for x in request.all_fields()]:
-            labs_to_put = []
-            for host in request.host:
-                duplicate_query = model.LabModel.query(
-                    model.LabModel.name == request.name,
-                    model.LabModel.owner == request.owner,
-                    model.LabModel.hostname == host.hostname)
-                duplicates = duplicate_query.fetch()
-                if duplicates:
-                    lab = duplicates[0]
-                else:
-                    lab = model.LabModel()
-                lab.name = request.name
-                lab.owner = request.owner
-                lab.admin = request.admin
-                lab.hostname = host.hostname
-                lab.ip = host.ip
-                lab.script = host.script
-
-                null_device_count = 0
-                devices_to_put = []
-                for config_device in host.device:
-                    if config_device.product == "null":
-                        null_device_count += 1
-                        continue
-                    if config_device.serial and config_device.product:
-                        device_query = model.DeviceModel.query(
-                            model.DeviceModel.serial == config_device.serial)
-                        devices = device_query.fetch()
-                        if devices:
-                            device = devices[0]
-                            if (device.hostname != host.hostname) and (
-                                    device.status !=
-                                    Status.DEVICE_STATUS_DICT["no-response"]):
-                                logging.error(
-                                    "{} is alive in another host.".format(
-                                        config_device.serial))
-                                # TODO: send an alert to lab.admin
-                                continue
-                            if device.hostname == host.hostname and set(
-                                    device.device_equipment) == set(
-                                        config_device.device_equipment):
-                                # no need to update.
-                                continue
-                        else:
-                            device = model.DeviceModel()
-                            device.status = Status.DEVICE_STATUS_DICT[
-                                "no-response"]
-                            device.product = config_device.product
-                            device.serial = config_device.serial
-                            device.hostname = host.hostname
-                            device.scheduling_status = (
-                                Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-                            device.timestamp = datetime.datetime.now()
-                        device.device_equipment = config_device.device_equipment
-                        devices_to_put.append(device)
-                    else:
-                        logging.error("Lab config does not have device "
-                                      "information correctly; it should "
-                                      "specify device product and serial.")
-                if devices_to_put:
-                    ndb.put_multi(devices_to_put)
-
-                lab.timestamp = datetime.datetime.now()
-                labs_to_put.append(lab)
-
-                if null_device_count > 0:
-                    host_info.AddNullDevices(host.hostname, null_device_count)
-
-            if labs_to_put:
-                ndb.put_multi(labs_to_put)
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        LAB_HOST_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="set_version",
-        http_method="POST",
-        name="set_version")
-    def set_version(self, request):
-        """Sets vtslab version of the host <hostname>"""
-        lab_query = model.LabModel.query(
-            model.LabModel.hostname == request.hostname)
-        labs = lab_query.fetch()
-
-        labs_to_put = []
-        for lab in labs:
-            lab.vtslab_version = request.vtslab_version.split(":")[0]
-            labs_to_put.append(lab)
-        if labs_to_put:
-            ndb.put_multi(labs_to_put)
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        endpoint_base.GET_REQUEST_RESOURCE,
-        model.LabResponseMessage,
-        path="get",
-        http_method="POST",
-        name="get")
-    def get(self, request):
-        """Gets the labs from datastore."""
-        return_list, more = self.Get(request=request,
-                                     metaclass=model.LabModel,
-                                     message=model.LabMessage)
-
-        return model.LabResponseMessage(labs=return_list, has_next=more)
-
-    @endpoints.method(
-        endpoint_base.COUNT_REQUEST_RESOURCE,
-        model.CountResponseMessage,
-        path="count",
-        http_method="POST",
-        name="count")
-    def count(self, request):
-        """Gets total number of BuildModel entities stored in datastore."""
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=model.LabModel)
-
-        count = self.Count(metaclass=model.LabModel, filters=filters)
-
-        return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/lab_info_test.py b/gae/webapp/src/endpoint/lab_info_test.py
deleted file mode 100644
index 7320c7b..0000000
--- a/gae/webapp/src/endpoint/lab_info_test.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src.endpoint import lab_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class LabInfoTest(unittest_base.UnitTestBase):
-    """A class to test lab_info endpoint API."""
-
-    def setUp(self):
-        """Initializes test"""
-        super(LabInfoTest, self).setUp()
-
-    def testUpdateErrorDevice(self):
-        """Asserts that device update does not create a duplicate."""
-        device_serial = self.GetRandomString()
-        product = self.GetRandomString()
-        device_equipment = [self.GetRandomString()]
-        device_info = {
-            "serial": device_serial,
-            "product": product,
-            "device_equipment": device_equipment
-        }
-
-        hostname = self.GetRandomString()
-        host_info = {
-            "hostname": hostname,
-            "ip": self.GetRandomString(),
-            "script": self.GetRandomString(),
-            "device": [device_info],
-            "vtslab_version": self.GetRandomString(),
-            "host_equipment": [],
-        }
-
-        lab_name = self.GetRandomString()
-        container = (
-            lab_info.LAB_INFO_RESOURCE.combined_message_class(
-                name=lab_name,
-                owner=self.GetRandomString(),
-                admin=[self.GetRandomString()],
-                host=[host_info],
-            ))
-
-        api = lab_info.LabInfoApi()
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        self.assertEqual(len(devices), 1)
-        self.assertEqual(devices[0].product, product)
-
-        # change device product name.
-        devices[0].product = "error"
-        devices[0].put()
-
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        # there should not be duplicates.
-        self.assertEqual(len(devices), 1)
-        # stored device name should be kept.
-        self.assertEqual(devices[0].product, "error")
-
-
-    def testUpdateExistingDevice(self):
-        """Asserts that device update does not create a duplicate."""
-        device_serial = self.GetRandomString()
-        product = self.GetRandomString()
-        device_equipment = [self.GetRandomString()]
-        device_info = {
-            "serial": device_serial,
-            "product": product,
-            "device_equipment": device_equipment,
-        }
-
-        hostname = self.GetRandomString()
-        host_info = {
-            "hostname": hostname,
-            "ip": self.GetRandomString(),
-            "script": self.GetRandomString(),
-            "device": [device_info],
-            "vtslab_version": self.GetRandomString(),
-            "host_equipment": [],
-        }
-
-        lab_name = self.GetRandomString()
-        container = (
-            lab_info.LAB_INFO_RESOURCE.combined_message_class(
-                name=lab_name,
-                owner=self.GetRandomString(),
-                admin=[self.GetRandomString()],
-                host=[host_info],
-            ))
-
-        device = self.GenerateDeviceModel(product="error",
-                                          serial=device_serial,
-                                          hostname=hostname)
-        device.put()
-
-        api = lab_info.LabInfoApi()
-        api.set(container)
-
-        devices = model.DeviceModel.query().fetch()
-        self.assertEqual(len(devices), 1)
-
-        # stored device name should be kept.
-        self.assertEqual(devices[0].product, "error")
-
-        # device equipment should be updated.
-        self.assertEqual(set(devices[0].device_equipment),
-                         set(device_equipment))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint/schedule_info.py b/gae/webapp/src/endpoint/schedule_info.py
deleted file mode 100644
index e353902..0000000
--- a/gae/webapp/src/endpoint/schedule_info.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Schedule Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-
-SCHEDULE_INFO_RESOURCE = endpoints.ResourceContainer(model.ScheduleInfoMessage)
-SCHEDULE_SUSPEND_RESOURCE = endpoints.ResourceContainer(
-    model.ScheduleSuspendMessage)
-
-
-@endpoints.api(name="schedule", version="v1")
-class ScheduleInfoApi(endpoint_base.EndpointBase):
-    """Endpoint API for schedule_info."""
-
-    @endpoints.method(
-        SCHEDULE_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="clear",
-        http_method="POST",
-        name="clear")
-    def clear(self, request):
-        """Clears test schedule info in DB."""
-        schedule_query = model.ScheduleModel.query(
-            model.ScheduleModel.schedule_type != "green")
-        existing_schedules = schedule_query.fetch(keys_only=True)
-        if existing_schedules and len(existing_schedules) > 0:
-            ndb.delete_multi(existing_schedules)
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        SCHEDULE_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="set",
-        http_method="POST",
-        name="set")
-    def set(self, request):
-        """Sets the schedule info based on `request`."""
-        exist_on_both = self.GetCommonAttributes(request, model.ScheduleModel)
-        # check duplicates
-        exclusions = [
-            "name", "schedule_type", "schedule", "param", "timestamp",
-            "children_jobs", "error_count", "suspended"
-        ]
-        # list of protorpc message fields.
-        duplicate_checklist = [x for x in exist_on_both if x not in exclusions]
-        empty_list_field = []
-        query = model.ScheduleModel.query()
-        for attr_name in duplicate_checklist:
-            if model.ScheduleModel._properties[attr_name]._repeated:
-                value = request.get_assigned_value(attr_name)
-                if value:
-                    query = query.filter(
-                        getattr(model.ScheduleModel, attr_name).IN(
-                            request.get_assigned_value(attr_name)))
-                else:
-                    # empty list cannot be queried.
-                    empty_list_field.append(attr_name)
-            else:
-                query = query.filter(
-                    getattr(model.ScheduleModel, attr_name) ==
-                    request.get_assigned_value(attr_name))
-        duplicated_schedules = query.fetch()
-
-        if empty_list_field:
-            duplicated_schedules = [
-                schedule for schedule in duplicated_schedules
-                if all(
-                    [not getattr(schedule, attr) for attr in empty_list_field])
-            ]
-
-        if duplicated_schedules:
-            schedule = duplicated_schedules[0]
-        else:
-            schedule = model.ScheduleModel()
-            for attr_name in exist_on_both:
-                setattr(schedule, attr_name,
-                        request.get_assigned_value(attr_name))
-            schedule.schedule_type = "test"
-            schedule.error_count = 0
-            schedule.suspended = False
-            schedule.priority_value = Status.GetPriorityValue(schedule.priority)
-
-        schedule.timestamp = datetime.datetime.now()
-        schedule.put()
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        endpoint_base.GET_REQUEST_RESOURCE,
-        model.ScheduleResponseMessage,
-        path="get",
-        http_method="POST",
-        name="get")
-    def get(self, request):
-        """Gets the schedules from datastore."""
-        return_list, more = self.Get(request=request,
-                                     metaclass=model.ScheduleModel,
-                                     message=model.ScheduleInfoMessage)
-
-        return model.ScheduleResponseMessage(
-            schedules=return_list, has_next=more)
-
-    @endpoints.method(
-        endpoint_base.COUNT_REQUEST_RESOURCE,
-        model.CountResponseMessage,
-        path="count",
-        http_method="POST",
-        name="count")
-    def count(self, request):
-        """Gets total number of ScheduleModel entities stored in datastore."""
-        filters = self.CreateFilterList(
-            filter_string=request.filter, metaclass=model.ScheduleModel)
-
-        count = self.Count(metaclass=model.ScheduleModel, filters=filters)
-
-        return model.CountResponseMessage(count=count)
-
-    @endpoints.method(
-        SCHEDULE_SUSPEND_RESOURCE,
-        model.ScheduleSuspendMessage,
-        path="suspend",
-        http_method="POST",
-        name="suspend")
-    def suspend(self, request):
-        """Toggles a schedule from suspend to resume, or vice versa."""
-        schedules_to_put = []
-        schedules_to_return = []
-        for schedule in request.schedules:
-            schedule_key = ndb.key.Key(urlsafe=schedule.urlsafe_key)
-            schedule_entity = schedule_key.get()
-            if schedule.suspend:  # to suspend
-                schedule_entity.suspended = True
-            else:  # to resume
-                schedule_entity.error_count = 0
-                schedule_entity.suspended = False
-            schedules_to_put.append(schedule_entity)
-            schedules_to_return.append({"urlsafe_key": schedule.urlsafe_key,
-                                        "suspend": schedule_entity.suspended})
-            # TODO(jongmok): Minimize a number of emails by merging schedules.
-            email_util.send_schedule_suspension_notification(schedule_entity)
-
-        ndb.put_multi(schedules_to_put)
-        return model.ScheduleSuspendMessage(schedules=schedules_to_return)
-
-
-@endpoints.api(name="green_schedule_info", version="v1")
-class GreenScheduleInfoApi(endpoint_base.EndpointBase):
-    """Endpoint API for green_schedule_info."""
-
-    @endpoints.method(
-        SCHEDULE_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="clear",
-        http_method="POST",
-        name="clear")
-    def clear(self, request):
-        """Clears green build schedule info in DB."""
-        schedule_query = model.ScheduleModel.query(
-            model.ScheduleModel.schedule_type == "green")
-        existing_schedules = schedule_query.fetch(keys_only=True)
-        if existing_schedules and len(existing_schedules) > 0:
-            ndb.delete_multi(existing_schedules)
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
-
-    @endpoints.method(
-        SCHEDULE_INFO_RESOURCE,
-        model.DefaultResponse,
-        path="set",
-        http_method="POST",
-        name="set")
-    def set(self, request):
-        """Sets the green build schedule info based on `request`."""
-        schedule = model.ScheduleModel()
-        schedule.name = request.name
-        schedule.manifest_branch = request.manifest_branch
-        schedule.build_target = request.build_target
-        schedule.device_pab_account_id = request.device_pab_account_id
-        schedule.test_name = request.test_name
-        schedule.schedule = request.schedule
-        schedule.priority = request.priority
-        schedule.device = request.device
-        schedule.shards = request.shards
-        schedule.gsi_branch = request.gsi_branch
-        schedule.gsi_build_target = request.gsi_build_target
-        schedule.gsi_pab_account_id = request.gsi_pab_account_id
-        schedule.gsi_vendor_version = request.gsi_vendor_version
-        schedule.test_branch = request.test_branch
-        schedule.test_build_target = request.test_build_target
-        schedule.test_pab_account_id = request.test_pab_account_id
-        schedule.timestamp = datetime.datetime.now()
-        schedule.schedule_type = "green"
-        schedule.put()
-
-        return model.DefaultResponse(
-            return_code=model.ReturnCodeMessage.SUCCESS)
diff --git a/gae/webapp/src/endpoint/schedule_info_test.py b/gae/webapp/src/endpoint/schedule_info_test.py
deleted file mode 100644
index 61e69ae..0000000
--- a/gae/webapp/src/endpoint/schedule_info_test.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import schedule_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class ScheduleInfoTest(unittest_base.UnitTestBase):
-    """A class to test schedule_info endpoint API."""
-
-    def setUp(self):
-        """Initializes test"""
-        super(ScheduleInfoTest, self).setUp()
-
-    def testSetWithSimpleMessage(self):
-        """Asserts schedule_info/set API receives a simple message."""
-        # As of June 8, 2018, these are uploaded from host controller.
-        container = (
-            schedule_info.SCHEDULE_INFO_RESOURCE.combined_message_class(
-                manifest_branch=self.GetRandomString(),
-                build_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                build_target=self.GetRandomString(),
-                require_signed_device_build=False,
-                has_bootloader_img=True,
-                has_radio_img=True,
-                test_name=self.GetRandomString(),
-                period=360,
-                priority="high",
-                device=[self.GetRandomString()],
-                required_host_equipment=[self.GetRandomString()],
-                required_device_equipment=[self.GetRandomString()],
-                device_pab_account_id=self.GetRandomString(),
-                shards=1,
-                param=[self.GetRandomString()],
-                retry_count=1,
-                gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                gsi_branch=self.GetRandomString(),
-                gsi_build_target=self.GetRandomString(),
-                gsi_pab_account_id=self.GetRandomString(),
-                gsi_vendor_version=self.GetRandomString(),
-                test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                test_branch=self.GetRandomString(),
-                test_build_target=self.GetRandomString(),
-                test_pab_account_id=self.GetRandomString(),
-                image_package_repo_base=self.GetRandomString(),
-                report_bucket=[self.GetRandomString()],
-                report_spreadsheet_id=[self.GetRandomString()],
-                report_persistent_url=[self.GetRandomString()],
-                report_reference_url=[self.GetRandomString()],
-            ))
-        api = schedule_info.ScheduleInfoApi()
-        response = api.set(container)
-
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-
-    def testSetWithEmptyRepeatedField(self):
-        """Asserts schedule_info/set API receives a message.
-
-        This test sets required_host_equipment to empty and sends to endpoint
-        method.
-        """
-        # As of June 8, 2018, these are uploaded from host controller.
-        container = (
-            schedule_info.SCHEDULE_INFO_RESOURCE.combined_message_class(
-                manifest_branch=self.GetRandomString(),
-                build_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                build_target=self.GetRandomString(),
-                require_signed_device_build=False,
-                has_bootloader_img=True,
-                has_radio_img=True,
-                test_name=self.GetRandomString(),
-                period=360,
-                priority="high",
-                device=[self.GetRandomString()],
-                required_host_equipment=[self.GetRandomString()],
-                required_device_equipment=[self.GetRandomString()],
-                device_pab_account_id=self.GetRandomString(),
-                shards=1,
-                param=[self.GetRandomString()],
-                retry_count=1,
-                gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                gsi_branch=self.GetRandomString(),
-                gsi_build_target=self.GetRandomString(),
-                gsi_pab_account_id=self.GetRandomString(),
-                gsi_vendor_version=self.GetRandomString(),
-                test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-                test_branch=self.GetRandomString(),
-                test_build_target=self.GetRandomString(),
-                test_pab_account_id=self.GetRandomString(),
-                image_package_repo_base=self.GetRandomString(),
-                report_bucket=[],
-                report_spreadsheet_id=[],
-                report_persistent_url=[],
-                report_reference_url=[],
-            ))
-        api = schedule_info.ScheduleInfoApi()
-        response = api.set(container)
-
-        self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/endpoint_main.py b/gae/webapp/src/endpoint_main.py
deleted file mode 100644
index 090d6d6..0000000
--- a/gae/webapp/src/endpoint_main.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import endpoints
-
-from webapp.src.endpoint import build_info
-from webapp.src.endpoint import host_info
-from webapp.src.endpoint import job_queue
-from webapp.src.endpoint import lab_info
-from webapp.src.endpoint import schedule_info
-
-api = endpoints.api_server([
-    build_info.BuildInfoApi,
-    host_info.HostInfoApi,
-    lab_info.LabInfoApi,
-    schedule_info.ScheduleInfoApi,
-    schedule_info.GreenScheduleInfoApi,
-    job_queue.JobQueueApi])
diff --git a/gae/webapp/src/handlers/__init__.py b/gae/webapp/src/handlers/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/handlers/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/handlers/base.py b/gae/webapp/src/handlers/base.py
deleted file mode 100644
index 2862ecb..0000000
--- a/gae/webapp/src/handlers/base.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import httplib
-import logging
-import os
-import urlparse
-
-from google.appengine.api import users
-import stripe
-import webapp2
-from webapp2_extras import jinja2 as wa2_jinja2
-from webapp2_extras import sessions
-
-import errors
-from webapp.src.utils import datetime_util
-
-
-class BaseHandler(webapp2.RequestHandler):
-    """BaseHandler for all requests."""
-
-    def initialize(self, request, response):
-        """Initializes this request handler."""
-        webapp2.RequestHandler.initialize(self, request, response)
-        self.session_backend = 'datastore'
-
-    def verify_origin(self):
-        """This function will check the request is comming from the same domain."""
-        server_host = os.environ.get('ENDPOINTS_SERVICE_NAME')
-        request_host = self.request.headers.get('Host')
-        request_referer = self.request.headers.get('Referer')
-        if request_referer:
-            request_referer = urlparse.urlsplit(request_referer)[1]
-        else:
-            request_referer = request_host
-        logging.info('server: %s, request: %s', server_host, request_referer)
-        if server_host and request_referer and server_host != request_referer:
-            raise errors.Error(httplib.FORBIDDEN)
-
-    def dispatch(self):
-        """Dispatch the request.
-
-        This will first check if there's a handler_method defined
-        in the matched route, and if not it'll use the method correspondent to
-        the request method (get(), post() etc).
-        """
-        self.session_store = sessions.get_store(request=self.request)
-        # Forwards the method for RESTful support.
-        self.forward_method()
-        # Security headers.
-        # https://www.owasp.org/index.php/List_of_useful_HTTP_headers
-        self.response.headers['x-content-type-options'] = 'nosniff'
-        self.response.headers['x-frame-options'] = 'SAMEORIGIN'
-        self.response.headers['x-xss-protection'] = '1; mode=block'
-        try:
-            webapp2.RequestHandler.dispatch(self)
-        finally:
-            self.session_store.save_sessions(self.response)
-        # Disabled for now because host is appspot.com in production.
-        #self.verify_origin()
-
-    @webapp2.cached_property
-    def session(self):
-        # Returns a session using the default cookie key.
-        return self.session_store.get_session()
-
-    def handle_exception(self, exception, debug=False):
-        """Render the exception as HTML."""
-        logging.exception(exception)
-
-        # Create response dictionary and status defaults.
-        tpl = 'error.html'
-        status = httplib.INTERNAL_SERVER_ERROR
-        resp_dict = {
-            'message': 'A server error occurred.',
-        }
-        url_parts = self.urlsplit()
-        redirect_url = '%s?%s' % (url_parts[2], url_parts[4])
-
-        # Use error code if a HTTPException, or generic 500.
-        if isinstance(exception, webapp2.HTTPException):
-            status = exception.code
-            resp_dict['message'] = exception.detail
-        elif isinstance(exception, errors.FormValidationError):
-            status = exception.code
-            resp_dict['message'] = exception.msg
-            resp_dict['errors'] = exception.errors
-            self.session['form_errors'] = exception.errors
-            # Redirect user to current view URL.
-            return self.redirect(redirect_url)
-        elif isinstance(exception, stripe.StripeError):
-            status = exception.http_status
-            resp_dict['errors'] = exception.json_body['error']['message']
-            self.session['form_errors'] = [
-                exception.json_body['error']['message']
-            ]
-            return self.redirect(redirect_url)
-        elif isinstance(exception, (errors.Error, errors.AclError)):
-            status = exception.code
-            resp_dict['message'] = exception.msg
-
-        resp_dict['status'] = status
-
-        # Render output.
-        self.response.status_int = status
-        self.response.status_message = httplib.responses[status]
-        # Render the exception response into the error template.
-        self.response.write(self.jinja2.render_template(tpl, **resp_dict))
-
-    # @Override
-    def get(self, *args, **kwargs):
-        self.abort(httplib.NOT_IMPLEMENTED)
-
-    # @Override
-    def post(self, *args, **kwargs):
-        self.abort(httplib.NOT_IMPLEMENTED)
-
-    # @Override
-    def put(self, *args, **kwargs):
-        self.abort(httplib.NOT_IMPLEMENTED)
-
-    # @Override
-    def delete(self, *args, **kwargs):
-        self.abort(httplib.NOT_IMPLEMENTED)
-
-    # @Override
-    def head(self, *args, **kwargs):
-        pass
-
-    def urlsplit(self):
-        """Return a tuple of the URL."""
-        return urlparse.urlsplit(self.request.url)
-
-    def path(self):
-        """Returns the path of the current URL."""
-        return self.urlsplit()[2]
-
-    def forward_method(self):
-        """Check for a method override param and change in the request."""
-        valid = (None, 'get', 'post', 'put', 'delete', 'head', 'options')
-        method = self.request.POST.get('__method__')
-        if not method:  # Backbone's _method parameter.
-            method = self.request.POST.get('_method')
-        if method not in valid:
-            logging.debug('Invalid method %s requested!', method)
-            method = None
-        logging.debug('Method being changed from %s to %s by request',
-                      self.request.route.handler_method, method)
-        self.request.route.handler_method = method
-
-    def render(self, resp, status=httplib.OK):
-        """Render the response as HTML."""
-        user = users.get_current_user()
-        if user:
-            url = users.create_logout_url(self.request.uri)
-            url_linktext = "Logout"
-        else:
-            url = users.create_login_url(self.request.uri)
-            url_linktext = "Login"
-
-        resp.update({
-            # Defaults go here.
-            'now': datetime.datetime.now(),
-            'dest_url': str(self.request.get('dest_url', '')),
-            'form_errors': self.session.pop('form_errors', []),
-            'user': user,
-            'url': url,
-            'url_linktext': url_linktext,
-            "convert_time": datetime_util.GetTimeWithTimezone
-        })
-
-        if 'preload' not in resp:
-            resp['preload'] = {}
-
-        self.response.status_int = status
-        self.response.status_message = httplib.responses[status]
-        self.response.write(self.jinja2.render_template(self.template, **resp))
-
-    @webapp2.cached_property
-    def jinja2(self):
-        """Returns a Jinja2 renderer cached in the app registry."""
-        jinja_config = {
-            'template_path':
-            os.path.join(os.path.dirname(__file__), "../../static"),
-            'compiled_path':
-            None,
-            'force_compiled':
-            False,
-            'environment_args': {
-                'autoescape': True,
-                'extensions': [
-                    'jinja2.ext.autoescape',
-                    'jinja2.ext.with_',
-                ],
-            },
-            'globals':
-            None,
-            'filters':
-            None,
-        }
-        return wa2_jinja2.Jinja2(app=self.app, config=jinja_config)
diff --git a/gae/webapp/src/handlers/errors.py b/gae/webapp/src/handlers/errors.py
deleted file mode 100644
index fde95c0..0000000
--- a/gae/webapp/src/handlers/errors.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import httplib
-
-
-class Error(Exception):
-    """Base Exception for handlers.
-
-    Attributes:
-        code: HTTP 1.1 status code
-        msg: the W3C names for HTTP 1.1 status code
-    """
-
-    def __init__(self, code=None, msg=None):
-        self.code = code or httplib.INTERNAL_SERVER_ERROR
-        self.msg = msg or httplib.responses[self.code]
-        super(Error, self).__init__(self.code, self.msg)
-
-    def __str__(self):
-        return repr([self.code, self.msg])
-
-
-class FormValidationError(Error):
-    """Form Validtion Exception for handlers."""
-
-    def __init__(self, code=None, msg=None, errors=None):
-        self.code = code or httplib.BAD_REQUEST
-        self.msg = msg or httplib.responses[self.code]
-        self.errors = errors or []
-        super(FormValidationError, self).__init__(self.code, self.msg)
-
-    def __str__(self):
-        return repr([self.code, self.msg, self.errors])
-
-
-class AclError(Error):
-    """Base ACL error."""
-
-    def __init__(self, code):
-        self.code = code
-        self.msg = httplib.responses[code]
-        super(AclError, self).__init__(self.code, self.msg)
-
-    def __str__(self):
-        return repr([self.code, self.msg])
-
-
-class NotFoundError(AclError):
-    """The item being access does not exist."""
-
-    def __init__(self):
-        super(NotFoundError, self).__init__(httplib.NOT_FOUND)
-
-
-class UnauthorizedError(AclError):
-    """The current user is not authenticated."""
-
-    def __init__(self):
-        super(UnauthorizedError, self).__init__(httplib.UNAUTHORIZED)
-
-
-class ForbiddenError(AclError):
-    """The current user does not have proper permission."""
-
-    def __init__(self):
-        super(ForbiddenError, self).__init__(httplib.FORBIDDEN)
diff --git a/gae/webapp/src/proto/__init__.py b/gae/webapp/src/proto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/proto/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/proto/model.py b/gae/webapp/src/proto/model.py
deleted file mode 100644
index 1b24154..0000000
--- a/gae/webapp/src/proto/model.py
+++ /dev/null
@@ -1,449 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from google.appengine.ext import ndb
-
-from protorpc import messages
-from protorpc import message_types
-
-
-class BuildModel(ndb.Model):
-    """A model for representing an individual build entry."""
-    manifest_branch = ndb.StringProperty()
-    build_id = ndb.StringProperty()
-    build_target = ndb.StringProperty()
-    build_type = ndb.StringProperty()
-    artifact_type = ndb.StringProperty()
-    artifacts = ndb.StringProperty(repeated=True)
-    timestamp = ndb.DateTimeProperty(auto_now=False)
-    signed = ndb.BooleanProperty()
-
-
-class BuildInfoMessage(messages.Message):
-    """A message for representing an individual build entry."""
-    manifest_branch = messages.StringField(1)
-    build_id = messages.StringField(2)
-    build_target = messages.StringField(3)
-    build_type = messages.StringField(4)
-    artifact_type = messages.StringField(5)
-    artifacts = messages.StringField(6, repeated=True)
-    signed = messages.BooleanField(7)
-    timestamp = message_types.DateTimeField(8)
-
-
-class ScheduleControlModel(ndb.Model):
-    """A model for representing a schedule control data entry."""
-    enabled = ndb.BooleanProperty()
-    # "global" or empty string to enable/disable all schedules.
-    schedule_name = ndb.StringProperty()
-
-
-class ScheduleModel(ndb.Model):
-    """A model for representing an individual schedule entry."""
-    # schedule name for green build schedule, optional.
-    name = ndb.StringProperty()
-    schedule_type = ndb.StringProperty()
-
-    # device image information
-    build_storage_type = ndb.IntegerProperty()
-    manifest_branch = ndb.StringProperty()
-    build_target = ndb.StringProperty()  # type:name
-    device_pab_account_id = ndb.StringProperty()
-    require_signed_device_build = ndb.BooleanProperty()
-    has_bootloader_img = ndb.BooleanProperty(default=True)
-    has_radio_img = ndb.BooleanProperty(default=True)
-
-    # GSI information
-    gsi_storage_type = ndb.IntegerProperty()
-    gsi_branch = ndb.StringProperty()
-    gsi_build_target = ndb.StringProperty()
-    gsi_pab_account_id = ndb.StringProperty()
-    gsi_vendor_version = ndb.StringProperty()
-
-    # test suite information
-    test_storage_type = ndb.IntegerProperty()
-    test_branch = ndb.StringProperty()
-    test_build_target = ndb.StringProperty()
-    test_pab_account_id = ndb.StringProperty()
-
-    test_name = ndb.StringProperty()
-    period = ndb.IntegerProperty()
-    schedule = ndb.StringProperty()
-    priority = ndb.StringProperty()
-    priority_value = ndb.IntegerProperty()
-    device = ndb.StringProperty(repeated=True)
-    shards = ndb.IntegerProperty()
-    param = ndb.StringProperty(repeated=True)
-    timestamp = ndb.DateTimeProperty(auto_now=False)
-    retry_count = ndb.IntegerProperty()
-
-    children_jobs = ndb.KeyProperty(kind="JobModel", repeated=True)
-    error_count = ndb.IntegerProperty()
-    suspended = ndb.BooleanProperty()
-    image_package_repo_base = ndb.StringProperty()
-
-    required_host_equipment = ndb.StringProperty(repeated=True)
-    required_device_equipment = ndb.StringProperty(repeated=True)
-
-    report_bucket = ndb.StringProperty(repeated=True)
-    report_spreadsheet_id = ndb.StringProperty(repeated=True)
-    report_persistent_url = ndb.StringProperty(repeated=True)
-    report_reference_url = ndb.StringProperty(repeated=True)
-
-    owner = ndb.StringProperty(repeated=True)
-
-
-class ScheduleControlInfoMessage(messages.Message):
-    """A message for representing a schedule control data entry."""
-    enabled = messages.BooleanField(1)
-    schedule_name = messages.StringField(2)
-
-
-class ScheduleInfoMessage(messages.Message):
-    """A message for representing an individual schedule entry."""
-    # Next ID = 39
-    # schedule name for green build schedule, optional.
-    name = messages.StringField(16)
-    schedule_type = messages.StringField(19)
-
-    # device image information
-    build_storage_type = messages.IntegerField(21)
-    manifest_branch = messages.StringField(1)
-    build_target = messages.StringField(2)
-    device_pab_account_id = messages.StringField(17)
-    require_signed_device_build = messages.BooleanField(20)
-    has_bootloader_img = messages.BooleanField(27)
-    has_radio_img = messages.BooleanField(28)
-
-    # GSI information
-    gsi_storage_type = messages.IntegerField(22)
-    gsi_branch = messages.StringField(9)
-    gsi_build_target = messages.StringField(10)
-    gsi_pab_account_id = messages.StringField(11)
-    gsi_vendor_version = messages.StringField(24)
-
-    # test suite information
-    test_storage_type = messages.IntegerField(23)
-    test_branch = messages.StringField(12)
-    test_build_target = messages.StringField(13)
-    test_pab_account_id = messages.StringField(14)
-
-    test_name = messages.StringField(3)
-    period = messages.IntegerField(4)
-    schedule = messages.StringField(18)
-    priority = messages.StringField(5)
-    device = messages.StringField(6, repeated=True)
-    shards = messages.IntegerField(7)
-    param = messages.StringField(8, repeated=True)
-    retry_count = messages.IntegerField(15)
-
-    required_host_equipment = messages.StringField(25, repeated=True)
-    required_device_equipment = messages.StringField(26, repeated=True)
-
-    report_bucket = messages.StringField(29, repeated=True)
-    report_spreadsheet_id = messages.StringField(30, repeated=True)
-    report_persistent_url = messages.StringField(32, repeated=True)
-    report_reference_url = messages.StringField(33, repeated=True)
-
-    image_package_repo_base = messages.StringField(31)
-    timestamp = message_types.DateTimeField(34)
-    owner = messages.StringField(35, repeated=True)
-
-    suspended = messages.BooleanField(36)
-    urlsafe_key = messages.StringField(37)
-    error_count = messages.IntegerField(38)
-
-
-class LabModel(ndb.Model):
-    """A model for representing an individual lab entry."""
-    name = ndb.StringProperty()
-    owner = ndb.StringProperty()
-    admin = ndb.StringProperty(repeated=True)
-    hostname = ndb.StringProperty()
-    ip = ndb.StringProperty()
-    # devices is a comma-separated list of serial=product pairs
-    devices = ndb.StringProperty()
-    timestamp = ndb.DateTimeProperty(auto_now=False)
-    vtslab_version = ndb.StringProperty()
-    host_equipment = ndb.StringProperty(repeated=True)
-
-
-class LabDeviceInfoMessage(messages.Message):
-    """A message for representing an individual lab host's device entry."""
-    serial = messages.StringField(1, repeated=False)
-    product = messages.StringField(2, repeated=False)
-    device_equipment = messages.StringField(3, repeated=True)
-
-
-class LabHostInfoMessage(messages.Message):
-    """A message for representing an individual lab's host entry."""
-    hostname = messages.StringField(1, repeated=False)
-    ip = messages.StringField(2, repeated=False)
-    script = messages.StringField(3)
-    device = messages.MessageField(LabDeviceInfoMessage, 4, repeated=True)
-    vtslab_version = messages.StringField(5)
-    host_equipment = messages.StringField(6, repeated=True)
-
-
-class LabInfoMessage(messages.Message):
-    """A message for representing an individual lab entry."""
-    name = messages.StringField(1)
-    owner = messages.StringField(2)
-    admin = messages.StringField(4, repeated=True)
-    host = messages.MessageField(LabHostInfoMessage, 3, repeated=True)
-
-
-class LabMessage(messages.Message):
-    """A model for representing a LabModel entity."""
-    name = messages.StringField(1)
-    owner = messages.StringField(2)
-    admin = messages.StringField(3, repeated=True)
-    hostname = messages.StringField(4)
-    ip = messages.StringField(5)
-    devices = messages.StringField(6)
-    vtslab_version = messages.StringField(7)
-    host_equipment = messages.StringField(8, repeated=True)
-
-
-class DeviceModel(ndb.Model):
-    """A model for representing an individual device entry."""
-    hostname = ndb.StringProperty()
-    product = ndb.StringProperty()
-    serial = ndb.StringProperty()
-    status = ndb.IntegerProperty()
-    scheduling_status = ndb.IntegerProperty()
-    timestamp = ndb.DateTimeProperty(auto_now=False)
-    device_equipment = ndb.StringProperty(repeated=True)
-
-
-class DeviceInfoMessage(messages.Message):
-    """A message for representing an individual host's device entry."""
-    serial = messages.StringField(1)
-    product = messages.StringField(2)
-    status = messages.IntegerField(3)
-    scheduling_status = messages.IntegerField(4)
-    hostname = messages.StringField(5)
-    device_equipment = messages.StringField(6, repeated=True)
-    timestamp = message_types.DateTimeField(7)
-
-
-class HostInfoMessage(messages.Message):
-    """A message for representing an individual host entry."""
-    hostname = messages.StringField(1)
-    devices = messages.MessageField(DeviceInfoMessage, 2, repeated=True)
-
-
-class JobModel(ndb.Model):
-    """A model for representing an individual job entry."""
-    test_type = ndb.IntegerProperty()
-
-    hostname = ndb.StringProperty()
-    priority = ndb.StringProperty()
-    test_name = ndb.StringProperty()
-    require_signed_device_build = ndb.BooleanProperty()
-    has_bootloader_img = ndb.BooleanProperty()
-    has_radio_img = ndb.BooleanProperty()
-    device = ndb.StringProperty()
-    serial = ndb.StringProperty(repeated=True)
-
-    # device image information
-    build_storage_type = ndb.IntegerProperty()
-    manifest_branch = ndb.StringProperty()
-    build_target = ndb.StringProperty()
-    build_id = ndb.StringProperty()
-    pab_account_id = ndb.StringProperty()
-
-    shards = ndb.IntegerProperty()
-    param = ndb.StringProperty(repeated=True)
-    status = ndb.IntegerProperty()
-    period = ndb.IntegerProperty()
-
-    # GSI information
-    gsi_storage_type = ndb.IntegerProperty()
-    gsi_branch = ndb.StringProperty()
-    gsi_build_target = ndb.StringProperty()
-    gsi_build_id = ndb.StringProperty()
-    gsi_pab_account_id = ndb.StringProperty()
-    gsi_vendor_version = ndb.StringProperty()
-
-    # test suite information
-    test_storage_type = ndb.IntegerProperty()
-    test_branch = ndb.StringProperty()
-    test_build_target = ndb.StringProperty()
-    test_build_id = ndb.StringProperty()
-    test_pab_account_id = ndb.StringProperty()
-
-    timestamp = ndb.DateTimeProperty(auto_now=False)
-    heartbeat_stamp = ndb.DateTimeProperty(auto_now=False)
-    retry_count = ndb.IntegerProperty()
-
-    infra_log_url = ndb.StringProperty()
-
-    parent_schedule = ndb.KeyProperty(kind="ScheduleModel")
-
-    image_package_repo_base = ndb.StringProperty()
-
-    report_bucket = ndb.StringProperty(repeated=True)
-    report_spreadsheet_id = ndb.StringProperty(repeated=True)
-    report_persistent_url = ndb.StringProperty(repeated=True)
-    report_reference_url = ndb.StringProperty(repeated=True)
-
-
-class JobMessage(messages.Message):
-    """A message for representing an individual job entry."""
-    # Next ID = 39
-    test_type = messages.IntegerField(29)
-
-    hostname = messages.StringField(1)
-    priority = messages.StringField(2)
-    test_name = messages.StringField(3)
-    require_signed_device_build = messages.BooleanField(23)
-    has_bootloader_img = messages.BooleanField(31)
-    has_radio_img = messages.BooleanField(32)
-    device = messages.StringField(4)
-    serial = messages.StringField(5, repeated=True)
-
-    # device image information
-    build_storage_type = messages.IntegerField(25)
-    manifest_branch = messages.StringField(6)
-    build_target = messages.StringField(7)
-    build_id = messages.StringField(10)
-    pab_account_id = messages.StringField(20)
-
-    shards = messages.IntegerField(8)
-    param = messages.StringField(9, repeated=True)
-    status = messages.IntegerField(11)
-    period = messages.IntegerField(12)
-
-    # GSI information
-    gsi_storage_type = messages.IntegerField(26)
-    gsi_branch = messages.StringField(13)
-    gsi_build_target = messages.StringField(14)
-    gsi_build_id = messages.StringField(21)
-    gsi_pab_account_id = messages.StringField(15)
-    gsi_vendor_version = messages.StringField(28)
-
-    # test suite information
-    test_storage_type = messages.IntegerField(27)
-    test_branch = messages.StringField(16)
-    test_build_target = messages.StringField(17)
-    test_build_id = messages.StringField(22)
-    test_pab_account_id = messages.StringField(18)
-
-    retry_count = messages.IntegerField(19)
-
-    infra_log_url = messages.StringField(24)
-
-    image_package_repo_base = messages.StringField(30)
-
-    report_bucket = messages.StringField(33, repeated=True)
-    report_spreadsheet_id = messages.StringField(34, repeated=True)
-    report_persistent_url = messages.StringField(35, repeated=True)
-    report_reference_url = messages.StringField(36, repeated=True)
-
-    timestamp = message_types.DateTimeField(37)
-    heartbeat_stamp = message_types.DateTimeField(38)
-
-
-class ReturnCodeMessage(messages.Enum):
-    """Enum for default return code."""
-    SUCCESS = 0
-    FAIL = 1
-
-
-class DefaultResponse(messages.Message):
-    """A default response proto message."""
-    return_code = messages.EnumField(ReturnCodeMessage, 1)
-
-
-class JobLeaseResponse(messages.Message):
-    """A job lease response proto message."""
-    return_code = messages.EnumField(ReturnCodeMessage, 1)
-    jobs = messages.MessageField(JobMessage, 2, repeated=True)
-
-
-class KeyValueModel(ndb.Model):
-    """A simple key-value model.
-
-    This class uses name as key and store one value or more than one values
-    to store values which require continuous monitoring such as counters,
-    or flags.
-    """
-    name = ndb.StringProperty()
-    string_value = ndb.StringProperty()
-    integer_value = ndb.IntegerProperty()
-    boolean_value = ndb.BooleanProperty()
-
-
-class GetRequestMessage(messages.Message):
-    """A message to request entities through /get endpoints."""
-    size = messages.IntegerField(1)
-    offset = messages.IntegerField(2)
-    filter = messages.StringField(3)
-    sort = messages.StringField(4)
-    direction = messages.StringField(5)
-
-
-class BuildResponseMessage(messages.Message):
-    """A message containing build entities to respond to /get endpoints."""
-    builds = messages.MessageField(BuildInfoMessage, 1, repeated=True)
-    has_next = messages.BooleanField(2)
-
-
-class DeviceResponseMessage(messages.Message):
-    """A message containing device entities to respond to /get endpoints."""
-    devices = messages.MessageField(DeviceInfoMessage, 1, repeated=True)
-    has_next = messages.BooleanField(2)
-
-
-class JobResponseMessage(messages.Message):
-    """A message containing job entities to respond to /get endpoints."""
-    jobs = messages.MessageField(JobMessage, 1, repeated=True)
-    has_next = messages.BooleanField(2)
-
-
-class LabResponseMessage(messages.Message):
-    """A message containing lab entities to respond to /get endpoints."""
-    labs = messages.MessageField(LabMessage, 1, repeated=True)
-    has_next = messages.BooleanField(2)
-
-
-class ScheduleResponseMessage(messages.Message):
-    """A message containing schedule entities to respond to /get endpoints."""
-    schedules = messages.MessageField(ScheduleInfoMessage, 1, repeated=True)
-    has_next = messages.BooleanField(2)
-
-
-class CountRequestMessage(messages.Message):
-    """A message to request a count of entities through /count endpoints."""
-    filter = messages.StringField(1)
-
-
-class CountResponseMessage(messages.Message):
-    """A message of a count of entities to respond to /count endpoints."""
-    count = messages.IntegerField(1)
-
-
-class ScheduleSuspendMessage(messages.Message):
-    """A response message to schedule endpoint API's /suspend method."""
-
-    class SingleScheduleSuspendMessage(messages.Message):
-        urlsafe_key = messages.StringField(1)
-        suspend = messages.BooleanField(2)
-
-    schedules = messages.MessageField(
-        SingleScheduleSuspendMessage, 1, repeated=True)
diff --git a/gae/webapp/src/scheduler/__init__.py b/gae/webapp/src/scheduler/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/scheduler/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/scheduler/device_heartbeat.py b/gae/webapp/src/scheduler/device_heartbeat.py
deleted file mode 100644
index 730fc5f..0000000
--- a/gae/webapp/src/scheduler/device_heartbeat.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import logger
-
-DEVICE_RESPONSE_TIMEOUT_SECONDS = 300
-
-
-class PeriodicDeviceHeartBeat(webapp2.RequestHandler):
-    """Main class for /tasks/device_heartbeat.
-
-    Used to find lost devices and change their status properly.
-
-    Attributes:
-        logger: Logger class
-    """
-    logger = logger.Logger()
-
-    def get(self):
-        """Generates an HTML page based on the task schedules kept in DB."""
-        self.logger.Clear()
-
-        device_query = model.DeviceModel.query(
-            model.DeviceModel.status !=
-            Status.DEVICE_STATUS_DICT["no-response"])
-        devices = device_query.fetch()
-        lost_devices = [
-            x for x in devices
-            if (datetime.datetime.now() - x.timestamp
-                ).seconds >= DEVICE_RESPONSE_TIMEOUT_SECONDS
-        ]
-        devices_to_put = []
-        labs_to_alert = {}
-        for device in lost_devices:
-            self.logger.Println("Device[{}] is not responding.".format(
-                device.serial))
-            device.status = Status.DEVICE_STATUS_DICT["no-response"]
-            devices_to_put.append(device)
-
-            # sending notification
-            lab_query = model.LabModel.query(
-                model.LabModel.hostname == device.hostname)
-            labs = lab_query.fetch()
-            if labs:
-                lab = labs[0]
-                if lab.name not in labs_to_alert:
-                    labs_to_alert[lab.name] = {}
-                    labs_to_alert[lab.name]["_recipients"] = []
-                if device.hostname not in labs_to_alert[lab.name]:
-                    labs_to_alert[lab.name][device.hostname] = []
-                if lab.owner not in labs_to_alert[lab.name]["_recipients"]:
-                    labs_to_alert[lab.name]["_recipients"].append(lab.owner)
-                labs_to_alert[lab.name]["_recipients"].extend([
-                    x for x in lab.admin
-                    if x not in labs_to_alert[lab.name]["_recipients"]
-                ])
-                labs_to_alert[lab.name][device.hostname].append(device.serial)
-            else:
-                logging.warning(
-                    "Could not find a lab model for hostname {}".format(
-                        device.hostname))
-                continue
-
-        if devices_to_put:
-            ndb.put_multi(devices_to_put)
-        if labs_to_alert:
-            email_util.send_device_notification(labs_to_alert)
-
-        self.response.write(
-            "<pre>\n" + "\n".join(self.logger.Get()) + "\n</pre>")
diff --git a/gae/webapp/src/scheduler/job_heartbeat.py b/gae/webapp/src/scheduler/job_heartbeat.py
deleted file mode 100644
index af8994c..0000000
--- a/gae/webapp/src/scheduler/job_heartbeat.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import logger
-from webapp.src.utils import model_util
-
-JOB_RESPONSE_TIMEOUT_SECONDS = 60 * 60
-
-
-class PeriodicJobHeartBeat(webapp2.RequestHandler):
-    """Main class for /tasks/job_heartbeat.
-
-    Used to find lost jobs and change their status properly.
-
-    Attributes:
-        logger: Logger class
-    """
-    logger = logger.Logger()
-
-    def get(self):
-        """Generates an HTML page based on the jobs kept in DB."""
-        self.logger.Clear()
-
-        job_query = model.JobModel.query(
-            model.JobModel.status == Status.JOB_STATUS_DICT["leased"])
-        jobs = job_query.fetch()
-
-        lost_jobs = []
-        for job in jobs:
-            if job.heartbeat_stamp:
-                job_timestamp = job.heartbeat_stamp
-            else:
-                job_timestamp = job.timestamp
-            if (datetime.datetime.now() -
-                    job_timestamp).seconds >= JOB_RESPONSE_TIMEOUT_SECONDS:
-                lost_jobs.append(job)
-
-        lost_jobs_to_put = []
-        devices_to_put = []
-        for job in lost_jobs:
-            self.logger.Println("Lost job found")
-            self.logger.Println("[hostname]{} [device]{} [test_name]{}".format(
-                job.hostname, job.device, job.test_name))
-            job.status = Status.JOB_STATUS_DICT["infra-err"]
-            lost_jobs_to_put.append(job)
-            model_util.UpdateParentSchedule(
-                job, Status.JOB_STATUS_DICT["infra-err"])
-
-            device_query = model.DeviceModel.query(
-                model.DeviceModel.serial.IN(job.serial))
-            devices = device_query.fetch()
-            for device in devices:
-                self.logger.Println("Device serial: {}".format(device.serial))
-                device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                    "free"]
-                devices_to_put.append(device)
-
-        if lost_jobs_to_put:
-            ndb.put_multi(lost_jobs_to_put)
-            email_util.send_job_notification(lost_jobs_to_put)
-            self.logger.Println("{} jobs are updated.".format(
-                len(lost_jobs_to_put)))
-
-        if devices_to_put:
-            ndb.put_multi(devices_to_put)
-            self.logger.Println("{} devices are updated.".format(
-                len(devices_to_put)))
-
-        lines = self.logger.Get()
-        logging.info("\n".join([line.strip() for line in lines]))
-
-        self.response.write("<pre>\n" + "\n".join(lines) + "\n</pre>")
diff --git a/gae/webapp/src/scheduler/job_heartbeat_test.py b/gae/webapp/src/scheduler/job_heartbeat_test.py
deleted file mode 100644
index c9f56a5..0000000
--- a/gae/webapp/src/scheduler/job_heartbeat_test.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import job_heartbeat
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-
-
-class JobHeartbeatTest(unittest_base.UnitTestBase):
-    """Tests for PeriodicJobHeartBeat cron class.
-
-    Attributes:
-        testbed: A Testbed instance which provides local unit testing.
-        job_heartbeat: A mock job_heartbeat.PeriodicJobHeartBeat instance.
-    """
-
-    def setUp(self):
-        """Initializes test"""
-        super(JobHeartbeatTest, self).setUp()
-        # Mocking PeriodicJobHeartBeat and essential methods.
-        self.job_heartbeat = job_heartbeat.PeriodicJobHeartBeat(mock.Mock())
-        self.job_heartbeat.response = mock.Mock()
-        self.job_heartbeat.response.write = mock.Mock()
-
-    def testJobHearbeat(self):
-        """Asserts job heartbeat detects unavailable jobs."""
-        num_of_devices = 2
-        shards = 2
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        devices = []
-        for _ in range(num_of_devices):
-            for i in range(shards):
-                device = self.GenerateDeviceModel(
-                    hostname=lab.hostname, product="product{}".format(i))
-                device.put()
-                devices.append(device)
-
-        schedules = []
-        for device in devices:
-            schedule = self.GenerateScheduleModel(
-                lab_model=lab, device_model=device, shards=shards)
-            schedule.put()
-            schedules.append(schedule)
-
-        for schedule in schedules:
-            build_dict = self.GenerateBuildModel(schedule)
-            for key in build_dict:
-                build_dict[key].put()
-
-        # Mocking ScheduleHandler and essential methods.
-        scheduler = schedule_worker.ScheduleHandler(mock.Mock())
-        scheduler.response = mock.Mock()
-        scheduler.response.write = mock.Mock()
-        scheduler.request.get = mock.MagicMock(return_value="")
-
-        # Creating jobs.
-        scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(2, len(jobs))
-
-        # jobs[0] will get old enough so it will be timed out.
-        jobs[0].status = Status.JOB_STATUS_DICT["leased"]
-        jobs[0].timestamp = (datetime.datetime.now() - datetime.timedelta(
-            seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS + 5))
-        jobs[0].heartbeat_stamp = (
-            datetime.datetime.now() - datetime.timedelta(
-                seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS + 5))
-        jobs[0].put()
-
-        # jobs[1] will not exceed the timeout time.
-        jobs[1].status = Status.JOB_STATUS_DICT["leased"]
-        jobs[1].timestamp = (datetime.datetime.now() - datetime.timedelta(
-            seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS - 5))
-        jobs[1].heartbeat_stamp = (
-            datetime.datetime.now() - datetime.timedelta(
-                seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS - 5))
-        jobs[1].put()
-
-        # Creating jobs.
-        self.job_heartbeat.get()
-
-        # One job(job[0]) should be changed to infra-err status.
-        jobs = model.JobModel.query().fetch()
-        infra_error_jobs = [
-            x for x in jobs if x.status == Status.JOB_STATUS_DICT["infra-err"]
-        ]
-        self.assertEqual(len(infra_error_jobs), 1)
-
-        # job[0]'s devices should be changed to free scheduling status.
-        serials = infra_error_jobs[0].serial
-        devices = model.DeviceModel.query(
-            model.DeviceModel.serial.IN(serials)).fetch()
-        for device in devices:
-            self.assertEqual(device.scheduling_status,
-                              Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/scheduler/periodic.py b/gae/webapp/src/scheduler/periodic.py
deleted file mode 100644
index 627ec14..0000000
--- a/gae/webapp/src/scheduler/periodic.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import webapp2
-
-from webapp.src.proto import model
-
-from google.appengine.api import taskqueue
-
-
-class PeriodicScheduler(webapp2.RequestHandler):
-    """Main class for /tasks/schedule servlet.
-
-    This class creates a task, which creates schedules, in given period.
-    """
-
-    def get(self):
-        """Enqueues a scheduling task if scheduler is enabled."""
-        schedule_control = model.ScheduleControlModel.query()
-        schedule_control_dataset = schedule_control.fetch()
-        enabled = True
-        if schedule_control_dataset:
-            for schedule_control_data_tuple in schedule_control_dataset:
-                if (not schedule_control_data_tuple.schedule_name or
-                    schedule_control_data_tuple.schedule_name == "global"):
-                    enabled = schedule_control_data_tuple.enabled
-
-        if not enabled:
-            self.response.write(
-                "<pre>\nScheduler not enabled.\n</pre>")
-            return
-
-        task = taskqueue.add(
-            url="/worker/schedule_handler",
-            target="worker",
-            queue_name="queue-schedule",
-            transactional=False
-        )
-        self.response.write(
-            "<pre>\nScheduling task is enqueued. ETA {}\n</pre>".format(
-                task.eta))
diff --git a/gae/webapp/src/scheduler/schedule_worker.py b/gae/webapp/src/scheduler/schedule_worker.py
deleted file mode 100644
index 4c4b20f..0000000
--- a/gae/webapp/src/scheduler/schedule_worker.py
+++ /dev/null
@@ -1,549 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import itertools
-import logging
-import re
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import logger
-import webapp2
-
-MAX_LOG_CHARACTERS = 10000  # maximum number of characters per each log
-BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS = 60  # retry minutes when boot-up error is occurred
-
-CREATE_JOB_SUCCESS = "success"
-CREATE_JOB_FAILED_NO_BUILD = "no_build"
-CREATE_JOB_FAILED_NO_DEVICE = "no_device"
-
-
-def GetTestVersionType(manifest_branch, gsi_branch, test_type=0):
-    """Compares manifest branch and gsi branch to get test type.
-
-    This function only completes two LSBs which represent version related
-    test type.
-
-    Args:
-        manifest_branch: a string, manifest branch name.
-        gsi_branch: a string, gsi branch name.
-        test_type: an integer, previous test type value.
-
-    Returns:
-        An integer, test type value.
-    """
-    if not test_type:
-        value = 0
-    else:
-        # clear two bits
-        value = test_type & ~(1 | 1 << 1)
-
-    if not manifest_branch:
-        logging.debug("manifest branch cannot be empty or None.")
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
-    if not gsi_branch:
-        logging.debug("gsi_branch is empty.")
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT]
-
-    gcs_pattern = "^gs://.*/v([0-9.]*)/.*"
-    q_pattern = "(git_)?(aosp-)?q.*"
-    p_pattern = "(git_)?(aosp-)?p.*"
-    o_mr1_pattern = "(git_)?(aosp-)?o[^-]*-m.*"
-    o_pattern = "(git_)?(aosp-)?o.*"
-    master_pattern = "(git_)?(aosp-)?master"
-
-    gcs_search = re.search(gcs_pattern, manifest_branch)
-    if gcs_search:
-        device_version = gcs_search.group(1)
-    elif re.match(q_pattern, manifest_branch):
-        device_version = "10.0"
-    elif re.match(p_pattern, manifest_branch):
-        device_version = "9.0"
-    elif re.match(o_mr1_pattern, manifest_branch):
-        device_version = "8.1"
-    elif re.match(o_pattern, manifest_branch):
-        device_version = "8.0"
-    elif re.match(master_pattern, manifest_branch):
-        device_version = "master"
-    else:
-        logging.debug("Unknown device version.")
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
-    gcs_search = re.search(gcs_pattern, gsi_branch)
-    if gcs_search:
-        gsi_version = gcs_search.group(1)
-    elif re.match(q_pattern, gsi_branch):
-        gsi_version = "10.0"
-    elif re.match(p_pattern, gsi_branch):
-        gsi_version = "9.0"
-    elif re.match(o_mr1_pattern, gsi_branch):
-        gsi_version = "8.1"
-    elif re.match(o_pattern, gsi_branch):
-        gsi_version = "8.0"
-    elif re.match(master_pattern, gsi_branch):
-        gsi_version = "master"
-    else:
-        logging.debug("Unknown gsi version.")
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
-    if device_version == gsi_version:
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT]
-    else:
-        return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_OTA]
-
-
-class ScheduleHandler(webapp2.RequestHandler):
-    """Background worker class for /worker/schedule_handler.
-
-    This class pull tasks from 'queue-schedule' queue and processes in
-    background service 'worker'.
-
-    Attributes:
-        logger: Logger class
-    """
-    logger = logger.Logger()
-
-    def ReserveDevices(self, target_device_serials):
-        """Reserves devices.
-
-        Args:
-            target_device_serials: a list of strings, containing target device
-                                   serial numbers.
-        """
-        device_query = model.DeviceModel.query(
-            model.DeviceModel.serial.IN(target_device_serials))
-        devices = device_query.fetch()
-        devices_to_put = []
-        for device in devices:
-            device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                "reserved"]
-            devices_to_put.append(device)
-        if devices_to_put:
-            ndb.put_multi(devices_to_put)
-
-    def FindBuildId(self, artifact_type, manifest_branch, target,
-                    signed=False):
-        """Finds a designated build ID.
-
-        Args:
-            artifact_type: a string, build artifact type.
-            manifest_branch: a string, build manifest branch.
-            target: a string which build target and type are joined by '-'.
-            signed: a boolean to get a signed build.
-
-        Return:
-            string, build ID found.
-        """
-        build_id = ""
-        if "-" in target:
-            build_target, build_type = target.split("-")
-        else:
-            build_target = target
-            build_type = ""
-        if not artifact_type or not manifest_branch or not build_target:
-            self.logger.Println("The argument format is invalid.")
-            return build_id
-        build_query = model.BuildModel.query(
-            model.BuildModel.artifact_type == artifact_type,
-            model.BuildModel.manifest_branch == manifest_branch,
-            model.BuildModel.build_target == build_target,
-            model.BuildModel.build_type == build_type)
-        builds = build_query.fetch()
-
-        if builds:
-            builds = [
-                build for build in builds
-                if (build.timestamp >
-                    datetime.datetime.now() - datetime.timedelta(hours=72))
-            ]
-
-        if builds:
-            self.logger.Println("-- Found build ID")
-            builds.sort(key=lambda x: x.build_id, reverse=True)
-            for build in builds:
-                if not signed or build.signed:
-                    build_id = build.build_id
-                    break
-        return build_id
-
-    def post(self):
-        self.logger.Clear()
-        manual_job = False
-        schedule_key = self.request.get("schedule_key")
-        if schedule_key:
-            key = ndb.key.Key(urlsafe=schedule_key)
-            manual_job = True
-            schedules = [key.get()]
-        else:
-            schedule_query = model.ScheduleModel.query(
-                model.ScheduleModel.suspended != True)
-            schedules = schedule_query.fetch()
-
-        if schedules:
-            # filter out the schedules which are not updated within 72 hours.
-            schedules = [
-                schedule for schedule in schedules
-                if (schedule.timestamp >
-                    datetime.datetime.now() - datetime.timedelta(hours=72))
-            ]
-            schedules = self.FilterWithPeriod(schedules)
-
-        if schedules:
-            schedules.sort(key=lambda x: self.GetProductName(x))
-            group_by_product = [
-                list(g)
-                for _, g in itertools.groupby(schedules,
-                                              lambda x: self.GetProductName(x))
-            ]
-            for group in group_by_product:
-                group.sort(key=lambda x: x.priority_value if (
-                    x.priority_value) else Status.GetPriorityValue(x.priority))
-                create_result = {
-                    CREATE_JOB_SUCCESS: [],
-                    CREATE_JOB_FAILED_NO_BUILD: [],
-                    CREATE_JOB_FAILED_NO_DEVICE: []
-                }
-                for schedule in group:
-                    self.logger.Println("")
-                    self.logger.Println("Schedule: %s (branch: %s)" %
-                                        (schedule.test_name,
-                                         schedule.manifest_branch))
-                    self.logger.Println(
-                        "Build Target: %s" % schedule.build_target)
-                    self.logger.Println("Device: %s" % schedule.device)
-                    self.logger.Indent()
-                    result, lab = self.CreateJob(schedule, manual_job)
-                    if result == CREATE_JOB_SUCCESS:
-                        create_result[result].append(lab)
-                    else:
-                        create_result[result].append(schedule)
-                    self.logger.Unindent()
-                # if any schedule in group created a job, increase priority of
-                # the schedules which couldn't create due to out of devices.
-                schedules_to_put = []
-                for lab in create_result[CREATE_JOB_SUCCESS]:
-                    for schedule in create_result[CREATE_JOB_FAILED_NO_DEVICE]:
-                        if any([lab in target for target in schedule.device
-                                ]) and schedule not in schedules_to_put:
-                            if schedule.priority_value is None:
-                                schedule.priority_value = (
-                                    Status.GetPriorityValue(schedule.priority))
-                            if schedule.priority_value > 0:
-                                schedule.priority_value -= 1
-                                schedules_to_put.append(schedule)
-                if schedules_to_put:
-                    ndb.put_multi(schedules_to_put)
-
-        self.logger.Println("Scheduling completed.")
-
-        lines = self.logger.Get()
-        lines = [line.strip() for line in lines]
-        outputs = []
-        chars = 0
-        for line in lines:
-            chars += len(line)
-            if chars > MAX_LOG_CHARACTERS:
-                logging.info("\n".join(outputs))
-                outputs = []
-                chars = len(line)
-            outputs.append(line)
-        logging.info("\n".join(outputs))
-
-    def CreateJob(self, schedule, manual_job=False):
-        """Creates a job for given schedule.
-
-        Args:
-            schedule: model.ScheduleModel instance.
-            manual_job: True if a job is created by a user, False otherwise.
-
-        Returns:
-            a string of job creation result message.
-            a string of lab name if job is created, otherwise empty string.
-        """
-        target_host, target_device, target_device_serials = (
-            self.SelectTargetLab(schedule))
-        if not target_host:
-            return CREATE_JOB_FAILED_NO_DEVICE, ""
-
-        self.logger.Println("- Target host: %s" % target_host)
-        self.logger.Println("- Target device: %s" % target_device)
-        self.logger.Println("- Target serials: %s" % target_device_serials)
-
-        # create job and add.
-        new_job = model.JobModel()
-        new_job.hostname = target_host
-        new_job.priority = schedule.priority
-        new_job.test_name = schedule.test_name
-        new_job.require_signed_device_build = (
-            schedule.require_signed_device_build)
-        new_job.device = target_device
-        new_job.period = schedule.period
-        new_job.serial.extend(target_device_serials)
-        new_job.build_storage_type = schedule.build_storage_type
-        new_job.manifest_branch = schedule.manifest_branch
-        new_job.build_target = schedule.build_target
-        new_job.pab_account_id = schedule.device_pab_account_id
-        new_job.shards = schedule.shards
-        new_job.param = schedule.param
-        new_job.retry_count = schedule.retry_count
-        new_job.gsi_storage_type = schedule.gsi_storage_type
-        new_job.gsi_branch = schedule.gsi_branch
-        new_job.gsi_build_target = schedule.gsi_build_target
-        new_job.gsi_pab_account_id = schedule.gsi_pab_account_id
-        new_job.gsi_vendor_version = schedule.gsi_vendor_version
-        new_job.test_storage_type = schedule.test_storage_type
-        new_job.test_branch = schedule.test_branch
-        new_job.test_build_target = schedule.test_build_target
-        new_job.test_pab_account_id = schedule.test_pab_account_id
-        new_job.parent_schedule = schedule.key
-        new_job.image_package_repo_base = schedule.image_package_repo_base
-        new_job.required_host_equipment = schedule.required_host_equipment
-        new_job.required_device_equipment = schedule.required_device_equipment
-        new_job.has_bootloader_img = schedule.has_bootloader_img
-        new_job.has_radio_img = schedule.has_radio_img
-        new_job.report_bucket = schedule.report_bucket
-        new_job.report_spreadsheet_id = schedule.report_spreadsheet_id
-        new_job.report_persistent_url = schedule.report_persistent_url
-        new_job.report_reference_url = schedule.report_reference_url
-
-        # uses bit 0-1 to indicate version.
-        test_type = GetTestVersionType(schedule.manifest_branch,
-                                       schedule.gsi_branch)
-        # uses bit 2
-        if schedule.require_signed_device_build:
-            test_type |= Status.TEST_TYPE_DICT[Status.TEST_TYPE_SIGNED]
-
-        if manual_job:
-            test_type |= Status.TEST_TYPE_DICT[Status.TEST_TYPE_MANUAL]
-
-        new_job.test_type = test_type
-
-        new_job.build_id = ""
-        new_job.gsi_build_id = ""
-        new_job.test_build_id = ""
-        for artifact_type in ["device", "gsi", "test"]:
-            if artifact_type == "device":
-                storage_type_text = "build_storage_type"
-                manifest_branch_text = "manifest_branch"
-                build_target_text = "build_target"
-                build_id_text = "build_id"
-                signed = new_job.require_signed_device_build
-            else:
-                storage_type_text = artifact_type + "_storage_type"
-                manifest_branch_text = artifact_type + "_branch"
-                build_target_text = artifact_type + "_build_target"
-                build_id_text = artifact_type + "_build_id"
-                signed = False
-
-            manifest_branch = getattr(new_job, manifest_branch_text)
-            build_target = getattr(new_job, build_target_text)
-            storage_type = getattr(new_job, storage_type_text)
-            if storage_type == Status.STORAGE_TYPE_DICT["PAB"]:
-                build_id = self.FindBuildId(
-                    artifact_type=artifact_type,
-                    manifest_branch=manifest_branch,
-                    target=build_target,
-                    signed=signed)
-            elif storage_type == Status.STORAGE_TYPE_DICT["GCS"]:
-                # temp value to distinguish from empty values.
-                build_id = "gcs"
-            else:
-                build_id = ""
-                self.logger.Println(
-                    "Unexpected storage type (%s)." % storage_type)
-            setattr(new_job, build_id_text, build_id)
-
-        if ((not new_job.manifest_branch or new_job.build_id)
-                and (not new_job.gsi_branch or new_job.gsi_build_id)
-                and (not new_job.test_branch or new_job.test_build_id)):
-            new_job.build_id = new_job.build_id.replace("gcs", "")
-            new_job.gsi_build_id = (new_job.gsi_build_id.replace("gcs", ""))
-            new_job.test_build_id = (new_job.test_build_id.replace("gcs", ""))
-            self.ReserveDevices(target_device_serials)
-            new_job.status = Status.JOB_STATUS_DICT["ready"]
-            new_job.timestamp = datetime.datetime.now()
-            new_job_key = new_job.put()
-            schedule.children_jobs.append(new_job_key)
-            schedule.priority_value = Status.GetPriorityValue(
-                schedule.priority)
-            schedule.put()
-            self.logger.Println("A new job has been created.")
-            labs = model.LabModel.query(
-                model.LabModel.hostname == target_host).fetch()
-            return CREATE_JOB_SUCCESS, labs[0].name
-        else:
-            self.logger.Println("Cannot find builds to create a job.")
-            self.logger.Println("- Device branch / build - {} / {}".format(
-                new_job.manifest_branch, new_job.build_id))
-            self.logger.Println("- GSI branch / build - {} / {}".format(
-                new_job.gsi_branch, new_job.gsi_build_id))
-            self.logger.Println("- Test branch / build - {} / {}".format(
-                new_job.test_branch, new_job.test_build_id))
-            return CREATE_JOB_FAILED_NO_BUILD, ""
-
-    def FilterWithPeriod(self, schedules):
-        """Filters schedules with period.
-
-        This method filters schedules if any children jobs are created within
-        period time.
-
-        Args:
-            schedules: a list of model.ScheduleModel instances.
-
-        Returns:
-            a list of model.ScheduleModel instances which need to create a new
-            job.
-        """
-        ret_list = []
-        if not schedules:
-            return ret_list
-
-        if type(schedules) is not list:
-            schedules = [schedules]
-
-        for schedule in schedules:
-            if not schedule.children_jobs:
-                ret_list.append(schedule)
-                continue
-
-            latest_job_key = schedule.children_jobs[-1]
-            latest_job = latest_job_key.get()
-
-            if datetime.datetime.now() - latest_job.timestamp > (
-                    datetime.timedelta(
-                        minutes=self.GetCorrectedPeriod(schedule))):
-                ret_list.append(schedule)
-
-        return ret_list
-
-    def SelectTargetLab(self, schedule):
-        """Find target host and devices to schedule a new job.
-
-        Args:
-            schedule: a proto containing the information of a schedule.
-
-        Returns:
-            a string which represents hostname,
-            a string containing target lab and product with '/' separator,
-            a list of selected devices serial (see whether devices will be
-            selected later when the job is picked up.)
-        """
-
-        available_devices = []
-        for target_device in schedule.device:
-            if "/" not in target_device:
-                self.logger.Println(
-                    "Device malformed - {}".format(target_device))
-                continue
-
-            target_lab, target_product_type = target_device.split("/")
-            self.logger.Println("- Lab %s" % target_lab)
-            self.logger.Indent()
-            host_query = model.LabModel.query(
-                model.LabModel.name == target_lab)
-            target_hosts = host_query.fetch()
-
-            if target_hosts:
-                for host in target_hosts:
-                    if not (set(schedule.required_host_equipment) <= set(
-                            host.host_equipment)):
-                        continue
-                    self.logger.Println("- Host: %s" % host.hostname)
-                    self.logger.Indent()
-                    device_query = model.DeviceModel.query(
-                        model.DeviceModel.hostname == host.hostname,
-                        model.DeviceModel.scheduling_status ==
-                        Status.DEVICE_SCHEDULING_STATUS_DICT["free"],
-                        model.DeviceModel.status.IN([
-                            Status.DEVICE_STATUS_DICT["fastboot"],
-                            Status.DEVICE_STATUS_DICT["online"],
-                            Status.DEVICE_STATUS_DICT["ready"]
-                        ]))
-                    host_devices = device_query.fetch()
-                    host_devices = [
-                        x for x in host_devices
-                        if x.product.lower() == target_product_type.lower() and
-                        (set(schedule.required_device_equipment) <= set(
-                            x.device_equipment))
-                    ]
-                    if len(host_devices) < schedule.shards:
-                        self.logger.Println(
-                            "A host {} does not have enough devices. "
-                            "# of devices = {}, shards = {}".format(
-                                host.hostname, len(host_devices),
-                                schedule.shards))
-                        self.logger.Unindent()
-                        continue
-                    host_devices.sort(
-                        key=lambda x: (len(x.device_equipment)
-                                       if x.device_equipment else 0))
-                    available_devices.append((host_devices, target_device))
-                    self.logger.Unindent()
-
-            self.logger.Unindent()
-
-        if not available_devices:
-            self.logger.Println("No hosts have enough devices for schedule!")
-            return None, None, []
-
-        available_devices.sort(key=lambda x: (
-            sum([len(y.device_equipment) for y in x[0][:schedule.shards]])))
-        selected_host_devices = available_devices[0]
-        return selected_host_devices[0][0].hostname, selected_host_devices[
-            1], [x.serial for x in selected_host_devices[0][:schedule.shards]]
-
-    def GetProductName(self, schedule):
-        """Gets a product name from schedule instance.
-
-        Args:
-            schedule: a schedule instance.
-
-        Returns:
-            a string, product name in lowercase.
-        """
-        if not schedule or not schedule.device:
-            return ""
-
-        if "/" not in schedule.device[0]:
-            return ""
-
-        return schedule.device[0].split("/")[1].lower()
-
-    def GetCorrectedPeriod(self, schedule):
-        """Corrects and returns period value based on latest children jobs.
-
-        Args:
-            schedule: a model.ScheduleModel instance containing schedule
-                      information.
-
-        Returns:
-            an integer, corrected schedule period.
-        """
-        if not schedule.error_count or not schedule.children_jobs or (
-                schedule.period <= BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS):
-            return schedule.period
-
-        latest_job = schedule.children_jobs[-1].get()
-
-        if latest_job.status == Status.JOB_STATUS_DICT["bootup-err"]:
-            return BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS
-        else:
-            return schedule.period
diff --git a/gae/webapp/src/scheduler/schedule_worker_test.py b/gae/webapp/src/scheduler/schedule_worker_test.py
deleted file mode 100644
index 2dcf1e9..0000000
--- a/gae/webapp/src/scheduler/schedule_worker_test.py
+++ /dev/null
@@ -1,581 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-from webapp.src.utils import model_util
-
-
-class ScheduleHandlerTest(unittest_base.UnitTestBase):
-    """Tests for ScheduleHandler.
-
-    Attributes:
-        scheduler: A mock schedule_worker.ScheduleHandler.
-    """
-
-    def setUp(self):
-        """Initializes test"""
-        super(ScheduleHandlerTest, self).setUp()
-        # Mocking ScheduleHandler and essential methods.
-        self.scheduler = schedule_worker.ScheduleHandler(mock.Mock())
-        self.scheduler.response = mock.Mock()
-        self.scheduler.response.write = mock.Mock()
-        self.scheduler.request.get = mock.MagicMock(return_value="")
-
-    def testSimpleJobCreation(self):
-        """Asserts a job is created.
-
-        This test defines that each model only has a single entity, and asserts
-        that a job is created.
-        """
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab)
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        self.scheduler.post()
-        self.assertEqual(1, len(model.JobModel.query().fetch()))
-        print("A job is created successfully.")
-
-        device_query = model.DeviceModel.query(
-            model.DeviceModel.serial == device.serial)
-        device = device_query.fetch()[0]
-        self.assertEqual(Status.DEVICE_SCHEDULING_STATUS_DICT["reserved"],
-                         device.scheduling_status)
-        print("A device is reserved successfully.")
-
-    def testPriorityScheduling(self):
-        """Asserts job creation with priority scheduling."""
-        product = "product"
-        high_priority_schedule_test_name = "high_test"
-        medium_priority_schedule_test_name = "medium_test"
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(
-            hostname=lab.hostname, product=product)
-        device.put()
-
-        schedule_high = self.GenerateScheduleModel(
-            device_model=device,
-            lab_model=lab,
-            priority="high",
-            test_name=high_priority_schedule_test_name)
-        schedule_high.put()
-
-        schedule_medium = self.GenerateScheduleModel(
-            device_model=device,
-            lab_model=lab,
-            priority="medium",
-            test_name=medium_priority_schedule_test_name)
-        schedule_medium.put()
-
-        build_dict = self.GenerateBuildModel(schedule_high)
-        for key in build_dict:
-            build_dict[key].put()
-
-        self.scheduler.post()
-        schedules = model.ScheduleModel.query().fetch()
-        self.assertEqual(schedules[0].test_name,
-                         high_priority_schedule_test_name)
-
-    def testPrioritySchedulingWithAging(self):
-        """Asserts job creation with priority scheduling with aging."""
-        product = "product"
-        high_priority_schedule_test_name = "high_test"
-        medium_priority_schedule_test_name = "medium_test"
-        schedule_period_minute = 100
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(
-            hostname=lab.hostname, product=product)
-        device.put()
-
-        schedules = []
-        schedule_high = self.GenerateScheduleModel(
-            device_model=device,
-            lab_model=lab,
-            test_name=high_priority_schedule_test_name,
-            period=schedule_period_minute,
-            priority="high")
-        schedule_high.put()
-        schedules.append(schedule_high)
-
-        schedule_medium = self.GenerateScheduleModel(
-            device_model=device,
-            lab_model=lab,
-            test_name=medium_priority_schedule_test_name,
-            period=schedule_period_minute,
-            priority="medium")
-        schedule_medium.put()
-        schedules.append(schedule_medium)
-
-        for schedule in schedules:
-            build_dict = self.GenerateBuildModel(schedule)
-            for key in build_dict:
-                build_dict[key].put()
-
-        high_original_priority_value = schedule_high.priority_value
-        medium_original_priority_value = schedule_medium.priority_value
-
-        # On first attempt, "high" priority will create a job.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(jobs[0].test_name, high_priority_schedule_test_name)
-
-        # medium priority schedule's priority value will be decreased.
-        self.assertEqual(medium_original_priority_value - 1,
-                         schedule_medium.priority_value)
-
-        self.PassTime(minutes=schedule_period_minute + 1)
-        self.ResetDevices()
-
-        # On second attempt, "high" priority will create a job.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        jobs.sort(key=lambda x: x.timestamp, reverse=True)  # latest first
-        self.assertEqual(jobs[0].test_name, high_priority_schedule_test_name)
-
-        # medium priority schedule's priority value will be decreased again.
-        self.assertEqual(medium_original_priority_value - 2,
-                         schedule_medium.priority_value)
-
-        while schedule_medium.priority_value >= high_original_priority_value:
-            self.PassTime(minutes=schedule_period_minute + 1)
-            self.ResetDevices()
-            self.scheduler.post()
-
-        # at last, medium priority schedule should be able to create a job.
-        self.PassTime(minutes=schedule_period_minute + 1)
-        self.ResetDevices()
-        self.scheduler.post()
-
-        jobs = model.JobModel.query().fetch()
-        jobs.sort(key=lambda x: x.timestamp, reverse=True)  # latest first
-        self.assertEqual(jobs[0].test_name, medium_priority_schedule_test_name)
-
-        # after a job is created, its priority value should be restored.
-        self.assertEqual(schedule_medium.priority_value,
-                         medium_original_priority_value)
-
-    def testPrioritySchedulingWithAgingForMultiDevices(self):
-        """Asserts job creation with priority scheduling for multi devices."""
-        product1 = "product1"
-        product2 = "product2"
-        schedule_period_minute = 360
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device1 = self.GenerateDeviceModel(
-            hostname=lab.hostname, product=product1)
-        device1.put()
-
-        device2 = self.GenerateDeviceModel(
-            hostname=lab.hostname, product=product2)
-        device2.put()
-
-        schedule1_l = self.GenerateScheduleModel(
-            device_model=device1,
-            lab_model=lab,
-            priority="low",
-            period=schedule_period_minute)
-        schedule1_l.put()
-
-        schedule1_h = self.GenerateScheduleModel(
-            device_model=device1,
-            lab_model=lab,
-            priority="high",
-            period=schedule_period_minute)
-        schedule1_h.put()
-
-        schedule2_m = self.GenerateScheduleModel(
-            device_model=device2,
-            lab_model=lab,
-            priority="medium",
-            period=schedule_period_minute)
-        schedule2_m.put()
-
-        schedule2_h = self.GenerateScheduleModel(
-            device_model=device2,
-            lab_model=lab,
-            priority="high",
-            period=schedule_period_minute)
-        schedule2_h.put()
-
-        schedule1_l_original_priority_value = schedule1_l.priority_value
-        schedule2_m_original_priority_value = schedule2_m.priority_value
-
-        for schedule in [schedule2_m, schedule2_h]:
-            build_dict = self.GenerateBuildModel(schedule)
-            for key in build_dict:
-                build_dict[key].put()
-
-        # create jobs
-        self.scheduler.post()
-
-        # schedule2_m will not get a change to create a job.
-        jobs = model.JobModel.query().fetch()
-        self.assertTrue(
-            any([job.test_name == schedule2_h.test_name for job in jobs]))
-        self.assertFalse(
-            any([job.test_name == schedule2_m.test_name for job in jobs]))
-
-        # schedule2_m's priority value should be decreased.
-        self.assertTrue(schedule2_m_original_priority_value - 1,
-                        schedule2_m.priority_value)
-
-        # schedule1_l's priority value should not be changed because all other
-        # schedules for device1 were also failed to created a job.
-        self.assertTrue(schedule1_l_original_priority_value,
-                        schedule1_l.priority_value)
-
-        for num in range(3):
-            self.assertTrue(schedule2_m_original_priority_value - 1 - num,
-                            schedule2_m.priority_value)
-            self.PassTime(minutes=schedule_period_minute + 1)
-            self.ResetDevices()
-            self.scheduler.post()
-            self.assertFalse(
-                any([job.test_name == schedule2_m.test_name for job in jobs]))
-            self.assertTrue(schedule1_l_original_priority_value,
-                            schedule1_l.priority_value)
-
-        # device1 is ready for scheduling.
-        for schedule in [schedule1_l, schedule1_h]:
-            build_dict = self.GenerateBuildModel(schedule)
-            for key in build_dict:
-                build_dict[key].put()
-
-        # after 4 times of failure, now schedule2_m can create a job.
-        self.PassTime(minutes=schedule_period_minute + 1)
-        self.ResetDevices()
-        self.scheduler.post()
-
-        jobs = model.JobModel.query().fetch()
-        self.assertTrue(
-            any([job.test_name == schedule2_m.test_name for job in jobs]))
-
-        # now schedule_1's priority value should be changed.
-        self.assertEqual(schedule1_l_original_priority_value - 1,
-                          schedule1_l.priority_value)
-
-    def testRetryAfterBootupError(self):
-        """Asserts a schedule's period is shortened after boot-up error."""
-        long_period = 5760
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab, period=long_period)
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        # a job should be created.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(1, len(jobs))
-
-        jobs[0].status = Status.JOB_STATUS_DICT["bootup-err"]
-        jobs[0].put()
-        model_util.UpdateParentSchedule(jobs[0],
-                                        Status.JOB_STATUS_DICT["bootup-err"])
-
-        self.PassTime(
-            minutes=schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS + 1)
-        self.ResetDevices()
-
-        # new job should be created again.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(2, len(jobs))
-
-        jobs.sort(key=lambda x: x.timestamp, reverse=True)  # latest first
-        jobs[0].status = Status.JOB_STATUS_DICT["bootup-err"]
-        jobs[0].put()
-        model_util.UpdateParentSchedule(jobs[0],
-                                        Status.JOB_STATUS_DICT["bootup-err"])
-
-        self.PassTime(
-            minutes=schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS - 1)
-        self.ResetDevices()
-
-        # time is not passed enough so there would be no new job.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(2, len(jobs))
-
-        # if latest job is completed successfully, period should be recovered.
-        jobs[0].status = Status.JOB_STATUS_DICT["complete"]
-        jobs[0].put()
-        model_util.UpdateParentSchedule(jobs[0],
-                                        Status.JOB_STATUS_DICT["complete"])
-
-        # pass time to (period - 1)
-        self.PassTime(minutes=long_period - 1 - (
-            schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS - 1))
-        self.ResetDevices()
-
-        # then no job will be created.
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(2, len(jobs))
-
-        # pass time to (period + 1)
-        self.PassTime(minutes=2)
-
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(3, len(jobs))
-
-    def testSimpleDevicePriorityWithEquipment(self):
-        """Asserts a scheduler creates a job with minimum device equipment."""
-        equipment_a = "equipment_a"
-        equipment_b = "equipment_b"
-
-        device_product = "device_product"
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device_a = self.GenerateDeviceModel(
-            product=device_product,
-            hostname=lab.hostname,
-            device_equipment=[equipment_a])
-        device_a.put()
-
-        device_b = self.GenerateDeviceModel(
-            product=device_product,
-            hostname=lab.hostname,
-            device_equipment=[equipment_b])
-        device_b.put()
-
-        device_c = self.GenerateDeviceModel(
-            product=device_product, hostname=lab.hostname)
-        device_c.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_target="{}-test".format(device_product),
-            lab_model=lab,
-            required_device_equipment=[equipment_b])
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        # a job should be created and it should be created with equipment_b
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(1, len(jobs))
-        self.assertIn(device_b.serial, jobs[0].serial)
-
-    def testDevicePriorityWithEquipment(self):
-        """Asserts a scheduler creates a job with minimum device equipment."""
-        lab_1 = "lab_1"
-        lab_2 = "lab_2"
-
-        host_a = "host_a"
-        host_b = "host_b"
-        host_c = "host_c"
-        host_d = "host_d"
-        host_e = "host_e"
-
-        equipment_a = "equipment_a"
-        equipment_b = "equipment_b"
-        equipment_c = "equipment_c"
-
-        correct_product = "correct"
-        wrong_product = "wrong"
-
-        self.GenerateLabModel(lab_name=lab_1, host_name=host_a).put()
-        self.GenerateLabModel(lab_name=lab_1, host_name=host_b).put()
-        self.GenerateLabModel(lab_name=lab_2, host_name=host_c).put()
-        self.GenerateLabModel(lab_name=lab_2, host_name=host_d).put()
-        self.GenerateLabModel(lab_name=lab_2, host_name=host_e).put()
-
-        # setting devices through host a to e.
-        equipments = [[equipment_a], [equipment_a], [equipment_b],
-                      [equipment_a, equipment_b]]
-        for equipment in equipments:
-            device = self.GenerateDeviceModel(
-                product=correct_product, hostname=host_a)
-            device.device_equipment = equipment
-            device.put()
-
-        equipments = [[], [equipment_a], [equipment_a, equipment_b],
-                      [equipment_a, equipment_b]]
-        for equipment in equipments:
-            device = self.GenerateDeviceModel(
-                product=correct_product, hostname=host_b)
-            device.device_equipment = equipment
-            device.put()
-
-        equipments = [[equipment_a], [equipment_a], [equipment_b],
-                      [equipment_b]]
-        for equipment in equipments:
-            device = self.GenerateDeviceModel(
-                product=correct_product, hostname=host_c)
-            device.device_equipment = equipment
-            device.put()
-
-        equipments = [[equipment_a], [equipment_a, equipment_b, equipment_c],
-                      [equipment_a, equipment_b]]
-        for equipment in equipments:
-            device = self.GenerateDeviceModel(
-                product=correct_product, hostname=host_d)
-            device.device_equipment = equipment
-            device.put()
-
-        products = [correct_product, correct_product, wrong_product]
-        for product in products:
-            device = self.GenerateDeviceModel(product=product, hostname=host_e)
-            device.device_equipment = [equipment_a]
-            device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_target="{}-test".format(correct_product), shards=3)
-        schedule.required_device_equipment = [equipment_a]
-        schedule.device = [
-            "{}/{}".format(lab_1, correct_product), "{}/{}".format(
-                lab_2, correct_product)
-        ]
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        # a job should be created on host_a
-        self.scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(1, len(jobs))
-
-        host_a_devices = model.DeviceModel.query(
-            model.DeviceModel.hostname == host_a).fetch()
-        host_a_devices_serial = [x.serial for x in host_a_devices]
-
-        for job_device in jobs[0].serial:
-            self.assertIn(job_device, host_a_devices_serial)
-
-    def testSelectTargetLab(self):
-        """Asserts SelectTargetLab() method."""
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab)
-        schedule.put()
-
-        ret_host, ret_device, ret_serials = (
-            self.scheduler.SelectTargetLab(schedule))
-
-        self.assertEqual(lab.hostname, ret_host)
-        self.assertEqual("{}/{}".format(lab.name, device.product), ret_device)
-        self.assertEqual([device.serial], ret_serials)
-
-    def testSimpleJobCreationWithOutdatedBuild(self):
-        """Asserts an outdated build is filtered out."""
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab)
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].timestamp = datetime.datetime.now(
-            ) - datetime.timedelta(hours=73)
-            build_dict[key].put()
-
-        self.scheduler.post()
-        self.assertEqual(0, len(model.JobModel.query().fetch()))
-
-        builds = model.BuildModel().query().fetch()
-        for build in builds:
-            build.timestamp = datetime.datetime.now()
-            build.put()
-
-        self.scheduler.post()
-        self.assertEqual(1, len(model.JobModel.query().fetch()))
-
-    def testSimpleJobCreationWithOutdatedSchedule(self):
-        """Asserts an outdated schedule is filtered out."""
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab)
-        schedule.timestamp = datetime.datetime.now() - datetime.timedelta(
-            hours=73)
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        self.scheduler.post()
-        self.assertEqual(0, len(model.JobModel.query().fetch()))
-
-        schedule = model.ScheduleModel().query().fetch()[0]
-        schedule.timestamp = datetime.datetime.now()
-        schedule.put()
-
-        self.scheduler.post()
-        self.assertEqual(1, len(model.JobModel.query().fetch()))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/tasks/__init__.py b/gae/webapp/src/tasks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/tasks/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/tasks/indexing.py b/gae/webapp/src/tasks/indexing.py
deleted file mode 100644
index 2ebe687..0000000
--- a/gae/webapp/src/tasks/indexing.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License") + "\n</pre>");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import logging
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-
-import webapp2
-from google.appengine.api import taskqueue
-from google.appengine.ext import ndb
-
-PAGING_SIZE = 1000
-DICT_MODELS = {
-    "build": model.BuildModel,
-    "device": model.DeviceModel,
-    "lab": model.LabModel,
-    "job": model.JobModel,
-    "schedule": model.ScheduleModel
-}
-
-
-class CreateIndex(webapp2.RequestHandler):
-    """Cron class for /tasks/indexing/{model}."""
-
-    def get(self, arg):
-        """Creates a task to re-index, with given URL format."""
-        index_list = []
-        if arg:
-            if arg.startswith("/") and arg[1:].lower() in DICT_MODELS.keys():
-                index_list.append(arg[1:].lower())
-            else:
-                self.response.write("<pre>Access Denied. Please visit "
-                                    "/tasks/indexing/{model}</pre>")
-                return
-        else:
-            # accessed by /tasks/indexing
-            index_list.extend(DICT_MODELS.keys())
-        self.response.write(
-            "<pre>Re-indexing task{} for {} {} going to be created.</pre>".
-            format("s"
-                   if len(index_list) > 1 else "", ", ".join(index_list), "are"
-                   if len(index_list) > 1 else "is"))
-
-        for model_type in index_list:
-            task = taskqueue.add(
-                url="/worker/indexing",
-                target="worker",
-                queue_name="queue-indexing",
-                transactional=False,
-                params={
-                    "model_type": model_type
-                })
-            self.response.write(
-                "<pre>Re-indexing task for {} is created. ETA: {}</pre>".
-                format(model_type, task.eta))
-
-
-class IndexingHandler(webapp2.RequestHandler):
-    """Task queue handler class to re-index ndb model."""
-
-    def post(self):
-        """Fetch entities and process model specific jobs."""
-        reload(model)
-        model_type = self.request.get("model_type")
-
-        num_updated = 0
-        next_cursor = None
-        more = True
-
-        while more:
-            query = DICT_MODELS[model_type].query()
-            entities, next_cursor, more = query.fetch_page(
-                PAGING_SIZE, start_cursor=next_cursor)
-
-            to_put = []
-            for entity in entities:
-                if model_type == "build":
-                    pass
-                elif model_type == "device":
-                    pass
-                elif model_type == "lab":
-                    pass
-                elif model_type == "job":
-                    # uses bits 0-1 to indicate version.
-                    test_type = schedule_worker.GetTestVersionType(
-                        entity.manifest_branch, entity.gsi_branch)
-                    # uses bit 2
-                    if entity.require_signed_device_build:
-                        test_type |= (
-                            Status.TEST_TYPE_DICT[Status.TEST_TYPE_SIGNED])
-                    entity.test_type = test_type
-
-                    if not entity.parent_schedule:
-                        # finds and links to a parent schedule.
-                        parent_schedule_query = model.ScheduleModel.query(
-                            model.ScheduleModel.priority == entity.priority,
-                            model.ScheduleModel.test_name == entity.test_name,
-                            model.ScheduleModel.period == entity.period,
-                            model.ScheduleModel.build_storage_type == (
-                                entity.build_storage_type),
-                            model.ScheduleModel.manifest_branch == (
-                                entity.manifest_branch),
-                            model.ScheduleModel.build_target == (
-                                entity.build_target),
-                            model.ScheduleModel.device_pab_account_id == (
-                                entity.pab_account_id),
-                            model.ScheduleModel.shards == entity.shards,
-                            model.ScheduleModel.retry_count == (
-                                entity.retry_count),
-                            model.ScheduleModel.gsi_storage_type == (
-                                entity.gsi_storage_type),
-                            model.ScheduleModel.gsi_branch == (
-                                entity.gsi_branch),
-                            model.ScheduleModel.gsi_build_target == (
-                                entity.gsi_build_target),
-                            model.ScheduleModel.gsi_pab_account_id == (
-                                entity.gsi_pab_account_id),
-                            model.ScheduleModel.gsi_vendor_version == (
-                                entity.gsi_vendor_version),
-                            model.ScheduleModel.test_storage_type == (
-                                entity.test_storage_type),
-                            model.ScheduleModel.test_branch == (
-                                entity.test_branch),
-                            model.ScheduleModel.test_build_target == (
-                                entity.test_build_target),
-                            model.ScheduleModel.test_pab_account_id == (
-                                entity.test_pab_account_id))
-                        parent_schedules = parent_schedule_query.fetch()
-                        if not parent_schedules:
-                            logging.error("Parent not found.")
-                        else:
-                            parent_schedule = parent_schedules[0]
-                            parent_schedule.children_jobs.append(entity.key)
-                            entity.parent_schedule = parent_schedule.key
-                            to_put.append(parent_schedule)
-
-                elif model_type == "schedule":
-                    if entity.error_count is None:
-                        entity.error_count = 0
-                    if entity.suspended is None:
-                        entity.suspended = False
-                    if entity.build_storage_type is None:
-                        entity.build_storage_type = Status.STORAGE_TYPE_DICT[
-                            "PAB"]
-                    # remove None children jobs.
-                    if entity.children_jobs:
-                        entity.children_jobs = [
-                            x for x in entity.children_jobs if x]
-                    else:
-                        entity.children_jobs = []
-
-                    for attr in ["has_bootloader_img", "has_radio_img"]:
-                        if getattr(entity, attr, None) is None:
-                            setattr(entity, attr, True)
-
-                    # set priority_value for old schedules.
-                    if entity.priority_value is None:
-                        entity.priority_value = Status.GetPriorityValue(
-                            entity.priority)
-                else:
-                    pass
-                to_put.append(entity)
-
-            if to_put:
-                ndb.put_multi(to_put)
-                num_updated += len(to_put)
-
-        logging.info("{} indexing complete with {} updates!".format(
-            model_type, num_updated))
diff --git a/gae/webapp/src/tasks/indexing_test.py b/gae/webapp/src/tasks/indexing_test.py
deleted file mode 100644
index 5d14a56..0000000
--- a/gae/webapp/src/tasks/indexing_test.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src.proto import model
-from webapp.src.tasks import indexing
-from webapp.src.testing import unittest_base
-
-
-class IndexingHandlerTest(unittest_base.UnitTestBase):
-    """Tests for IndexingHandler.
-
-    Attributes:
-        testbed: A Testbed instance which provides local unit testing.
-        indexing_handler: A mock IndexingHandler instance.
-    """
-
-    def setUp(self):
-        """Initializes test"""
-        super(IndexingHandlerTest, self).setUp()
-        # Mocking IndexingHandler.
-        self.indexing_handler = indexing.IndexingHandler(mock.Mock())
-        self.indexing_handler.request = mock.Mock()
-
-    def testSingleJobReindexing(self):
-        """Asserts re-indexing links job and schedule successfully."""
-
-        print("\nCreating a single schedule...")
-        schedule = self.GenerateScheduleModel()
-        schedule.put()
-
-        schedules = model.ScheduleModel.query().fetch()
-        self.assertEqual(1, len(schedules))
-
-        print("Creating a job for stored schedule...")
-        for schedule in schedules:
-            job = model.JobModel()
-            job.priority = schedule.priority
-            job.test_name = schedule.test_name
-            job.period = schedule.period
-            job.build_storage_type = schedule.build_storage_type
-            job.manifest_branch = schedule.manifest_branch
-            job.build_target = schedule.build_target
-            job.pab_account_id = schedule.device_pab_account_id
-            job.shards = schedule.shards
-            job.retry_count = schedule.retry_count
-            job.gsi_storage_type = schedule.gsi_storage_type
-            job.gsi_branch = schedule.gsi_branch
-            job.gsi_build_target = schedule.gsi_build_target
-            job.gsi_pab_account_id = schedule.gsi_pab_account_id
-            job.gsi_vendor_version = schedule.gsi_vendor_version
-            job.test_storage_type = schedule.test_storage_type
-            job.test_branch = schedule.test_branch
-            job.test_build_target = schedule.test_build_target
-            job.test_pab_account_id = schedule.test_pab_account_id
-            job.put()
-
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(1, len(jobs))
-
-        print("Seeking children jobs before re-indexing...")
-        jobs = model.JobModel.query().fetch()
-        for job in jobs:
-            parent_key = job.parent_schedule
-            self.assertIsNone(parent_key)
-
-        print("Seeking children jobs after re-indexing...")
-        self.indexing_handler.request.get = mock.MagicMock(return_value="job")
-        self.indexing_handler.post()
-        jobs = model.JobModel.query().fetch()
-        for job in jobs:
-            parent_key = job.parent_schedule
-            parent_schedule = parent_key.get()
-            self.assertEqual(
-                True,
-                ((parent_schedule.priority == job.priority) and
-                 (parent_schedule.test_name == job.test_name) and
-                 (parent_schedule.period == job.period) and
-                 (parent_schedule.build_storage_type == job.build_storage_type)
-                 and (parent_schedule.manifest_branch == job.manifest_branch)
-                 and (parent_schedule.build_target == job.build_target) and
-                 (parent_schedule.device_pab_account_id == job.pab_account_id)
-                 and (parent_schedule.shards == job.shards) and
-                 (parent_schedule.retry_count == job.retry_count) and
-                 (parent_schedule.gsi_storage_type == job.gsi_storage_type) and
-                 (parent_schedule.gsi_branch == job.gsi_branch) and
-                 (parent_schedule.gsi_build_target == job.gsi_build_target) and
-                 (parent_schedule.gsi_pab_account_id == job.gsi_pab_account_id)
-                 and
-                 (parent_schedule.test_storage_type == job.test_storage_type)
-                 and (parent_schedule.test_branch == job.test_branch) and
-                 (parent_schedule.test_build_target == job.test_build_target)
-                 and (parent_schedule.test_pab_account_id ==
-                      job.test_pab_account_id)))
-
-    def testMultiJobReindexing(self):
-        """Asserts re-indexing links job and schedule successfully."""
-        print("\nCreating four schedules...")
-        for num in xrange(4):
-            schedule = self.GenerateScheduleModel(test_name=str(num + 1))
-            schedule.put()
-            schedule.put()
-
-        schedules = model.ScheduleModel.query().fetch()
-        self.assertEqual(4, len(schedules))
-
-        print("Creating jobs as number of test_name...")
-        for schedule in schedules:
-            for _ in xrange(int(schedule.test_name)):
-                job = model.JobModel()
-                job.priority = schedule.priority
-                job.test_name = schedule.test_name
-                job.period = schedule.period
-                job.build_storage_type = schedule.build_storage_type
-                job.manifest_branch = schedule.manifest_branch
-                job.build_target = schedule.build_target
-                job.pab_account_id = schedule.device_pab_account_id
-                job.shards = schedule.shards
-                job.retry_count = schedule.retry_count
-                job.gsi_storage_type = schedule.gsi_storage_type
-                job.gsi_branch = schedule.gsi_branch
-                job.gsi_build_target = schedule.gsi_build_target
-                job.gsi_pab_account_id = schedule.gsi_pab_account_id
-                job.gsi_vendor_version = schedule.gsi_vendor_version
-                job.test_storage_type = schedule.test_storage_type
-                job.test_branch = schedule.test_branch
-                job.test_build_target = schedule.test_build_target
-                job.test_pab_account_id = schedule.test_pab_account_id
-                job.put()
-
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(10, len(jobs))
-
-        print("Seeking children jobs before re-indexing...")
-        jobs = model.JobModel.query().fetch()
-        for job in jobs:
-            parent_key = job.parent_schedule
-            self.assertIsNone(parent_key)
-
-        print("Seeking children jobs after re-indexing...")
-        self.indexing_handler.request.get = mock.MagicMock(return_value="job")
-        self.indexing_handler.post()
-        jobs = model.JobModel.query().fetch()
-        for job in jobs:
-            parent_key = job.parent_schedule
-            parent_schedule = parent_key.get()
-            self.assertEqual(
-                True,
-                ((parent_schedule.priority == job.priority) and
-                 (parent_schedule.test_name == job.test_name) and
-                 (parent_schedule.period == job.period) and
-                 (parent_schedule.build_storage_type == job.build_storage_type)
-                 and (parent_schedule.manifest_branch == job.manifest_branch)
-                 and (parent_schedule.build_target == job.build_target) and
-                 (parent_schedule.device_pab_account_id == job.pab_account_id)
-                 and (parent_schedule.shards == job.shards) and
-                 (parent_schedule.retry_count == job.retry_count) and
-                 (parent_schedule.gsi_storage_type == job.gsi_storage_type) and
-                 (parent_schedule.gsi_branch == job.gsi_branch) and
-                 (parent_schedule.gsi_build_target == job.gsi_build_target) and
-                 (parent_schedule.gsi_pab_account_id == job.gsi_pab_account_id)
-                 and
-                 (parent_schedule.test_storage_type == job.test_storage_type)
-                 and (parent_schedule.test_branch == job.test_branch) and
-                 (parent_schedule.test_build_target == job.test_build_target)
-                 and (parent_schedule.test_pab_account_id ==
-                      job.test_pab_account_id)))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/tasks/removing_outdated_devices.py b/gae/webapp/src/tasks/removing_outdated_devices.py
deleted file mode 100644
index 6a4eeab..0000000
--- a/gae/webapp/src/tasks/removing_outdated_devices.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import datetime
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src.proto import model
-
-OUTDATED_DEVICE_REMOVE_TIME_IN_HOURS = 48
-
-
-class RemoveOutdatedDevices(webapp2.RequestHandler):
-    """Main class for /tasks/remove_outdated_devices.
-
-    Used to find outdated devices and remove them.
-    """
-
-    def get(self):
-        device_query = model.DeviceModel.query(
-            model.DeviceModel.timestamp < datetime.datetime.now() -
-            datetime.timedelta(hours=OUTDATED_DEVICE_REMOVE_TIME_IN_HOURS))
-        outdated_devices = device_query.fetch(keys_only=True)
-        ndb.delete_multi(outdated_devices)
diff --git a/gae/webapp/src/tasks/removing_outdated_devices_test.py b/gae/webapp/src/tasks/removing_outdated_devices_test.py
deleted file mode 100644
index 6ff57d4..0000000
--- a/gae/webapp/src/tasks/removing_outdated_devices_test.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src.proto import model
-from webapp.src.tasks import removing_outdated_devices
-from webapp.src.testing import unittest_base
-
-
-class RemoveOutdatedDevicesTest(unittest_base.UnitTestBase):
-    """Tests for RemoveOutdatedDevices cron class.
-
-    Attributes:
-        remove_outdated_device: A mock device_heartbeat.RemoveOutdatedDevices
-                                instance.
-    """
-
-    def setUp(self):
-        """Initializes test"""
-        super(RemoveOutdatedDevicesTest, self).setUp()
-        # Mocking RemoveOutdatedDevices and essential methods.
-        self.remove_outdated_device = (
-            removing_outdated_devices.RemoveOutdatedDevices(mock.Mock()))
-        self.remove_outdated_device.response = mock.Mock()
-        self.remove_outdated_device.response.write = mock.Mock()
-
-    def testRemoveOutdatedDevicesTest(self):
-        """Asserts job heartbeat detects unavailable jobs."""
-        device_a_serial = "a"
-        device_b_serial = "b"
-        device_c_serial = "c"
-        device_d_serial = "c"
-
-        # create a device A, which is outdated.
-        device = self.GenerateDeviceModel(serial=device_a_serial)
-        device.timestamp = datetime.datetime.now() - datetime.timedelta(
-            hours=100)
-        device.put()
-
-        # create a device B, which is offline for a day.
-        device = self.GenerateDeviceModel(serial=device_b_serial)
-        device.timestamp = datetime.datetime.now() - datetime.timedelta(
-            hours=24)
-        device.put()
-
-        # create a device C and D, which are alive.
-        for serial in [device_c_serial, device_d_serial]:
-            device = self.GenerateDeviceModel(serial=serial)
-            device.timestamp = datetime.datetime.now()
-            device.put()
-
-        # Remove outdated devices.
-        self.remove_outdated_device.get()
-
-        devices = model.DeviceModel.query().fetch()
-
-        # device A should not be included.
-        self.assertEqual(len(devices), 3)
-        self.assertTrue(device_a_serial not in [x.serial for x in devices])
-
-        # change devices' timestamp
-        for device in devices:
-            device.timestamp = device.timestamp - datetime.timedelta(hours=25)
-            device.put()
-
-        # Remove outdated devices.
-        self.remove_outdated_device.get()
-
-        devices = model.DeviceModel.query().fetch()
-
-        # Now device B should not be included also.
-        self.assertEqual(len(devices), 2)
-        self.assertTrue(device_b_serial not in [x.serial for x in devices])
-
-        # change devices' timestamp
-        for device in devices:
-            device.timestamp = device.timestamp - datetime.timedelta(hours=25)
-            device.put()
-
-        # Remove outdated devices.
-        self.remove_outdated_device.get()
-
-        devices = model.DeviceModel.query().fetch()
-
-        # Now there should not be no devices.
-        self.assertEqual(len(devices), 0)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/testing/__init__.py b/gae/webapp/src/testing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/testing/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/testing/unittest_base.py b/gae/webapp/src/testing/unittest_base.py
deleted file mode 100644
index 0e47ee0..0000000
--- a/gae/webapp/src/testing/unittest_base.py
+++ /dev/null
@@ -1,347 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import random
-import string
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from google.appengine.ext import ndb
-from google.appengine.ext import testbed
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-
-
-class UnitTestBase(unittest.TestCase):
-    """Base class for unittest.
-
-    Attributes:
-        testbed: A Testbed instance which provides local unit testing.
-        random_strs: a list of strings generated by GetRandomString() method
-                     in order to avoid duplicates.
-    """
-    random_strs = []
-
-    def setUp(self):
-        """Initializes unittest."""
-        # Create the Testbed class instance and initialize service stubs.
-        self.testbed = testbed.Testbed()
-        self.testbed.activate()
-        self.testbed.init_datastore_v3_stub()
-        self.testbed.init_memcache_stub()
-        self.testbed.init_mail_stub()
-        self.testbed.setup_env(app_id="vtslab-schedule-unittest")
-        # Clear cache between tests.
-        ndb.get_context().clear_cache()
-
-    def tearDown(self):
-        self.testbed.deactivate()
-
-    def GetRandomString(self, length=7):
-        """Generates and returns a random string.
-
-        Args:
-            length: an integer, string length.
-
-        Returns:
-            a random string.
-        """
-        new_str = ""
-        while new_str == "" or new_str in self.random_strs:
-            new_str = "".join(
-                random.choice(string.ascii_letters + string.digits)
-                for _ in range(length))
-        return new_str
-
-    def GenerateLabModel(self, lab_name=None, host_name=None):
-        """Builds model.LabModel with given information.
-
-        Args:
-            lab_name: a string, lab name.
-            host_name: a string, host name.
-
-        Returns:
-            model.LabModel instance.
-        """
-        lab = model.LabModel()
-        lab.name = lab_name if lab_name else self.GetRandomString()
-        lab.hostname = host_name if host_name else self.GetRandomString()
-        lab.owner = "test@abc.com"
-        lab.ip = "100.100.100.100"
-        return lab
-
-    def GenerateDeviceModel(
-            self,
-            status=Status.DEVICE_STATUS_DICT["fastboot"],
-            scheduling_status=Status.DEVICE_SCHEDULING_STATUS_DICT["free"],
-            **kwargs):
-        """Builds model.DeviceModel with given information.
-
-        Args:
-            status: an integer, device's initial status.
-            scheduling_status: an integer, device's initial scheduling status.
-            **kwargs: the optional arguments.
-
-        Returns:
-            model.DeviceModel instance.
-        """
-        device = model.DeviceModel()
-        device.status = status
-        device.scheduling_status = scheduling_status
-        device.timestamp = datetime.datetime.now()
-
-        skip_list = ["status", "scheduling_status", "timestamp"]
-        set_or_empty = []
-        for arg in device._properties:
-            if arg in skip_list or (arg in set_or_empty and arg not in kwargs):
-                continue
-            if arg in kwargs:
-                value = kwargs[arg]
-            elif isinstance(device._properties[arg], ndb.StringProperty):
-                value = self.GetRandomString()
-            elif isinstance(device._properties[arg], ndb.IntegerProperty):
-                value = 0
-            elif isinstance(device._properties[arg], ndb.BooleanProperty):
-                value = False
-            else:
-                print("A type of property '{}' is not supported.".format(arg))
-                continue
-            if device._properties[arg]._repeated and type(value) is not list:
-                value = [value]
-            setattr(device, arg, value)
-        return device
-
-    def GenerateScheduleModel(
-            self,
-            device_model=None,
-            lab_model=None,
-            priority="medium",
-            period=360,
-            retry_count=1,
-            shards=1,
-            lab_name=None,
-            device_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-            device_branch=None,
-            device_target=None,
-            gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-            gsi_build_target=None,
-            test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
-            test_build_target=None,
-            required_signed_device_build=False,
-            **kwargs):
-        """Builds model.ScheduleModel with given information.
-
-        Args:
-            device_model: a model.DeviceModel instance to refer device product.
-            lab_model: a model.LabModel instance to refer host name.
-            priority: a string, scheduling priority
-            period: an integer, scheduling period.
-            retry_count: an integer, scheduling retry count.
-            shards: an integer, # ways of device shards.
-            lab_name: a string, target lab name.
-            device_storage_type: an integer, device storage type
-            device_branch: a string, device build branch.
-            device_target: a string, device build target.
-            gsi_storage_type: an integer, GSI storage type
-            gsi_build_target: a string, GSI build target.
-            test_storage_type: an integer, test storage type
-            test_build_target: a string, test build target.
-            required_signed_device_build: a boolean, True to schedule for signed
-                                          device build, False if not.
-            **kwargs: the optional arguments.
-
-        Returns:
-            model.ScheduleModel instance.
-        """
-
-        if device_model:
-            device_product = device_model.product
-            device_target = self.GetRandomString(4)
-        elif device_target:
-            device_product, device_target = device_target.split("-")
-        else:
-            device_product = self.GetRandomString(7)
-            device_target = self.GetRandomString(4)
-
-        if lab_model:
-            lab = lab_model.name
-        elif lab_name:
-            lab = lab_name
-        else:
-            lab = self.GetRandomString()
-
-        schedule = model.ScheduleModel()
-        schedule.priority = priority
-        schedule.priority_value = Status.GetPriorityValue(schedule.priority)
-        schedule.period = period
-        schedule.shards = shards
-        schedule.retry_count = retry_count
-        schedule.required_signed_device_build = required_signed_device_build
-        schedule.build_storage_type = device_storage_type
-        schedule.manifest_branch = (device_branch if device_branch else
-                                    self.GetRandomString())
-        schedule.build_target = "-".join([device_product, device_target])
-
-        schedule.gsi_storage_type = gsi_storage_type
-        schedule.gsi_build_target = (gsi_build_target
-                                     if gsi_build_target else "-".join([
-                                         self.GetRandomString(),
-                                         self.GetRandomString(4)
-                                     ]))
-        schedule.test_storage_type = test_storage_type
-        schedule.test_build_target = (test_build_target
-                                      if test_build_target else "-".join([
-                                          self.GetRandomString(),
-                                          self.GetRandomString(4)
-                                      ]))
-        schedule.device = []
-        schedule.device.append("/".join([lab, device_product]))
-
-        schedule.timestamp = datetime.datetime.now()
-
-        skip_list = [
-            "priority", "priority_value", "period", "shards",
-            "retry_count", "required_signed_device_build",
-            "build_storage_type", "manifest_branch", "build_target",
-            "gsi_storage_type", "gsi_build_target",
-            "test_storage_type", "test_build_target", "device",
-            "children_jobs"]
-        set_or_empty = ["required_host_equipment", "required_device_equipment"]
-        for arg in schedule._properties:
-            if arg in skip_list or (arg in set_or_empty and arg not in kwargs):
-                continue
-            if arg in kwargs:
-                value = kwargs[arg]
-            elif isinstance(schedule._properties[arg], ndb.StringProperty):
-                value = self.GetRandomString()
-            elif isinstance(schedule._properties[arg], ndb.IntegerProperty):
-                value = 0
-            elif isinstance(schedule._properties[arg], ndb.BooleanProperty):
-                value = False
-            else:
-                print("A type of property '{}' is not supported.".format(arg))
-                continue
-            if schedule._properties[arg]._repeated and type(value) is not list:
-                value = [value]
-            setattr(schedule, arg, value)
-
-        return schedule
-
-    def GenerateBuildModel(self, schedule, targets=None):
-        """Builds model.BuildModel with given information.
-
-        Args:
-            schedule: a model.ScheduleModel instance to look up build info.
-            targets: a list of strings which indicates artifact type.
-
-        Returns:
-            model.BuildModel instance.
-        """
-        build_dict = {}
-        if targets is None:
-            targets = ["device", "gsi", "test"]
-        for target in targets:
-            build = model.BuildModel()
-            build.artifact_type = target
-            build.timestamp = datetime.datetime.now()
-            if target == "device":
-                build.signed = schedule.required_signed_device_build
-                build.manifest_branch = schedule.manifest_branch
-                build.build_target, build.build_type = (
-                    schedule.build_target.split("-"))
-            elif target == "gsi":
-                build.manifest_branch = schedule.gsi_branch
-                build.build_target, build.build_type = (
-                    schedule.gsi_build_target.split("-"))
-            elif target == "test":
-                build.manifest_branch = schedule.test_branch
-                build.build_target, build.build_type = (
-                    schedule.test_build_target.split("-"))
-            build.build_id = self.GetNewBuildId(build)
-            build_dict[target] = build
-        return build_dict
-
-    def GetNewBuildId(self, build):
-        """Generates build ID.
-
-        This method always generates newest (higher number) build ID than other
-        builds stored in testbed datastore.
-
-        Args:
-            build: a model.BuildModel instance to look up build information
-                   from testbed datastore.
-
-        Returns:
-            a string, build ID.
-        """
-        format_string = "{0:07d}"
-        build_query = model.BuildModel.query(
-            model.BuildModel.artifact_type == build.artifact_type,
-            model.BuildModel.build_target == build.build_target,
-            model.BuildModel.signed == build.signed,
-            model.BuildModel.manifest_branch == build.manifest_branch)
-        exiting_builds = build_query.fetch()
-        if exiting_builds:
-            exiting_builds.sort(key=lambda x: x.build_id, reverse=True)
-            latest_build_id = int(exiting_builds[0].build_id)
-            return format_string.format(latest_build_id + 1)
-        else:
-            return format_string.format(1)
-
-    def PassTime(self, hours=0, minutes=0, seconds=0):
-        """Assumes that a certain amount of time has passed.
-
-        This method changes does not change actual system time but changes all
-        jobs timestamp to assume time has passed.
-
-        Args:
-            hours: an integer, number of hours to pass time.
-            minutes: an integer, number of minutes to pass time.
-            seconds: an integer, number of seconds to pass time.
-        """
-        if not hours and not minutes and not seconds:
-            return
-
-        jobs = model.JobModel.query().fetch()
-        to_put = []
-        for job in jobs:
-            if job.timestamp:
-                job.timestamp -= datetime.timedelta(
-                    hours=hours, minutes=minutes, seconds=seconds)
-            if job.heartbeat_stamp:
-                job.heartbeat_stamp -= datetime.timedelta(
-                    hours=hours, minutes=minutes, seconds=seconds)
-            to_put.append(job)
-        if to_put:
-            ndb.put_multi(to_put)
-
-    def ResetDevices(self):
-        """Resets all devices to ready status."""
-        devices = model.DeviceModel.query().fetch()
-        to_put = []
-        for device in devices:
-            device.status = Status.DEVICE_STATUS_DICT["fastboot"]
-            device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
-                "free"]
-            to_put.append(device)
-        if to_put:
-            ndb.put_multi(to_put)
diff --git a/gae/webapp/src/utils/__init__.py b/gae/webapp/src/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/utils/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/utils/datetime_util.py b/gae/webapp/src/utils/datetime_util.py
deleted file mode 100644
index a1cff67..0000000
--- a/gae/webapp/src/utils/datetime_util.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import logging
-import pytz
-
-
-def GetTimeWithTimezone(dt, timezone="US/Pacific"):
-    """Converts timezone of datetime.datetime() instance.
-
-    Args:
-        dt: datetime.datetime() instance.
-        timezone: a string representing timezone listed in TZ database.
-
-    Returns:
-        datetime.datetime() instance with the given timezone.
-    """
-    if not dt:
-        return None
-    utc_time = dt.replace(tzinfo=pytz.utc)
-    try:
-        converted_time = utc_time.astimezone(pytz.timezone(timezone))
-    except pytz.UnknownTimeZoneError as e:
-        logging.exception(e)
-        converted_time = dt
-    return converted_time
diff --git a/gae/webapp/src/utils/email_util.py b/gae/webapp/src/utils/email_util.py
deleted file mode 100644
index 2ef795e..0000000
--- a/gae/webapp/src/utils/email_util.py
+++ /dev/null
@@ -1,295 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import re
-
-from google.appengine.api import app_identity
-from google.appengine.api import mail
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import datetime_util
-
-SENDER_ADDRESS = "noreply@{}.appspotmail.com"
-
-SEND_NOTIFICATION_FOOTER = (
-    "You are receiving this email because you are "
-    "listed as an owner, or an administrator of the "
-    "lab {}.\nIf you received this email by mistake, "
-    "please send an email to VTS Lab infra development "
-    "team. Thank you.")
-
-SEND_DEVICE_NOTIFICATION_TITLE = ("[VTS lab] Devices not responding in lab {} "
-                                  "({})")
-SEND_DEVICE_NOTIFICATION_HEADER = "Devices in lab {} are not responding."
-
-SEND_JOB_NOTIFICATION_TITLE = ("[VTS lab] Job error has been occurred in "
-                               "lab {} ({})")
-SEND_JOB_NOTIFICATION_HEADER = ("Jobs in lab {} have been completed "
-                                "unexpectedly.")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_TITLE = (
-    "[VTS lab] A job schedule has been {}. ({})")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_HEADER = ("The below job schedule has "
-                                                "been {}.")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_FOOTER = (
-    "You are receiving this email because one or more labs which you are "
-    "listed as an owner or an administrator are affected.\nIf you received "
-    "this email by mistake, please send an email to VTS Lab infra development "
-    "team. Thank you.")
-
-
-def send_device_notification(devices):
-    """Sends notification for not responding devices.
-
-    Args:
-        devices: a dict containing lab and host information of no-response
-                 devices.
-    """
-    for lab in devices:
-        email_message = mail.EmailMessage()
-        email_message.sender = SENDER_ADDRESS.format(
-            app_identity.get_application_id())
-        try:
-            email_message.to = verify_recipient_address(
-                devices[lab]["_recipients"])
-        except ValueError as e:
-            logging.error(e)
-            continue
-        email_message.subject = SEND_DEVICE_NOTIFICATION_TITLE.format(
-            lab,
-            datetime_util.GetTimeWithTimezone(
-                datetime.datetime.now()).strftime("%Y-%m-%d"))
-        message = ""
-        message += SEND_DEVICE_NOTIFICATION_HEADER.format(lab)
-        message += "\n\n"
-        for host in devices[lab]:
-            if host == "_recipients" or not devices[lab][host]:
-                continue
-            message += "hostname\n"
-            message += host
-            message += "\n\ndevices\n"
-            message += "\n".join(devices[lab][host])
-            message += "\n\n\n"
-        message += "\n\n"
-        message += SEND_NOTIFICATION_FOOTER.format(lab)
-
-        try:
-            email_message.body = message
-            email_message.check_initialized()
-            email_message.send()
-        except mail.MissingRecipientError as e:
-            logging.exception(e)
-
-
-def send_job_notification(jobs):
-    """Sends notification for job error.
-
-    Args:
-        jobs: a JobModel entity, or a list of JobModel entities.
-    """
-    if not jobs:
-        return
-    if type(jobs) is not list:
-        jobs = [jobs]
-
-    # grouping jobs by lab to send to each lab owner and admins at once.
-    labs_to_alert = {}
-    for job in jobs:
-        lab_query = model.LabModel.query(
-            model.LabModel.hostname == job.hostname)
-        labs = lab_query.fetch()
-        if labs:
-            lab = labs[0]
-            if lab.name not in labs_to_alert:
-                labs_to_alert[lab.name] = {}
-                labs_to_alert[lab.name]["jobs"] = []
-                labs_to_alert[lab.name]["_recipients"] = []
-            if lab.owner not in labs_to_alert[lab.name]["_recipients"]:
-                labs_to_alert[lab.name]["_recipients"].append(lab.owner)
-            labs_to_alert[lab.name]["_recipients"].extend([
-                x for x in lab.admin
-                if x not in labs_to_alert[lab.name]["_recipients"]
-            ])
-            labs_to_alert[lab.name]["jobs"].append(job)
-        else:
-            logging.warning(
-                "Could not find a lab model for hostname {}".format(
-                    job.hostname))
-            continue
-
-    for lab in labs_to_alert:
-        email_message = mail.EmailMessage()
-        email_message.sender = SENDER_ADDRESS.format(
-            app_identity.get_application_id())
-        try:
-            email_message.to = verify_recipient_address(
-                labs_to_alert[lab]["_recipients"])
-        except ValueError as e:
-            logging.error(e)
-            continue
-        email_message.subject = SEND_JOB_NOTIFICATION_TITLE.format(
-            lab,
-            datetime_util.GetTimeWithTimezone(
-                datetime.datetime.now()).strftime("%Y-%m-%d"))
-        message = ""
-        message += SEND_JOB_NOTIFICATION_HEADER.format(lab)
-        message += "\n\n"
-        message += "http://{}.appspot.com/job".format(
-            app_identity.get_application_id())
-        message += "\n\n"
-        for job in labs_to_alert[lab]["jobs"]:
-            message += "hostname: {}\n\n".format(job.hostname)
-            message += "device: {}\n".format(job.device.split("/")[1])
-            message += "device serial: {}\n".format(", ".join(job.serial))
-            message += (
-                "device: branch - {}, target - {}, build_id - {}\n").format(
-                    job.manifest_branch, job.build_target, job.build_id)
-            message += "gsi: branch - {}, target - {}, build_id - {}\n".format(
-                job.gsi_branch, job.gsi_build_target, job.gsi_build_id)
-            message += "test: branch - {}, target - {}, build_id - {}\n".format(
-                job.test_branch, job.test_build_target, job.test_build_id)
-            message += "job created: {}\n".format(
-                datetime_util.GetTimeWithTimezone(
-                    job.timestamp).strftime("%Y-%m-%d %H:%M:%S %Z"))
-            message += "job status: {}\n".format([
-                key for key, value in Status.JOB_STATUS_DICT.items()
-                if value == job.status
-            ][0])
-            message += "\n\n\n"
-        message += "\n\n"
-        message += SEND_NOTIFICATION_FOOTER.format(lab)
-
-        try:
-            email_message.body = message
-            email_message.check_initialized()
-            email_message.send()
-        except mail.MissingRecipientError as e:
-            logging.exception(e)
-
-
-def send_schedule_suspension_notification(schedule):
-    """Sends notification when a schedule is suspended, or resumed.
-
-    Args:
-        schedule: a ScheduleModel entity.
-    """
-    if not schedule:
-        return
-
-    if not schedule.device:
-        return
-
-    email_message = mail.EmailMessage()
-    email_message.sender = SENDER_ADDRESS.format(
-        app_identity.get_application_id())
-
-    lab_names = []
-    for device in schedule.device:
-        if not "/" in device:
-            continue
-        lab_name = device.split("/")[0]
-        lab_names.append(lab_name)
-
-    recipients = []
-    for lab_name in lab_names:
-        lab_query = model.LabModel.query(model.LabModel.name == lab_name)
-        labs = lab_query.fetch()
-        if labs:
-            lab = labs[0]
-            if lab.owner not in recipients:
-                recipients.append(lab.owner)
-            recipients.extend([x for x in lab.admin if x not in recipients])
-        else:
-            logging.warning(
-                "Could not find a lab model for lab {}".format(lab_name))
-
-    try:
-        email_message.to = verify_recipient_address(recipients)
-    except ValueError as e:
-        logging.error(e)
-        return
-
-    status_text = "suspended" if schedule.suspended else "resumed"
-    email_message.subject = SEND_SCHEDULE_SUSPENSION_NOTIFICATION_TITLE.format(
-        status_text,
-        datetime_util.GetTimeWithTimezone(
-            datetime.datetime.now()).strftime("%Y-%m-%d"))
-    message = ""
-    message += SEND_SCHEDULE_SUSPENSION_NOTIFICATION_HEADER.format(status_text)
-    message += "\n\n"
-    message += "\n\ndevices\n"
-    message += "\n".join(schedule.device)
-    message += "\n\ndevice branch\n"
-    message += schedule.manifest_branch
-    message += "\n\ndevice build target\n"
-    message += schedule.build_target
-    message += "\n\ngsi branch\n"
-    message += schedule.gsi_branch
-    message += "\n\ngsi build target\n"
-    message += schedule.gsi_build_target
-    message += "\n\ntest branch\n"
-    message += schedule.test_branch
-    message += "\n\ntest build target\n"
-    message += schedule.test_build_target
-    message += "\n\n"
-    message += ("Please see the details in the following link: "
-                "http://{}.appspot.com/schedule".format(
-                    app_identity.get_application_id()))
-    message += "\n\n\n\n"
-    message += SEND_SCHEDULE_SUSPENSION_NOTIFICATION_FOOTER
-
-    try:
-        email_message.body = message
-        email_message.check_initialized()
-        email_message.send()
-    except mail.MissingRecipientError as e:
-        logging.exception(e)
-
-
-def verify_recipient_address(address):
-    """Verifies recipients address.
-
-    Args:
-        address: a list of strings or a string, recipient(s) address.
-
-    Returns:
-        A list of verified addresses if list type argument is given, or
-        a string of a verified address if str type argument is given.
-
-    Raises:
-        ValueError if type of address is neither list nor str.
-    """
-    # pattern for 'any@google.com', and 'any name <any@google.com>'
-    verify_patterns = [
-        re.compile(".*@google\.com$"),
-        re.compile(".*<.*@google\.com>$")
-    ]
-    if not address:
-        return None
-    if type(address) is list:
-        verified_address = [
-            x for x in address
-            if any(pattern.match(x) for pattern in verify_patterns)
-        ]
-        return verified_address
-    elif type(address) is str:
-        return address if any(
-            pattern.match(address) for pattern in verify_patterns) else None
-    else:
-        raise ValueError("Wrong type - {}.".format(type(address)))
diff --git a/gae/webapp/src/utils/logger.py b/gae/webapp/src/utils/logger.py
deleted file mode 100644
index 20c03d2..0000000
--- a/gae/webapp/src/utils/logger.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-
-class Logger(object):
-    """A class to log messages to a list of strings.
-
-    Attributes:
-        log_message: a list of strings, containing the log messages.
-        log_indent: integer, representing the index level
-    """
-
-    def __init__(self):
-        self.log_message = []
-        self.log_indent = 0
-
-    def Clear(self):
-        """Clears the log buffer."""
-        self.log_message = []
-        self.log_indent = 0
-
-    def Get(self):
-        """Retruns a list of all log message strings."""
-        return self.log_message
-
-    def Println(self, msg):
-        """Stores a new string `msg` to the log buffer."""
-        indent = "  " * self.log_indent
-        if msg and type(msg) is not str:
-            msg = str(msg)
-        self.log_message.append(indent + msg)
-
-    def Indent(self):
-        """Increase indent of log message."""
-        self.log_indent += 1
-
-    def Unindent(self):
-        """Decrease indent of log message."""
-        if self.log_indent > 0:
-            self.log_indent -= 1
diff --git a/gae/webapp/src/utils/model_util.py b/gae/webapp/src/utils/model_util.py
deleted file mode 100644
index aa07a63..0000000
--- a/gae/webapp/src/utils/model_util.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from webapp.src import vtslab_status as Status
-from webapp.src.utils import email_util
-
-
-def UpdateParentSchedule(job, status):
-    """Updates a parent schedule of the given job with status.
-
-    Args:
-        job: a JobModel entity.
-        status: an integer, job status value.
-    """
-    if status not in [
-        Status.JOB_STATUS_DICT["complete"],
-        Status.JOB_STATUS_DICT["infra-err"],
-        Status.JOB_STATUS_DICT["expired"],
-        Status.JOB_STATUS_DICT["bootup-err"]
-    ]:
-        return
-
-    if job.parent_schedule:
-        schedule = job.parent_schedule.get()
-        if schedule:
-            previous_suspended = schedule.suspended
-            if schedule.error_count is None:
-                schedule.error_count = 0
-            if status == Status.JOB_STATUS_DICT["complete"]:
-                schedule.error_count = 0
-                schedule.suspended = False
-            elif status in [
-                Status.JOB_STATUS_DICT["infra-err"],
-                Status.JOB_STATUS_DICT["expired"],
-                Status.JOB_STATUS_DICT["bootup-err"]
-            ]:
-                schedule.error_count += 1
-                if schedule.error_count >= Status.NUM_ERRORS_FOR_SUSPENSION:
-                    schedule.suspended = True
-            schedule.put()
-            if previous_suspended != schedule.suspended:
-                email_util.send_schedule_suspension_notification(schedule)
diff --git a/gae/webapp/src/utils/model_util_test.py b/gae/webapp/src/utils/model_util_test.py
deleted file mode 100644
index 4be54b1..0000000
--- a/gae/webapp/src/utils/model_util_test.py
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-from webapp.src.utils import model_util
-
-
-class ModelTest(unittest_base.UnitTestBase):
-    """Tests for PeriodicJobHeartBeat cron class."""
-
-    def testJobAndScheduleModel(self):
-        """Asserts JobModel and ScheduleModel.
-
-        When JobModel's status is changed, ScheduleModel's error_count is
-        changed based on the status. This should not be applied before JobModel
-        entity is updated to Datastore.
-        """
-        period = 360
-
-        lab = self.GenerateLabModel()
-        lab.put()
-
-        device = self.GenerateDeviceModel(hostname=lab.hostname)
-        device.put()
-
-        schedule = self.GenerateScheduleModel(
-            device_model=device, lab_model=lab, period=period)
-        schedule.put()
-
-        build_dict = self.GenerateBuildModel(schedule)
-        for key in build_dict:
-            build_dict[key].put()
-
-        # Mocking ScheduleHandler and essential methods.
-        scheduler = schedule_worker.ScheduleHandler(mock.Mock())
-        scheduler.response = mock.Mock()
-        scheduler.response.write = mock.Mock()
-        scheduler.request.get = mock.MagicMock(return_value="")
-
-        print("\nCreating a job...")
-        scheduler.post()
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(1, len(jobs))
-
-        print("Occurring infra error...")
-        job = jobs[0]
-        job.status = Status.JOB_STATUS_DICT["infra-err"]
-        parent_schedule = job.parent_schedule.get()
-        parent_from_db = model.ScheduleModel.query().fetch()[0]
-
-        # in test error_count could be None but in real there will be no None.
-        self.assertNotEqual(1, parent_schedule.error_count)
-        self.assertNotEqual(1, parent_from_db.error_count)
-
-        # error count should be changed after put
-        job.put()
-        model_util.UpdateParentSchedule(job, job.status)
-        self.assertEqual(1, parent_schedule.error_count)
-        self.assertEqual(1, parent_from_db.error_count)
-
-        print("Suspending a job...")
-        for num in xrange(2):
-            jobs = model.JobModel.query().fetch()
-            for job in jobs:
-                job.timestamp = datetime.datetime.now() - datetime.timedelta(
-                    minutes=(period + 10))
-                job.put()
-
-            parent_from_db = model.ScheduleModel.query().fetch()[0]
-            self.assertEqual(1 + num, parent_schedule.error_count)
-            self.assertEqual(1 + num, parent_from_db.error_count)
-
-            # reset a device manually to re-schedule
-            device = model.DeviceModel.query().fetch()[0]
-            device.status = Status.DEVICE_STATUS_DICT["fastboot"]
-            device.scheduling_status = (
-                Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-            device.timestamp = datetime.datetime.now()
-            device.put()
-
-            scheduler.post()
-            jobs = model.JobModel.query().fetch()
-            self.assertEqual(2 + num, len(jobs))
-
-            ready_jobs = model.JobModel.query(
-                model.JobModel.status == Status.JOB_STATUS_DICT[
-                    "ready"]).fetch()
-            self.assertEqual(1, len(ready_jobs))
-
-            ready_job = ready_jobs[0]
-            ready_job.status = Status.JOB_STATUS_DICT["infra-err"]
-            parent_schedule = ready_job.parent_schedule.get()
-            parent_from_db = model.ScheduleModel.query().fetch()[0]
-            self.assertEqual(1 + num, parent_schedule.error_count)
-            self.assertEqual(1 + num, parent_from_db.error_count)
-
-            # # error count should be changed after put
-            ready_job.put()
-            model_util.UpdateParentSchedule(ready_job, ready_job.status)
-            self.assertEqual(2 + num, parent_schedule.error_count)
-            self.assertEqual(2 + num, parent_from_db.error_count)
-
-        print("Asserting a schedule's suspend status...")
-        # after three errors the schedule should be suspended.
-        schedule_from_db = model.ScheduleModel.query().fetch()[0]
-        schedule_from_db.put()
-        self.assertEqual(3, schedule_from_db.error_count)
-        self.assertEqual(True, schedule_from_db.suspended)
-
-        # reset a device manually to re-schedule
-        device = model.DeviceModel.query().fetch()[0]
-        device.status = Status.DEVICE_STATUS_DICT["fastboot"]
-        device.scheduling_status = (
-            Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-        device.timestamp = datetime.datetime.now()
-        device.put()
-
-        print("Asserting that job creation is blocked...")
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(3, len(jobs))
-
-        for job in jobs:
-            job.timestamp = datetime.datetime.now() - datetime.timedelta(
-                minutes=(period + 10))
-            job.put()
-
-        scheduler.post()
-
-        # a job should not be created.
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(3, len(jobs))
-
-        print("Asserting that job creation is allowed after resuming...")
-        schedule_from_db = model.ScheduleModel.query().fetch()[0]
-        schedule_from_db.suspended = False
-        schedule_from_db.put()
-
-        scheduler.post()
-
-        jobs = model.JobModel.query().fetch()
-        self.assertEqual(4, len(jobs))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/gae/webapp/src/vtslab_status.py b/gae/webapp/src/vtslab_status.py
deleted file mode 100644
index c1d1363..0000000
--- a/gae/webapp/src/vtslab_status.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Status dict updated from HC.
-DEVICE_STATUS_DICT = {
-    # default state, currently not in use.
-    "unknown": 0,
-    # for devices detected via "fastboot devices" shell command.
-    "fastboot": 1,
-    # for devices detected via "adb devices" shell command.
-    "online": 2,
-    # currently not in use.
-    "ready": 3,
-    # currently not in use.
-    "use": 4,
-    # for devices in error state.
-    "error": 5,
-    # for devices which timed out (not detected either via fastboot or adb).
-    "no-response": 6
-}
-
-# Scheduling status dict based on the status of each jobs in job queue.
-DEVICE_SCHEDULING_STATUS_DICT = {
-    # for devices detected but not scheduled.
-    "free": 0,
-    # for devices scheduled but not running.
-    "reserved": 1,
-    # for devices scheduled for currently leased job(s).
-    "use": 2
-}
-
-# Job status dict
-JOB_STATUS_DICT = {
-    # scheduled but not leased yet
-    "ready": 0,
-    # scheduled and in running
-    "leased": 1,
-    # completed job
-    "complete": 2,
-    # unexpected error during running
-    "infra-err": 3,
-    # never leased within schedule period
-    "expired": 4,
-    # device boot error after flashing the given img sets
-    "bootup-err": 5
-}
-
-JOB_PRIORITY_DICT = {
-    "top": 3,
-    "high": 6,
-    "medium": 9,
-    "low": 12,
-    "other": 15
-}
-
-
-STORAGE_TYPE_DICT = {
-    "unknown": 0,
-    "PAB": 1,
-    "GCS": 2
-}
-
-
-TEST_TYPE_UNKNOWN = "unknown"
-TEST_TYPE_TOT = "ToT"
-TEST_TYPE_OTA = "OTA"
-TEST_TYPE_SIGNED = "signed"
-TEST_TYPE_PRESUBMIT = "presubmit"
-TEST_TYPE_MANUAL = "manual"
-
-# a dict, where keys indicate test type and values have bitwise values.
-# bit 0-1  : version related test type
-#            00 - Unknown
-#            01 - ToT
-#            10 - OTA
-# bit 2    : device signed build
-# bit 3-4  : reserved for gerrit related test type
-#            01 - pre-submit
-# bit 5    : manually created test job
-TEST_TYPE_DICT = {
-    TEST_TYPE_UNKNOWN: 0,
-    TEST_TYPE_TOT: 1,
-    TEST_TYPE_OTA: 1 << 1,
-    TEST_TYPE_SIGNED: 1 << 2,
-    TEST_TYPE_PRESUBMIT: 1 << 3,
-    TEST_TYPE_MANUAL: 1 << 5
-}
-
-# # of errors in a row to suspend a schedule
-NUM_ERRORS_FOR_SUSPENSION = 3
-
-# filter methods
-FILTER_EqualTo = "EqualTo"
-FILTER_LessThan = "LessThan"
-FILTER_GreaterThan = "GreaterThan"
-FILTER_LessThanOrEqualTo = "LessThanOrEqualTo"
-FILTER_GreaterThanOrEqualTo = "GreaterThanOrEqualTo"
-FILTER_NotEqualTo = "NotEqualTo"
-FILTER_Has = "Has"
-
-FILTER_METHOD = {
-    FILTER_EqualTo: 1,
-    FILTER_LessThan: 2,
-    FILTER_GreaterThan: 3,
-    FILTER_LessThanOrEqualTo: 4,
-    FILTER_GreaterThanOrEqualTo: 5,
-    FILTER_NotEqualTo: 6,
-    FILTER_Has: 7,
-}
-
-
-def GetPriorityValue(priority):
-    """Helper function to sort jobs based on priority.
-
-    Args:
-        priority: string, the job priority.
-
-    Returns:
-        int, priority order (the lower, the higher)
-    """
-    if priority:
-        priority = priority.lower()
-        if priority in JOB_PRIORITY_DICT:
-            return JOB_PRIORITY_DICT[priority]
-    return JOB_PRIORITY_DICT["other"]
diff --git a/gae/webapp/src/webapp_main.py b/gae/webapp/src/webapp_main.py
deleted file mode 100644
index 2587f4b..0000000
--- a/gae/webapp/src/webapp_main.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-
-import webapp2
-
-from webapp.src.handlers import base
-from webapp.src.scheduler import device_heartbeat
-from webapp.src.scheduler import job_heartbeat
-from webapp.src.scheduler import periodic
-from webapp.src.tasks import indexing
-from webapp.src.tasks import removing_outdated_devices
-
-
-class RedirectHandler(base.BaseHandler):
-    """Redirect handler to redirect to specific appspot version."""
-    def get(self, arg):
-        if arg:
-            return self.redirect("https://{}.appspot.com/".format(arg))
-
-
-class MainPage(base.BaseHandler):
-    """Main web page request handler."""
-
-    def get(self):
-        """Generates an HTML page."""
-        self.template = "index.html"
-
-        template_values = {}
-
-        self.render(template_values)
-
-
-config = {}
-config['webapp2_extras.sessions'] = {
-    'secret_key': os.environ.get('SESSION_SECRET_KEY'),
-}
-
-app = webapp2.WSGIApplication(
-    [
-        ("/tasks/schedule", periodic.PeriodicScheduler),
-        ("/tasks/device_heartbeat", device_heartbeat.PeriodicDeviceHeartBeat),
-        ("/tasks/job_heartbeat", job_heartbeat.PeriodicJobHeartBeat),
-        ("/tasks/remove_outdated_devices",
-         removing_outdated_devices.RemoveOutdatedDevices),
-        ("/tasks/indexing([/]?.*)", indexing.CreateIndex),
-        ("/redirect/(.*)", RedirectHandler),
-    ],
-    config=config,
-    debug=False)
diff --git a/gae/webapp/src/worker_main.py b/gae/webapp/src/worker_main.py
deleted file mode 100644
index 40afdf9..0000000
--- a/gae/webapp/src/worker_main.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from webapp.src.tasks import indexing
-from webapp.src.scheduler import schedule_worker
-import webapp2
-
-
-app = webapp2.WSGIApplication([
-        ("/worker/schedule_handler", schedule_worker.ScheduleHandler),
-        ("/worker/indexing", indexing.IndexingHandler)
-    ], debug=True)
diff --git a/gae/worker.yaml b/gae/worker.yaml
deleted file mode 100644
index 7d6b859..0000000
--- a/gae/worker.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-runtime: python27
-api_version: 1
-threadsafe: true
-service: worker
-
-handlers:
-- url: /.*
-  script: webapp.src.worker_main.app
-  login: admin
-
-# [START exclude]
-skip_files:
-- ^(.*/)?#.*#$
-- ^(.*/)?.*~$
-- ^(.*/)?.*\.py[co]$
-- ^(.*/)?.*/RCS/.*$
-- ^(.*/)?\..*$
-- ^script/*$
-- .*_test.py$
-- ^(.*/)?frontend/(.*)
-- ^(.*/)?\.idea/(.*)
-# [END exclude]
diff --git a/proto/GreenBuildScheduleConfigMessage.proto b/proto/GreenBuildScheduleConfigMessage.proto
deleted file mode 100644
index 3ca5679..0000000
--- a/proto/GreenBuildScheduleConfigMessage.proto
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// To specify a green build scheduling policy.
-message GreenBuildScheduleConfigMessage {
-  // Schedule name.
-  optional bytes name = 1;
-
-  // Schedule description (e.g., daily/HH:MM)
-  optional bytes schedule = 2;
-
-  // Scheduling priority (e.g., top, high, medium, low)
-  optional bytes priority = 3;
-
-  // if GSI (General System Image) is used, GSI manifest branch name.
-  optional bytes gsi_branch = 11;
-
-  // if GSI (General System Image) is used, GSI PAB account ID.
-  optional bytes gsi_pab_account_id = 12;
-
-  // Test package's manifest branch name.
-  optional bytes test_branch = 21;
-
-  // PAB account ID for test package.
-  optional bytes test_pab_account_id = 22;
-
-  repeated GreenBuildTestScheduleConfigMessage test = 31;
-}
-
-// To specify a test plan scheduling policy.
-message GreenBuildTestScheduleConfigMessage {
-  // Test name (e.g., test_group/test_plan)
-  optional bytes test_name = 1;
-
-  // Test package's build target name.
-  optional bytes test_build_target = 11;
-
-  // Device manifest branch name.
-  optional bytes device_branch = 21;
-
-  // Device PAB account ID.
-  optional bytes device_pab_account_id = 22;
-
-  repeated GreenBuildDeviceScheduleConfigMessage device = 31;
-}
-
-// To specify a device scheduling policy.
-message GreenBuildDeviceScheduleConfigMessage {
-  // Device type (format: <lab>/<device type>)
-  optional bytes device = 1;
-
-  // Number of shards (0 for auto selection)
-  optional int32 shards = 11;
-
-  // Device manifest branch name if different.
-  optional bytes device_branch = 21;
-
-  // Device build target if different.
-  optional bytes device_build_target = 22;
-
-  // Device PAB account ID if different.
-  optional bytes device_pab_account_id = 23;
-
-  // GSI's build target name.
-  optional bytes gsi_build_target = 31;
-}
diff --git a/proto/GreenBuildScheduleConfigMessage_pb2.py b/proto/GreenBuildScheduleConfigMessage_pb2.py
deleted file mode 100644
index a001a7a..0000000
--- a/proto/GreenBuildScheduleConfigMessage_pb2.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: GreenBuildScheduleConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='GreenBuildScheduleConfigMessage.proto',
-  package='android.test.lab',
-  syntax='proto2',
-  serialized_pb=_b('\n%GreenBuildScheduleConfigMessage.proto\x12\x10\x61ndroid.test.lab\"\xfa\x01\n\x1fGreenBuildScheduleConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x10\n\x08schedule\x18\x02 \x01(\x0c\x12\x10\n\x08priority\x18\x03 \x01(\x0c\x12\x12\n\ngsi_branch\x18\x0b \x01(\x0c\x12\x1a\n\x12gsi_pab_account_id\x18\x0c \x01(\x0c\x12\x13\n\x0btest_branch\x18\x15 \x01(\x0c\x12\x1b\n\x13test_pab_account_id\x18\x16 \x01(\x0c\x12\x43\n\x04test\x18\x1f \x03(\x0b\x32\x35.android.test.lab.GreenBuildTestScheduleConfigMessage\"\xd2\x01\n#GreenBuildTestScheduleConfigMessage\x12\x11\n\ttest_name\x18\x01 \x01(\x0c\x12\x19\n\x11test_build_target\x18\x0b \x01(\x0c\x12\x15\n\rdevice_branch\x18\x15 \x01(\x0c\x12\x1d\n\x15\x64\x65vice_pab_account_id\x18\x16 \x01(\x0c\x12G\n\x06\x64\x65vice\x18\x1f \x03(\x0b\x32\x37.android.test.lab.GreenBuildDeviceScheduleConfigMessage\"\xb4\x01\n%GreenBuildDeviceScheduleConfigMessage\x12\x0e\n\x06\x64\x65vice\x18\x01 \x01(\x0c\x12\x0e\n\x06shards\x18\x0b \x01(\x05\x12\x15\n\rdevice_branch\x18\x15 \x01(\x0c\x12\x1b\n\x13\x64\x65vice_build_target\x18\x16 \x01(\x0c\x12\x1d\n\x15\x64\x65vice_pab_account_id\x18\x17 \x01(\x0c\x12\x18\n\x10gsi_build_target\x18\x1f \x01(\x0c')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_GREENBUILDSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='GreenBuildScheduleConfigMessage',
-  full_name='android.test.lab.GreenBuildScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='name', full_name='android.test.lab.GreenBuildScheduleConfigMessage.name', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='schedule', full_name='android.test.lab.GreenBuildScheduleConfigMessage.schedule', index=1,
-      number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='priority', full_name='android.test.lab.GreenBuildScheduleConfigMessage.priority', index=2,
-      number=3, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_branch', full_name='android.test.lab.GreenBuildScheduleConfigMessage.gsi_branch', index=3,
-      number=11, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_pab_account_id', full_name='android.test.lab.GreenBuildScheduleConfigMessage.gsi_pab_account_id', index=4,
-      number=12, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_branch', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test_branch', index=5,
-      number=21, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_pab_account_id', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test_pab_account_id', index=6,
-      number=22, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test', index=7,
-      number=31, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=60,
-  serialized_end=310,
-)
-
-
-_GREENBUILDTESTSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='GreenBuildTestScheduleConfigMessage',
-  full_name='android.test.lab.GreenBuildTestScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='test_name', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.test_name', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_build_target', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.test_build_target', index=1,
-      number=11, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_branch', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device_branch', index=2,
-      number=21, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_pab_account_id', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device_pab_account_id', index=3,
-      number=22, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device', index=4,
-      number=31, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=313,
-  serialized_end=523,
-)
-
-
-_GREENBUILDDEVICESCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='GreenBuildDeviceScheduleConfigMessage',
-  full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='device', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='shards', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.shards', index=1,
-      number=11, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_branch', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_branch', index=2,
-      number=21, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_build_target', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_build_target', index=3,
-      number=22, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_pab_account_id', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_pab_account_id', index=4,
-      number=23, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_build_target', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.gsi_build_target', index=5,
-      number=31, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=526,
-  serialized_end=706,
-)
-
-_GREENBUILDSCHEDULECONFIGMESSAGE.fields_by_name['test'].message_type = _GREENBUILDTESTSCHEDULECONFIGMESSAGE
-_GREENBUILDTESTSCHEDULECONFIGMESSAGE.fields_by_name['device'].message_type = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildScheduleConfigMessage'] = _GREENBUILDSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildTestScheduleConfigMessage'] = _GREENBUILDTESTSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildDeviceScheduleConfigMessage'] = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE
-
-GreenBuildScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _GREENBUILDSCHEDULECONFIGMESSAGE,
-  __module__ = 'GreenBuildScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(GreenBuildScheduleConfigMessage)
-
-GreenBuildTestScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildTestScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _GREENBUILDTESTSCHEDULECONFIGMESSAGE,
-  __module__ = 'GreenBuildScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildTestScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(GreenBuildTestScheduleConfigMessage)
-
-GreenBuildDeviceScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildDeviceScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE,
-  __module__ = 'GreenBuildScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildDeviceScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(GreenBuildDeviceScheduleConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/TestLabConfigMessage.proto b/proto/TestLabConfigMessage.proto
deleted file mode 100644
index 2324ead..0000000
--- a/proto/TestLabConfigMessage.proto
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// To specify the whole test execution schedule of a manifest branch.
-message LabConfigMessage {
-  // Lab name where format is labtype-location-instance (e.g., vtslab-mtv32-main).
-  optional bytes name = 1;
-  optional bytes owner = 2;
-  repeated bytes admin = 3;
-
-  // For the IP address.
-  repeated HostConfigMessage host = 11;
-}
-
-// To specify the basic information about a host computer.
-message HostConfigMessage {
-  optional bytes hostname = 1;
-  optional bytes ip = 2;
-
-  // host management scripts
-  optional bytes script = 3;
-  optional bytes setup_script = 4;
-
-  // list of equipment installed on this host.
-  repeated bytes host_equipment = 5;
-
-  repeated DeviceConfigMessage device = 11;
-}
-
-// To specify information about a DUT (Device Under Test).
-message DeviceConfigMessage {
-  // device serial number (retrieved by fastboot or adb).
-  optional bytes serial = 1;
-
-  // optional - device index for a host starting from 0 to 13 (max).
-  optional int32 index = 2;
-
-  // device product type (e.g., taimen or walleye).
-  optional bytes product = 11;
-
-  // list of equipment installed on this device.
-  repeated bytes device_equipment = 21;
-}
-
diff --git a/proto/TestLabConfigMessage_pb2.py b/proto/TestLabConfigMessage_pb2.py
deleted file mode 100644
index eb1799c..0000000
--- a/proto/TestLabConfigMessage_pb2.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: TestLabConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='TestLabConfigMessage.proto',
-  package='android.test.lab',
-  syntax='proto2',
-  serialized_pb=_b('\n\x1aTestLabConfigMessage.proto\x12\x10\x61ndroid.test.lab\"q\n\x10LabConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\r\n\x05owner\x18\x02 \x01(\x0c\x12\r\n\x05\x61\x64min\x18\x03 \x03(\x0c\x12\x31\n\x04host\x18\x0b \x03(\x0b\x32#.android.test.lab.HostConfigMessage\"\xa6\x01\n\x11HostConfigMessage\x12\x10\n\x08hostname\x18\x01 \x01(\x0c\x12\n\n\x02ip\x18\x02 \x01(\x0c\x12\x0e\n\x06script\x18\x03 \x01(\x0c\x12\x14\n\x0csetup_script\x18\x04 \x01(\x0c\x12\x16\n\x0ehost_equipment\x18\x05 \x03(\x0c\x12\x35\n\x06\x64\x65vice\x18\x0b \x03(\x0b\x32%.android.test.lab.DeviceConfigMessage\"_\n\x13\x44\x65viceConfigMessage\x12\x0e\n\x06serial\x18\x01 \x01(\x0c\x12\r\n\x05index\x18\x02 \x01(\x05\x12\x0f\n\x07product\x18\x0b \x01(\x0c\x12\x18\n\x10\x64\x65vice_equipment\x18\x15 \x03(\x0c')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_LABCONFIGMESSAGE = _descriptor.Descriptor(
-  name='LabConfigMessage',
-  full_name='android.test.lab.LabConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='name', full_name='android.test.lab.LabConfigMessage.name', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='owner', full_name='android.test.lab.LabConfigMessage.owner', index=1,
-      number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='admin', full_name='android.test.lab.LabConfigMessage.admin', index=2,
-      number=3, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='host', full_name='android.test.lab.LabConfigMessage.host', index=3,
-      number=11, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=48,
-  serialized_end=161,
-)
-
-
-_HOSTCONFIGMESSAGE = _descriptor.Descriptor(
-  name='HostConfigMessage',
-  full_name='android.test.lab.HostConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='hostname', full_name='android.test.lab.HostConfigMessage.hostname', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='ip', full_name='android.test.lab.HostConfigMessage.ip', index=1,
-      number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='script', full_name='android.test.lab.HostConfigMessage.script', index=2,
-      number=3, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='setup_script', full_name='android.test.lab.HostConfigMessage.setup_script', index=3,
-      number=4, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='host_equipment', full_name='android.test.lab.HostConfigMessage.host_equipment', index=4,
-      number=5, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device', full_name='android.test.lab.HostConfigMessage.device', index=5,
-      number=11, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=164,
-  serialized_end=330,
-)
-
-
-_DEVICECONFIGMESSAGE = _descriptor.Descriptor(
-  name='DeviceConfigMessage',
-  full_name='android.test.lab.DeviceConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='serial', full_name='android.test.lab.DeviceConfigMessage.serial', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='index', full_name='android.test.lab.DeviceConfigMessage.index', index=1,
-      number=2, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='product', full_name='android.test.lab.DeviceConfigMessage.product', index=2,
-      number=11, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device_equipment', full_name='android.test.lab.DeviceConfigMessage.device_equipment', index=3,
-      number=21, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=332,
-  serialized_end=427,
-)
-
-_LABCONFIGMESSAGE.fields_by_name['host'].message_type = _HOSTCONFIGMESSAGE
-_HOSTCONFIGMESSAGE.fields_by_name['device'].message_type = _DEVICECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['LabConfigMessage'] = _LABCONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['HostConfigMessage'] = _HOSTCONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['DeviceConfigMessage'] = _DEVICECONFIGMESSAGE
-
-LabConfigMessage = _reflection.GeneratedProtocolMessageType('LabConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _LABCONFIGMESSAGE,
-  __module__ = 'TestLabConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.LabConfigMessage)
-  ))
-_sym_db.RegisterMessage(LabConfigMessage)
-
-HostConfigMessage = _reflection.GeneratedProtocolMessageType('HostConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _HOSTCONFIGMESSAGE,
-  __module__ = 'TestLabConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.HostConfigMessage)
-  ))
-_sym_db.RegisterMessage(HostConfigMessage)
-
-DeviceConfigMessage = _reflection.GeneratedProtocolMessageType('DeviceConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _DEVICECONFIGMESSAGE,
-  __module__ = 'TestLabConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.DeviceConfigMessage)
-  ))
-_sym_db.RegisterMessage(DeviceConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/TestScheduleConfigMessage.proto b/proto/TestScheduleConfigMessage.proto
deleted file mode 100644
index c2f7991..0000000
--- a/proto/TestScheduleConfigMessage.proto
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// Type of a command.
-enum BuildStorageType {
-  UNKNOWN_BUILD_STORAGE_TYPE = 0;
-  // For Partner Android Build (PAB)
-  BUILD_STORAGE_TYPE_PAB = 1;
-  // For a Google Cloud Storage (GCS) bucket
-  BUILD_STORAGE_TYPE_GCS = 2;
-}
-
-// To specify the whole test execution schedule of a manifest branch.
-message ScheduleConfigMessage {
-  // Manifest branch name.
-  optional bytes manifest_branch = 1;
-
-  // PAB account ID.
-  optional bytes pab_account_id = 2;
-
-  // Device image storage type (e.g., PAB or GCS)
-  optional BuildStorageType build_storage_type = 3 [default = BUILD_STORAGE_TYPE_PAB];
-
-  // For the IP address.
-  repeated BuildScheduleConfigMessage build_target = 11;
-}
-
-message BuildScheduleConfigMessage {
-  // build target name (e.g., aosp_taimen-userdebug)
-  optional bytes name = 1;
-
-  // whether to use signed build.
-  optional bool require_signed_device_build = 2;
-
-  // whether the build target has bootloader.img
-  optional bool has_bootloader_img = 3 [default = true];
-
-  // whether the build target has radio.img
-  optional bool has_radio_img = 4 [default = true];
-
-  repeated TestScheduleConfigMessage test_schedule = 11;
-}
-
-message TestScheduleConfigMessage {
-  // Test name (e.g., test_group/test_plan)
-  optional bytes test_name = 1;
-
-  // Scheduling period in minutes
-  optional int32 period = 2;
-
-  // Priority such as high, low, or medium
-  optional bytes priority = 3;
-
-  // such as <lab>/<device type>
-  repeated bytes device = 4;
-
-  // number of shards (-1 for auto selection?)
-  optional int32 shards = 5;
-
-  // required host-side equipment.
-  repeated bytes required_host_equipment = 6;
-
-  // required device-side equipment such as a SIM card.
-  repeated bytes required_device_equipment = 7;
-
-  optional bytes param = 11;
-
-  // GSI storage type (e.g., PAB or GCS)
-  optional BuildStorageType gsi_storage_type = 24 [default = BUILD_STORAGE_TYPE_PAB];
-
-  // if GSI (General System Image) is used, GSI manifest branch name.
-  optional bytes gsi_branch = 21;
-
-  // if GSI (General System Image) is used, GSI build target name.
-  optional bytes gsi_build_target = 22;
-
-  // if GSI (General System Image) is used, GSI PAB account ID.
-  optional bytes gsi_pab_account_id = 23;
-
-  // if GSI (General System Image) is used, the version of a vendor.img
-  // to use GSI with (e.g., 8.1.0).
-  optional bytes gsi_vendor_version = 25;
-
-  // Test package's storage type (e.g., PAB or GCS)
-  optional BuildStorageType test_storage_type = 34 [default = BUILD_STORAGE_TYPE_PAB];
-
-  // Test package's manifest branch name.
-  optional bytes test_branch = 31;
-
-  // Test package's build target name.
-  optional bytes test_build_target = 32;
-
-  // PAB account ID for test package.
-  optional bytes test_pab_account_id = 33;
-
-  // number of retry count.
-  optional int32 retry_count = 41;
-
-  // whether to disable this schedule.
-  optional bool disable = 51 [default = false];
-
-  // Base GCS url for the repack command.
-  optional bytes image_package_repo_base = 61;
-
-  // the GCS url where test results are uploaded
-  repeated bytes report_bucket = 71;
-
-  // the ID of the spreadsheet where test results are uploaded
-  repeated bytes report_spreadsheet_id = 72;
-
-  // the GCS url where the latest test result is uploaded
-  repeated bytes report_persistent_url = 73;
-
-  // the GCS url where the reference result is.
-  repeated bytes report_reference_url = 74;
-}
diff --git a/proto/TestScheduleConfigMessage_pb2.py b/proto/TestScheduleConfigMessage_pb2.py
deleted file mode 100644
index 46dafac..0000000
--- a/proto/TestScheduleConfigMessage_pb2.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: vti/test_serving/proto/TestScheduleConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf.internal import enum_type_wrapper
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='vti/test_serving/proto/TestScheduleConfigMessage.proto',
-  package='android.test.lab',
-  syntax='proto2',
-  serialized_pb=_b('\n6vti/test_serving/proto/TestScheduleConfigMessage.proto\x12\x10\x61ndroid.test.lab\"\xe4\x01\n\x15ScheduleConfigMessage\x12\x17\n\x0fmanifest_branch\x18\x01 \x01(\x0c\x12\x16\n\x0epab_account_id\x18\x02 \x01(\x0c\x12V\n\x12\x62uild_storage_type\x18\x03 \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x42\n\x0c\x62uild_target\x18\x0b \x03(\x0b\x32,.android.test.lab.BuildScheduleConfigMessage\"\xd2\x01\n\x1a\x42uildScheduleConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12#\n\x1brequire_signed_device_build\x18\x02 \x01(\x08\x12 \n\x12has_bootloader_img\x18\x03 \x01(\x08:\x04true\x12\x1b\n\rhas_radio_img\x18\x04 \x01(\x08:\x04true\x12\x42\n\rtest_schedule\x18\x0b \x03(\x0b\x32+.android.test.lab.TestScheduleConfigMessage\"\xe4\x05\n\x19TestScheduleConfigMessage\x12\x11\n\ttest_name\x18\x01 \x01(\x0c\x12\x0e\n\x06period\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x01(\x0c\x12\x0e\n\x06\x64\x65vice\x18\x04 \x03(\x0c\x12\x0e\n\x06shards\x18\x05 \x01(\x05\x12\x1f\n\x17required_host_equipment\x18\x06 \x03(\x0c\x12!\n\x19required_device_equipment\x18\x07 \x03(\x0c\x12\r\n\x05param\x18\x0b \x01(\x0c\x12T\n\x10gsi_storage_type\x18\x18 \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x12\n\ngsi_branch\x18\x15 \x01(\x0c\x12\x18\n\x10gsi_build_target\x18\x16 \x01(\x0c\x12\x1a\n\x12gsi_pab_account_id\x18\x17 \x01(\x0c\x12\x1a\n\x12gsi_vendor_version\x18\x19 \x01(\x0c\x12U\n\x11test_storage_type\x18\" \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x13\n\x0btest_branch\x18\x1f \x01(\x0c\x12\x19\n\x11test_build_target\x18  \x01(\x0c\x12\x1b\n\x13test_pab_account_id\x18! \x01(\x0c\x12\x13\n\x0bretry_count\x18) \x01(\x05\x12\x16\n\x07\x64isable\x18\x33 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x17image_package_repo_base\x18= \x01(\x0c\x12\x15\n\rreport_bucket\x18G \x03(\x0c\x12\x1d\n\x15report_spreadsheet_id\x18H \x03(\x0c\x12\x1d\n\x15report_persistent_url\x18I \x03(\x0c\x12\x1c\n\x14report_reference_url\x18J \x03(\x0c*j\n\x10\x42uildStorageType\x12\x1e\n\x1aUNKNOWN_BUILD_STORAGE_TYPE\x10\x00\x12\x1a\n\x16\x42UILD_STORAGE_TYPE_PAB\x10\x01\x12\x1a\n\x16\x42UILD_STORAGE_TYPE_GCS\x10\x02')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-_BUILDSTORAGETYPE = _descriptor.EnumDescriptor(
-  name='BuildStorageType',
-  full_name='android.test.lab.BuildStorageType',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNKNOWN_BUILD_STORAGE_TYPE', index=0, number=0,
-      options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BUILD_STORAGE_TYPE_PAB', index=1, number=1,
-      options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BUILD_STORAGE_TYPE_GCS', index=2, number=2,
-      options=None,
-      type=None),
-  ],
-  containing_type=None,
-  options=None,
-  serialized_start=1263,
-  serialized_end=1369,
-)
-_sym_db.RegisterEnumDescriptor(_BUILDSTORAGETYPE)
-
-BuildStorageType = enum_type_wrapper.EnumTypeWrapper(_BUILDSTORAGETYPE)
-UNKNOWN_BUILD_STORAGE_TYPE = 0
-BUILD_STORAGE_TYPE_PAB = 1
-BUILD_STORAGE_TYPE_GCS = 2
-
-
-
-_SCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='ScheduleConfigMessage',
-  full_name='android.test.lab.ScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='manifest_branch', full_name='android.test.lab.ScheduleConfigMessage.manifest_branch', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='pab_account_id', full_name='android.test.lab.ScheduleConfigMessage.pab_account_id', index=1,
-      number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='build_storage_type', full_name='android.test.lab.ScheduleConfigMessage.build_storage_type', index=2,
-      number=3, type=14, cpp_type=8, label=1,
-      has_default_value=True, default_value=1,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='build_target', full_name='android.test.lab.ScheduleConfigMessage.build_target', index=3,
-      number=11, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=77,
-  serialized_end=305,
-)
-
-
-_BUILDSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='BuildScheduleConfigMessage',
-  full_name='android.test.lab.BuildScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='name', full_name='android.test.lab.BuildScheduleConfigMessage.name', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='require_signed_device_build', full_name='android.test.lab.BuildScheduleConfigMessage.require_signed_device_build', index=1,
-      number=2, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='has_bootloader_img', full_name='android.test.lab.BuildScheduleConfigMessage.has_bootloader_img', index=2,
-      number=3, type=8, cpp_type=7, label=1,
-      has_default_value=True, default_value=True,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='has_radio_img', full_name='android.test.lab.BuildScheduleConfigMessage.has_radio_img', index=3,
-      number=4, type=8, cpp_type=7, label=1,
-      has_default_value=True, default_value=True,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_schedule', full_name='android.test.lab.BuildScheduleConfigMessage.test_schedule', index=4,
-      number=11, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=308,
-  serialized_end=518,
-)
-
-
-_TESTSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
-  name='TestScheduleConfigMessage',
-  full_name='android.test.lab.TestScheduleConfigMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='test_name', full_name='android.test.lab.TestScheduleConfigMessage.test_name', index=0,
-      number=1, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='period', full_name='android.test.lab.TestScheduleConfigMessage.period', index=1,
-      number=2, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='priority', full_name='android.test.lab.TestScheduleConfigMessage.priority', index=2,
-      number=3, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='device', full_name='android.test.lab.TestScheduleConfigMessage.device', index=3,
-      number=4, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='shards', full_name='android.test.lab.TestScheduleConfigMessage.shards', index=4,
-      number=5, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='required_host_equipment', full_name='android.test.lab.TestScheduleConfigMessage.required_host_equipment', index=5,
-      number=6, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='required_device_equipment', full_name='android.test.lab.TestScheduleConfigMessage.required_device_equipment', index=6,
-      number=7, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='param', full_name='android.test.lab.TestScheduleConfigMessage.param', index=7,
-      number=11, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_storage_type', full_name='android.test.lab.TestScheduleConfigMessage.gsi_storage_type', index=8,
-      number=24, type=14, cpp_type=8, label=1,
-      has_default_value=True, default_value=1,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_branch', full_name='android.test.lab.TestScheduleConfigMessage.gsi_branch', index=9,
-      number=21, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_build_target', full_name='android.test.lab.TestScheduleConfigMessage.gsi_build_target', index=10,
-      number=22, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_pab_account_id', full_name='android.test.lab.TestScheduleConfigMessage.gsi_pab_account_id', index=11,
-      number=23, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='gsi_vendor_version', full_name='android.test.lab.TestScheduleConfigMessage.gsi_vendor_version', index=12,
-      number=25, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_storage_type', full_name='android.test.lab.TestScheduleConfigMessage.test_storage_type', index=13,
-      number=34, type=14, cpp_type=8, label=1,
-      has_default_value=True, default_value=1,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_branch', full_name='android.test.lab.TestScheduleConfigMessage.test_branch', index=14,
-      number=31, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_build_target', full_name='android.test.lab.TestScheduleConfigMessage.test_build_target', index=15,
-      number=32, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='test_pab_account_id', full_name='android.test.lab.TestScheduleConfigMessage.test_pab_account_id', index=16,
-      number=33, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='retry_count', full_name='android.test.lab.TestScheduleConfigMessage.retry_count', index=17,
-      number=41, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='disable', full_name='android.test.lab.TestScheduleConfigMessage.disable', index=18,
-      number=51, type=8, cpp_type=7, label=1,
-      has_default_value=True, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='image_package_repo_base', full_name='android.test.lab.TestScheduleConfigMessage.image_package_repo_base', index=19,
-      number=61, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=_b(""),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='report_bucket', full_name='android.test.lab.TestScheduleConfigMessage.report_bucket', index=20,
-      number=71, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='report_spreadsheet_id', full_name='android.test.lab.TestScheduleConfigMessage.report_spreadsheet_id', index=21,
-      number=72, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='report_persistent_url', full_name='android.test.lab.TestScheduleConfigMessage.report_persistent_url', index=22,
-      number=73, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-    _descriptor.FieldDescriptor(
-      name='report_reference_url', full_name='android.test.lab.TestScheduleConfigMessage.report_reference_url', index=23,
-      number=74, type=12, cpp_type=9, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      options=None),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  options=None,
-  is_extendable=False,
-  syntax='proto2',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=521,
-  serialized_end=1261,
-)
-
-_SCHEDULECONFIGMESSAGE.fields_by_name['build_storage_type'].enum_type = _BUILDSTORAGETYPE
-_SCHEDULECONFIGMESSAGE.fields_by_name['build_target'].message_type = _BUILDSCHEDULECONFIGMESSAGE
-_BUILDSCHEDULECONFIGMESSAGE.fields_by_name['test_schedule'].message_type = _TESTSCHEDULECONFIGMESSAGE
-_TESTSCHEDULECONFIGMESSAGE.fields_by_name['gsi_storage_type'].enum_type = _BUILDSTORAGETYPE
-_TESTSCHEDULECONFIGMESSAGE.fields_by_name['test_storage_type'].enum_type = _BUILDSTORAGETYPE
-DESCRIPTOR.message_types_by_name['ScheduleConfigMessage'] = _SCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['BuildScheduleConfigMessage'] = _BUILDSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['TestScheduleConfigMessage'] = _TESTSCHEDULECONFIGMESSAGE
-DESCRIPTOR.enum_types_by_name['BuildStorageType'] = _BUILDSTORAGETYPE
-
-ScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('ScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _SCHEDULECONFIGMESSAGE,
-  __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.ScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(ScheduleConfigMessage)
-
-BuildScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('BuildScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _BUILDSCHEDULECONFIGMESSAGE,
-  __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.BuildScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(BuildScheduleConfigMessage)
-
-TestScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('TestScheduleConfigMessage', (_message.Message,), dict(
-  DESCRIPTOR = _TESTSCHEDULECONFIGMESSAGE,
-  __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
-  # @@protoc_insertion_point(class_scope:android.test.lab.TestScheduleConfigMessage)
-  ))
-_sym_db.RegisterMessage(TestScheduleConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/__init__.py b/proto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/__init__.py
+++ /dev/null
diff --git a/script/build-python.sh b/script/build-python.sh
deleted file mode 100755
index f8d2fb0..0000000
--- a/script/build-python.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Modifies any import statements (to remove subdir path)
-pushd ${ANDROID_BUILD_TOP}/test
-
-protoc -I=. --python_out=. ./vti/test_serving/proto/TestLabConfigMessage.proto
-protoc -I=. --python_out=. ./vti/test_serving/proto/TestScheduleConfigMessage.proto
-protoc -I=. --python_out=. ./vti/test_serving/proto/GreenBuildScheduleConfigMessage.proto
-
-# Compiles all the python source codes.
-python -m compileall .
-
-popd
diff --git a/script/pack-gae.sh b/script/pack-gae.sh
deleted file mode 100755
index 9917aef..0000000
--- a/script/pack-gae.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ -d "$ANDROID_BUILD_TOP" ]; then
-  TEST_SERVING_DIR="$ANDROID_BUILD_TOP/test/vti/test_serving"
-else
-  CURRENT_DIR_NAME="${PWD##*/}"
-  if [ "${CURRENT_DIR_NAME}" = "test_serving" ]; then
-    TEST_SERVING_DIR="${PWD}"
-  elif [ "${CURRENT_DIR_NAME}" = "script" ]; then
-    TEST_SERVING_DIR="${PWD}/.."
-  else
-    echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
-    exit 1
-  fi
-fi
-
-if [ ! -d "${TEST_SERVING_DIR}/gae" ]; then
-  echo "Please run this script in 'test_serving' directory."
-  exit 1
-fi
-
-pushd $TEST_SERVING_DIR/gae
-echo "Removing unnecessary files in ${TEST_SERVING_DIR}/gae directory..."
-git clean -f
-
-echo "Updating python libraries..."
-rm -rf lib/
-./script/install-pip.sh
-popd
-
-pushd $TEST_SERVING_DIR/
-zip vtslab-scheduler-$(git log -s -n 1 --format="%cd" --date=format:"%Y%m%d_%H%M%S")-$(git rev-parse --short HEAD).zip -r gae -x *.pyc "*/\.*" *.DS_Store* gae/frontend/node_modules**\*
-popd
diff --git a/script/run-unittest.sh b/script/run-unittest.sh
deleted file mode 100755
index 6ce6949..0000000
--- a/script/run-unittest.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
-    echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
-    exit 1
-fi
-
-# Runs all unit tests under test/vti/test_serving/gae using an e2e_test framework.
-pushd $ANDROID_BUILD_TOP/test/vti/test_serving/gae
-python testing/e2e_test.py
-popd
-