diff --git a/.gitignore b/.gitignore
index ef7d6d066680ad1da8a8203a9eb10b86a94c4f13..64219757615fd84bc28a6b5a45a17415668ac599 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,25 +1,11 @@
 *.pyc
 *.bak
 *.blend[1-9]
-/temp/
-/docs/site/
 
 .cache/
 .coverage
-*.css.map
 
-/packages/flamenco-manager-go/bin/
-/packages/flamenco-manager-go/pkg/
-/packages/flamenco-manager-go/src/[a-eg-z]*
-/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager
-/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager.yaml
-/packages/flamenco-manager-go/src/flamenco-manager/test_*.json
-/packages/flamenco-manager-go/src/flamenco-manager/docker/flamenco-manager
-/packages/flamenco-manager-go/src/flamenco-manager/docker/flamenco-manager.yaml
-/packages/flamenco-manager-go/src/flamenco-manager/docker/flamenco-manager-install-*.sh
-/packages/flamenco-manager-go/src/flamenco-manager/docker/flamenco-manager-*.docker.tgz
-
-/packages/flamenco-worker-python/flamenco_worker.egg-info/
-/packages/flamenco-worker-python/flamenco-worker.db
-/packages/flamenco-worker-python/build/
-/packages/flamenco-worker-python/dist/
+/flamenco_worker.egg-info/
+/flamenco-worker.db
+/build/
+/dist/
diff --git a/README.md b/README.md
index 59676c0b5f6c0fe96d34bcd2b1d594f8d879d6a7..63fd37a90f4b9a44526b2521e9cd4e0f8c14203c 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,91 @@
-# Flamenco 2.0
+# Flamenco Worker
 
-Development repo for Flamenco 2.0 (originally known as brender). Flamenco is a Free and Open Source 
-Job distribution system for render farms.
+This is the Flamenco Worker implemented in Python 3.
 
-Warning: currently Flamenco is in beta stage, and can still change in major ways.
 
-This project contains the 3 main components of the system: Server, Manager(s) and Worker(s)
+## Configuration
 
-## Server
-Flamenco Server is a [Pillar](https://pillarframework.org) extension, therefore it is implemented
-in Python and shares all the existing Pillar requirements. Flamenco Server relies on Pillar to
-provide all the authentication, authorization, project and user management functionality.
+Configuration is read from three locations:
 
-## Manager
-The Manager is written in [Go](https://golang.org/). The Manager is documented in its own
-[README](./packages/flamenco-manager-go/README.md).
+- A hard-coded default in the Python source code.
+- `flamenco-worker.cfg` in the current working directory.
+- `$HOME/.flamenco-worker.cfg`.
 
-## Worker
-The Flamenco worker is a very simple standalone component implemented in
-[Python](https://www.python.org/). The Worker is documented
-in its own [README](./packages/flamenco-worker-python/README.md).
+When those files do not exist, they are skipped (i.e. this is not an error). They
+should be in INI format, as specified by the
+[configparser documentation](https://docs.python.org/3/library/configparser.html)
 
-## User and Developer documentation
-The documentation is built with [MkDocs](http://www.mkdocs.org/) and uses the 
-[mkdocs-material](http://squidfunk.github.io/mkdocs-material/) theme, so make sure you have it 
-installed. You can build the docs by running.
+### Configuration contents:
 
-```
-pip install mkdocs-material
-cd docs
-mkdocs serve
-```
+All configuration keys should be placed in the `[flamenco-worker]` section of the
+config files.
+
+- `manager_url`: Flamenco Manager URL.
+- `worker_id`: ID of the worker, handed out by the Manager upon registration (see
+  Registration below) and used for authentication with the Manager.
+- `worker_secret`: Secret key of the worker, given to the Manager upon registration
+  and authentication.
+- `job_types`: Space-separated list of job types this worker may execute.
+- `task_update_queue_db`: filename of the SQLite3 database holding the queue of task
+  updates to be sent to the Master.
+
+### TODO
+
+- Certain settings are currently only settable by editing constants in the Python source code.
+  It might be nice to read them from the config file too, at some point.
+- Update worker address in MongoDB when communicating with it.
+
+## Invocation
+
+Install using `pip install -e .` for development, or `setup.py install` for production.
+This creates a command `flamenco-worker`, which can be run with `--help` to obtain
+a list of possible CLI arguments.
+
+## Registration
+
+If the configuration file does not contain both a `worker_id` and `worker_secret`, at startup
+the worker will attempt to register itself at the Master.
+Once registered via a POST to the manager's `/register-worker` endpoint, the `worker_id` and
+`worker_secret` will be written to `$HOME/.flamenco-worker.cfg`
+
+## Task fetch & execution
+
+1. A task is obtained by the FlamencoWorker from the manager via a POST to its `/task` endpoint.
+   If this fails (for example due to a connection error), the worker will retry every few seconds
+   until a task fetch is succesful.
+2. The task is given to a TaskRunner object.
+3. The TaskRunner object iterates over the commands and executes them.
+4. At any time, the FlamencoWorker can be called upon to register activities and log lines,
+   and forward them to the Manager. These updates are queued in a SQLite3 database, such that
+   task execution isn't interrupted when the Manager cannot be reached.
+5. A separate coroutine of TaskUpdateQueue fetches updates from the queue, and forwards them to
+   the Master, using a POST to its `/tasks/{task-id}/update` endpoint.
+   **TODO:** the response to this endpoint may indicate a request to abort the currently running
+   task. This should be implemented.
+
+
+## Shutdown
+
+Pressing [CTRL]+[C] will cause a clean shutdown of the worker.
+If there is a task currently running, it will be aborted without changing its status. Any pending task updates are sent to the Manager, and then the Manager's `/sign-off` URL is
+POSTed to, to indicate a clean shutdown of the worker. Any active task that is still
+assigned to the worker is given status "claimed-by-manager" so that it can be re-activated
+by another worker.
+
+
+## Systemd integration
+
+To run Flamenco Worker as a systemd-managed service, copy `flamenco-worker.service` to
+`/etc/systemd/system/flamenco-worker.service`, then run `systemctl daemon-reload`.
+
+After installation of this service, `systemctl {start,stop,status,restart} flamenco-worker`
+commands can be used to manage it. To ensure that the Flamenco Worker starts at system boot,
+use `systemctl enable flamenco-worker`.
+
+
+## Signals
+
+Flamenco Worker responds to the following POSIX signals:
+
+- `SIGINT`, `SIGTERM`: performs a clean shutdown, as described in the Shutdown section above.
+- `SIGUSR1`: logs the currently scheduled asyncio tasks.
diff --git a/clients/blender/render_flamenco.py b/clients/blender/render_flamenco.py
deleted file mode 100755
index fbb4c7d7e03bbbed6493cc56f86a95d7035a370a..0000000000000000000000000000000000000000
--- a/clients/blender/render_flamenco.py
+++ /dev/null
@@ -1,629 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License
-#  as published by the Free Software Foundation; either version 2
-#  of the License, or (at your option) any later version.
-#
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software Foundation,
-#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_info = {
-    "name": "Flamenco Integration",
-    "author": "Eibriel, Francesco Siddi",
-    "version": (0, 5),
-    "blender": (2, 73, 0),
-    "location": "View3D > Tool Shelf > Flamenco",
-    "description": "BAM pack current file and send it to the Flamenco Renderfarm",
-    "wiki_url": "",
-    "tracker_url": "",
-    "category": "Render"}
-
-import bpy
-import sys
-import os
-import json
-import requests
-import subprocess
-import uuid
-# from time import strftime
-
-from bpy.props import IntProperty
-from bpy.props import BoolProperty
-from bpy.props import StringProperty
-from bpy.props import EnumProperty
-from bpy.props import CollectionProperty
-
-from requests.exceptions import ConnectionError
-from requests.exceptions import Timeout
-
-from bpy.types import AddonPreferences
-
-class ProfilesUtility():
-    """Class that leverages the blender-id authentication system"""
-    def __new__(cls, *args, **kwargs):
-        raise TypeError("Base class may not be instantiated")
-
-    @staticmethod
-    def get_profiles_file():
-        """Returns the profiles.json filepath from a .blender_id folder in the user
-        home directory. If the file does not exist we create one with the basic data
-        structure.
-        """
-        profiles_path = os.path.join(os.path.expanduser('~'), '.blender_id')
-        profiles_file = os.path.join(profiles_path, 'profiles.json')
-        if not os.path.exists(profiles_file):
-            profiles = [{
-                "username" : "",
-                "token" : "",
-                "is_active" : False}]
-            try:
-                os.makedirs(profiles_path)
-            except FileExistsError:
-                pass
-            except Exception as e:
-                raise e
-
-            import json
-            with open(profiles_file, 'w') as outfile:
-                json.dump(profiles, outfile)
-        return profiles_file
-
-    @classmethod
-    def credentials_load(cls):
-        """Loads the credentials from a profile file. TODO: add a username
-        arg so that one out of many identities can be retrieved.
-        """
-        import json
-        profiles_file = cls.get_profiles_file()
-        with open(profiles_file) as f:
-            return json.load(f)
-
-    @classmethod
-    def get_active_profile(cls):
-        """Pick the active profile from the profiles.json. If no active
-        profile is found we return None.
-        """
-        profiles = ProfilesUtility.credentials_load()
-        index = next((index for (index, d) in enumerate(profiles) if d["is_active"] == True), None)
-        if index is not None:
-            return profiles[index]
-        else:
-            return None
-
-# TODO move into proper utils module
-suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
-def humansize(nbytes):
-    if nbytes == 0: return '0 B'
-    i = 0
-    while nbytes >= 1024 and i < len(suffixes)-1:
-        nbytes /= 1024.
-        i += 1
-    f = ('%.2f' % nbytes).rstrip('0').rstrip('.')
-    return '%s %s' % (f, suffixes[i])
-
-class flamencoPreferences(AddonPreferences):
-    bl_idname = __name__
-
-    flamenco_server = StringProperty(
-        name="Flamenco Server URL",
-        default="http://127.0.0.1:9999",
-        options={'HIDDEN', 'SKIP_SAVE'})
-
-    def draw(self, context):
-        layout = self.layout
-        layout.prop(self, "flamenco_server")
-
-class flamencoUpdate (bpy.types.Operator):
-    """Update information about Flamenco Server"""
-    bl_idname = "flamenco.update"
-    bl_label = "Update Flamenco info"
-
-    def execute(self, context):
-        user_preferences = context.user_preferences
-        addon_prefs = user_preferences.addons[__name__].preferences
-        serverurl = addon_prefs.flamenco_server
-        wm = bpy.context.window_manager
-
-        try:
-            timeout = 5
-            projects = requests.get(
-                '{0}/projects'.format(serverurl), timeout=timeout)
-            settings_server = requests.get(
-                '{0}/settings'.format(serverurl), timeout=timeout)
-            settings_managers = requests.get(
-                '{0}/settings/managers'.format(serverurl), timeout=timeout)
-            managers = requests.get(
-                '{0}/managers'.format(serverurl), timeout=timeout)
-        except ConnectionError:
-            self.report( {'ERROR'}, "Can't connect to server on {0}".format(serverurl) )
-            return {'CANCELLED'}
-        except Timeout:
-            self.report( {'ERROR'}, "Timeout connecting to server on {0}".format(serverurl) )
-            return {'CANCELLED'}
-
-        wm.flamenco_projectCache = projects.text
-
-
-        settings_server = settings_server.json()
-        wm.flamenco_settingsServerIndex = 0
-        wm.flamenco_settingsServer.clear()
-        for setting in settings_server['settings']:
-            sett_item = wm.flamenco_settingsServer.add()
-            sett_item.name = str(setting['name'])
-            sett_item.value = str(setting['value'])
-
-        settings_managers = settings_managers.json()
-        wm.flamenco_settingsManagerIndex = 0
-        wm.flamenco_settingsManagers.clear()
-        for manager in settings_managers:
-            for setting in settings_managers[manager]:
-                if setting == 'manager_name':
-                    continue
-                sett_item = wm.flamenco_settingsManagers.add()
-                sett_item.manager = str(manager)
-                sett_item.name = str(setting)
-                sett_item.value = str(settings_managers[manager][setting])
-                sett_item.new = False
-                sett_item.manager_name = str(
-                    settings_managers[manager]['manager_name'])
-
-        managers = managers.json()
-        wm.flamenco_managersIndex = 0
-        wm.flamenco_managers.clear()
-        for manager in managers:
-            man_item = wm.flamenco_managers.add()
-            man_item.name = managers[manager].get('name')
-            man_item.id = managers[manager].get('id')
-
-        return {'FINISHED'}
-
-class saveManagerSetting (bpy.types.Operator):
-    """Save Manager Setting"""
-    bl_idname = "flamenco.save_manager_setting"
-    bl_label = "Save Preferences"
-
-    def execute(self, context):
-        user_preferences = context.user_preferences
-        addon_prefs = user_preferences.addons[__name__].preferences
-        serverurl = addon_prefs.flamenco_server
-        wm = context.window_manager
-        selected_setting = wm.flamenco_settingsManagers[
-            wm.flamenco_settingsManagerIndex]
-
-        if selected_setting.name=="":
-            return {'FINISHED'}
-
-        url = "{0}/settings/managers/{1}/{2}".format(
-            serverurl, selected_setting.manager, selected_setting.name)
-
-        data = {'value': selected_setting.value}
-        r = requests.post(url, data=data, timeout=20)
-
-        selected_setting.new = False
-
-        return {'FINISHED'}
-
-class addManagerSetting (bpy.types.Operator):
-    """Add a Manager Setting"""
-    bl_idname = "flamenco.add_manager_setting"
-    bl_label = "Add Manager Setting"
-    def execute(self,context):
-        wm = context.window_manager
-        settings_collection = wm.flamenco_settingsManagers
-
-        selected_setting = settings_collection[wm.flamenco_settingsManagerIndex]
-        manager = wm.flamenco_managers[wm.flamenco_managersIndex]
-
-        setting = settings_collection.add()
-        setting.manager = str(manager.id)
-        setting.manager_name = manager.name
-        setting.name = ""
-        setting.valur = ""
-        wm.flamenco_settingsManagerIndex = len(settings_collection)-1
-        return {'FINISHED'}
-
-class bamToRenderfarm (bpy.types.Operator):
-    """Save current file and send it to the Renderfarm using BAM pack"""
-    bl_idname = "flamenco.send_job"
-    bl_label = "Save and Send"
-
-    def execute(self, context):
-        C = context
-        D = bpy.data
-        scn = C.scene
-        wm = bpy.context.window_manager
-        user_preferences = context.user_preferences
-        addon_prefs = user_preferences.addons[__name__].preferences
-        serverurl = addon_prefs.flamenco_server
-
-
-        job_name = wm.flamenco_jobName
-
-        if not D.filepath:
-            self.report({'ERROR'}, "Save your blend file first")
-            return {'CANCELLED'}
-
-        if job_name == "":
-            self.report({'ERROR'}, "Name your Job")
-            return {'CANCELLED'}
-
-        # We retrieve the username via the .blender_id profiles file. If no file
-        # is available we fail silently and set the username to "default"
-        profile = ProfilesUtility.get_active_profile()
-        if profile:
-            username = profile['username']
-        else:
-            username = "default"
-
-        job_settings = {
-            'frames': "{0}-{1}".format(scn.frame_start, scn.frame_end),
-            'chunk_size': wm.flamenco_chunkSize,
-            'filepath': os.path.split(D.filepath)[1],
-            'render_settings': "",
-            'format': wm.flamenco_file_format,
-            'command_name': wm.flamenco_command,
-            }
-
-        job_properties = {
-            'project_id': int(wm.flamenco_project),
-            'settings': json.dumps(job_settings),
-            'name': job_name,
-            'type': wm.flamenco_jobType,
-            'managers': wm.flamenco_managers[wm.flamenco_managersIndex].id,
-            'priority': wm.flamenco_priority,
-            'username': username,
-            #'start_job': wm.flamenco_startJob,
-            # We always submit the job as not started, until we fix the server
-            # behavior. See comments belo about startJob.
-            'start_job': False
-        }
-
-        use_extension = C.scene.render.use_file_extension
-        C.scene.render.use_file_extension = True
-        bpy.ops.wm.save_mainfile()
-        C.scene.render.use_file_extension = use_extension
-
-        tmppath = C.user_preferences.filepaths.temporary_directory
-
-        # Generate a UUID and attach it to the zipfile
-        zipname = "jobfile_{0}".format(str(uuid.uuid1()))
-        zippath = os.path.join(tmppath, "{0}.zip".format(zipname))
-
-        try:
-            print("Creating BAM archive at {0}".format(zippath))
-            command = ["bam", "pack", D.filepath, '-o', zippath]
-
-            # If we do not want to pack large files
-            exclude_pattern = []
-            if wm.flamenco_pack_alembic_caches is False:
-                exclude_pattern.append('*.abc')
-            if wm.flamenco_pack_exr_sequences is False:
-                exclude_pattern.append('*.exr')
-                exclude_pattern.append('*.jpg')
-                exclude_pattern.append('*.png')
-            if wm.flamenco_pack_movie_files is False:
-                exclude_pattern.append('*.mov')
-                exclude_pattern.append('*.avi')
-            if wm.flamenco_pack_audio_files is False:
-                exclude_pattern.append('*.wav')
-                exclude_pattern.append('*.mp3')
-
-            if exclude_pattern:
-                pattern = ";".join(exclude_pattern)
-                command.extend(["--exclude", pattern])
-            subprocess.call(command)
-
-            # We give feedback abouth the end of the packing
-            statinfo = os.stat(zippath)
-            print ("Created a {0} BAM archive".format(
-                humansize(statinfo.st_size)))
-
-        except:
-            self.report({'ERROR'}, "Error running BAM. Is it installed?")
-            return {'CANCELLED'}
-
-        render_file = None
-        if wm.flamenco_submit_archive:
-            render_file = [('jobfile',
-                            ('jobfile.zip', open(zippath, 'rb'),
-                            'application/zip'))]
-
-        server_job_url = "{0}/jobs".format(serverurl)
-
-        try:
-            r = requests.post(server_job_url, data=job_properties)
-            r = r.json()
-        except ConnectionError:
-            print ("Connection Error: {0}".format(server_job_url))
-
-        # If we are submitting the archived file (can be serveral GB large)
-        if wm.flamenco_submit_archive:
-            server_job_file_url = "{0}/jobs/file/{1}".format(
-                serverurl,  r['id'])
-            # Stream the data to the server
-            with open(zippath, 'rb') as f:
-                print ("Sending {0} file to server...".format(
-                    humansize(statinfo.st_size)))
-                p = requests.post(server_job_file_url, data=f)
-            print ("Done")
-            # Cleanup the temp file
-            try:
-                print("Removing BAM archive")
-                os.remove(zippath)
-            except OSError:
-                print("Failed to removed BAM archive")
-
-        return {'FINISHED'}
-
-class MovPanelControl(bpy.types.Panel):
-    bl_space_type = 'VIEW_3D'
-    bl_region_type = 'TOOLS'
-    bl_label = "Send Job"
-    bl_category = "Flamenco"
-
-    def draw(self, context):
-        D = bpy.data
-        wm = bpy.context.window_manager
-        scene = context.scene
-
-        layout = self.layout
-        col = layout.column()
-        col.operator("flamenco.update", icon="FILE_REFRESH")
-
-        col.separator()
-
-        if len(project_list(self, context)) == 0:
-            return
-        if len(wm.flamenco_managers) == 0:
-            return
-
-        # Try to build a nice name for the job (this is done only once, then
-        # the user has to update it himself). The name looks like this:
-        # JOB_NAME | RENDER_RESOLUTION | SAMPLES
-
-        if wm.flamenco_jobName == "" and D.filepath != "":
-            file_name = os.path.split(D.filepath)[1]
-            job_name = os.path.splitext(file_name)[0]
-            render_size = scene.render.resolution_percentage
-            if scene.render.engine == 'CYCLES':
-                samples_count = "{0}S".format(scene.cycles.samples)
-            else:
-                samples_count = ""
-            wm.flamenco_jobName = u"{0} | {1}% | {2}".format(
-                job_name, render_size, samples_count)
-
-        col.prop(wm, 'flamenco_project')
-        col.prop(wm, 'flamenco_jobName')
-        col.prop(wm, 'flamenco_jobType')
-        col.prop(wm, 'flamenco_file_format')
-        if wm.flamenco_jobType in ['blender_bake_anim_cache']:
-            col.label(text="Objects to Bake:")
-            for obj in context.selected_objects:
-                if obj.cache_library:
-                    col.label(text="- {0}".format(obj.name))
-        col.prop(wm, 'flamenco_command')
-
-        col.separator()
-
-        col.template_list(
-            "UI_UL_list",
-            "ui_lib_list_prop",
-            wm,
-            "flamenco_managers",
-            wm,
-            "flamenco_managersIndex",
-            rows=5)
-
-        col.separator()
-
-        # Set the job priority (betweeen 0 and 100)
-        col.prop(wm, 'flamenco_priority')
-
-        if not wm.flamenco_jobType in ['blender_bake_anim_cache']:
-            col.prop(wm, 'flamenco_chunkSize')
-        # Show info to help the user to determine a good chunk size
-        row = col.row(align=True)
-
-        count_frames = scene.frame_end - scene.frame_start + 1
-        row.label("Frames Count: {0}".format(count_frames))
-        count_chunks = int(count_frames / wm.flamenco_chunkSize)
-        if count_chunks < 1: count_chunks = 1
-        row.label("Chunks Count: {0}".format(count_chunks))
-
-        # Automatically start the job. Currenlty commented, since we create a job
-        # and could set it to started even before the actual file is uploaded
-        # col.prop(wm, 'flamenco_startJob')
-
-        col.separator()
-
-        col.prop(wm, 'flamenco_submit_archive')
-        col.prop(wm, 'flamenco_pack_alembic_caches')
-        col.prop(wm, 'flamenco_pack_exr_sequences')
-        col.prop(wm, 'flamenco_pack_movie_files')
-        col.prop(wm, 'flamenco_pack_audio_files')
-
-        col.separator()
-
-        col.operator("flamenco.send_job", icon="APPEND_BLEND")
-
-jobType_list = [
-    ('blender_simple_render', 'Simple', '', 1),
-    ('tiled_blender_render', 'Tiled', '', 2),
-    ('blender_bake_anim_cache', 'Bake Anim Cache', '', 3),
-    ('blender_opengl_render', 'OpenGL Render', '', 4),
-    ]
-
-command_names = [
-    ('default', 'Default', '', 1),
-    ('multiview', 'Multiview', '', 2),
-    ('latest', 'Latest', '', 3),
-    ]
-
-class flamencoManagers(bpy.types.PropertyGroup):
-    name = StringProperty(
-        name="Name",
-        default="",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    id = IntProperty(
-        name="ID",
-        default=0,
-        options={'HIDDEN', 'SKIP_SAVE'})
-
-class flamencoSettingsServer(bpy.types.PropertyGroup):
-    name = StringProperty(
-        name="Name",
-        default="",
-        options={'SKIP_SAVE'})
-    value = StringProperty(
-        name="Value",
-        default="",
-        options={'SKIP_SAVE'})
-
-class flamencoSettingsManagers(bpy.types.PropertyGroup):
-    manager = StringProperty(
-        name="Manager",
-        default="",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    manager_name = StringProperty(
-        name="Manager Name",
-        default="",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    name = StringProperty(
-        name="Name",
-        default="",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    value = StringProperty(
-        name="Value",
-        default="",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    new = BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'})
-
-def project_list(self, context):
-    wm = context.window_manager
-
-    try:
-        project_cache = json.loads(wm.flamenco_projectCache)
-    except:
-        return []
-
-    project_list = []
-    if project_cache:
-        for project in project_cache:
-            project_list.append((project, project_cache[project].get('name'), ''))
-
-    return project_list
-
-def register():
-    bpy.utils.register_module(__name__)
-    wm = bpy.types.WindowManager
-
-    # Project
-    wm.flamenco_project = EnumProperty(
-        items=project_list, name="Projects", description="Flamenco Projects")
-    wm.flamenco_projectCache = StringProperty(
-        name="Project list cache", default="", options={'HIDDEN', 'SKIP_SAVE'})
-    # Job Name
-    wm.flamenco_jobName = StringProperty(
-        name="Job Name", default="", options={'HIDDEN', 'SKIP_SAVE'})
-    # Job Type
-    wm.flamenco_jobType = EnumProperty(
-        items=jobType_list, name="Job type", description="Type of job available")
-    # File Format
-    wm.flamenco_file_format = EnumProperty(
-        items=[('EXR', 'EXR', ''), ('JPEG', 'JPEG', ''), ('PNG', 'PNG', ''),
-            ('JPEG2000', 'JPEG2000', '') ],
-        name="File Format",
-        description="Output file format for the job")
-    # Chunk Size
-    wm.flamenco_chunkSize = IntProperty(
-        name="Chunk Size",
-        description="Number of chunks in which the render will be divided",
-        default=5,
-        soft_min=1,
-        options={'HIDDEN', 'SKIP_SAVE'})
-    # Managers
-    wm.flamenco_managers = CollectionProperty(
-        type=flamencoManagers, name="Managers", description="Flamenco Managers")
-    wm.flamenco_managersIndex = IntProperty(
-        name="Manager Index", description="Currently selected Flamenco Manager")
-    # Command (Blender Version)
-    wm.flamenco_command = EnumProperty(
-        items=command_names, name="Command", description="Flamenco Command")
-    # Priority
-    wm.flamenco_priority = IntProperty(
-        name="Priority",
-        description="A value between 0 and 100. The closer to 100, the higher the priority",
-        default=50,
-        soft_min=0,
-        soft_max=100,
-        options={'HIDDEN', 'SKIP_SAVE'})
-    # Start Job
-    wm.flamenco_startJob = BoolProperty(
-        name="Start Job",
-        description="As soon the file is sent to the server, the job will be started",
-        options={'HIDDEN', 'SKIP_SAVE'})
-    # Send Packed file
-    wm.flamenco_submit_archive = BoolProperty(
-        name="Send Packed File",
-        description="If unchecked, the file will be BAM packed, but not sent to the server. \
-This will have to be done by hand",
-        options={'HIDDEN', 'SKIP_SAVE'},
-        default=True)
-    # Pack Alembic Caches
-    wm.flamenco_pack_alembic_caches = BoolProperty(
-        name="Pack Alembic Caches",
-        description="If checked, .abc caches will be added to the bam archive. \
-This can generate very large files",
-        options={'HIDDEN', 'SKIP_SAVE'},
-        default=False)
-    # Pack EXR files
-    wm.flamenco_pack_exr_sequences = BoolProperty(
-        name="Pack EXR sequences",
-        description="If checked, .exr image sequences will be included in the bam archive. \
-This can generate very large files",
-        options={'HIDDEN', 'SKIP_SAVE'},
-        default=False)
-    # Pack movie files
-    wm.flamenco_pack_movie_files = BoolProperty(
-        name="Pack movie files",
-        description="If checked, .mov and .avi files will be included in the bam archive. \
-This can generate very large files",
-        options={'HIDDEN', 'SKIP_SAVE'},
-        default=False)
-    # Pack movie files
-    wm.flamenco_pack_audio_files = BoolProperty(
-        name="Pack audio files",
-        description="If checked, .wav and .mp3 files will be included in the bam archive. \
-    This can generate very large files",
-        options={'HIDDEN', 'SKIP_SAVE'},
-        default=False)
-
-    wm.flamenco_settingsServer = CollectionProperty(
-        type=flamencoSettingsServer,
-        name="Server Settings",
-        description="Server Settings")
-    wm.flamenco_settingsServerIndex = IntProperty(
-        name="Server Setting Index",
-        description="Currently selected Flamenco Server Setting")
-    wm.flamenco_settingsManagers = CollectionProperty(
-        type=flamencoSettingsManagers,
-        name="Managers Settings",
-        description="Managers Settings")
-    wm.flamenco_settingsManagerIndex = IntProperty(
-        name="Manager Setting Index",
-        description="Currently selected Flamenco Manager Setting")
-
-def unregister():
-    bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
-    register()
diff --git a/clients/cli/blender_render.py b/clients/cli/blender_render.py
deleted file mode 100755
index 2471c8af934171fd0d8ef333250d330e8e6c19e3..0000000000000000000000000000000000000000
--- a/clients/cli/blender_render.py
+++ /dev/null
@@ -1,352 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-"""CLI command for scheduling Blender renders on Flamenco Server.
-
-Assumes that the workers already have access to the required files.
-
-The user_config_dir and user_data_dir functions come from
- https://github.com/ActiveState/appdirs/blob/master/appdirs.py and
- are licensed under the MIT license.
-"""
-
-import argparse
-import json
-import os.path
-import pprint
-import sys
-
-import requests
-
-PY2 = sys.version_info[0] == 2
-
-if PY2:
-    str = unicode
-    input = raw_input
-    from urlparse import urljoin
-else:
-    from urllib.parse import urljoin
-
-if sys.platform.startswith('java'):
-    import platform
-
-    os_name = platform.java_ver()[3][0]
-    if os_name.startswith('Windows'):  # "Windows XP", "Windows 7", etc.
-        system = 'win32'
-    elif os_name.startswith('Mac'):  # "Mac OS X", etc.
-        system = 'darwin'
-    else:  # "Linux", "SunOS", "FreeBSD", etc.
-        # Setting this to "linux2" is not ideal, but only Windows or Mac
-        # are actually checked for and the rest of the module expects
-        # *sys.platform* style strings.
-        system = 'linux2'
-else:
-    system = sys.platform
-
-if system == 'win32':
-    # Win32 is not supported because it requires too much fluff, and we don't use it in the studio.
-    raise RuntimeError("Sorry, Windows is not supported for now.")
-
-
-def find_user_id(server_url, auth_token):
-    """Returns the current user ID."""
-
-    print(15 * '=', 'User info', 15 * '=')
-
-    url = urljoin(server_url, '/api/users/me')
-
-    resp = requests.get(url, auth=(auth_token, ''))
-    resp.raise_for_status()
-
-    user_info = resp.json()
-    print('You are logged in as %(full_name)s (%(_id)s)' % user_info)
-    print()
-
-    return user_info['_id']
-
-
-def find_manager_id(server_url, auth_token):
-    """Returns the manager ID.
-
-    If the user has more than one Manager available, offers a choice.
-    """
-
-    print(15 * '=', 'Manager selection', 15 * '=')
-    url = urljoin(server_url, '/api/flamenco/managers')
-    resp = requests.get(url, auth=(auth_token, ''))
-    resp.raise_for_status()
-
-    managers = resp.json()['_items']
-    if not managers:
-        raise SystemExit('No Flamenco Managers available to your account.')
-
-    if len(managers) == 1:
-        print('One Flamenco Manager is available to you:')
-        manager = managers[0]
-    else:
-        print('Please choose which Flamenco Manager should handle this job:')
-        for idx, manager in enumerate(managers):
-            print('    [%i] %s (%s)' % (idx + 1, manager['name'], manager['_id']))
-        choice = input('Give index, or ENTER for the first one: ')
-        if choice:
-            manager = managers[int(choice) - 1]
-        else:
-            manager = managers[0]
-
-    print('Using manager "%s" (%s)' % (manager['name'], manager['_id']))
-    print()
-    return manager['_id']
-
-
-def find_project_id(server_url, auth_token):
-    """Returns the project ID.
-
-    If the user has more than one Flamenco-enabled project, offers a choice.
-    """
-    import json
-
-    print(15 * '=', 'Project selection', 15 * '=')
-    url = urljoin(server_url, '/api/projects')
-    resp = requests.get(url,
-                        params={
-                            'where': json.dumps({'extension_props.flamenco': {'$exists': 1}}),
-                            'projection': json.dumps({'_id': 1, 'name': 1, 'permissions': 1})
-                        },
-                        auth=(auth_token, ''))
-    resp.raise_for_status()
-
-    projects = resp.json()['_items']
-    if not projects:
-        raise SystemExit('No Flamenco Projects available to your account.')
-
-    if len(projects) == 1:
-        print('One Flamenco Project is available to you:')
-        project = projects[0]
-    else:
-        print('Please choose which Flamenco Project this job belongs to:')
-        for idx, project in enumerate(projects):
-            print('    [%i] %s (%s)' % (idx + 1, project['name'], project['_id']))
-        choice = input('Give index, or ENTER for the first one: ')
-        if choice:
-            project = projects[int(choice) - 1]
-        else:
-            project = projects[0]
-
-    print('Using project "%s" (%s)' % (project['name'], project['_id']))
-    print()
-    return project['_id']
-
-
-def create_render_job(server_url, auth_token, settings, args):
-    user_id = find_user_id(server_url, auth_token)
-    project_id = find_project_id(server_url, auth_token)
-    manager_id = find_manager_id(server_url, auth_token)
-
-    filename = os.path.basename(settings['filepath'])
-
-    job = {
-        u'status': u'queued',
-        u'priority': 50,
-        u'name': args.name or u'render %s' % filename,
-        u'settings': settings,
-        u'job_type': args.jobtype,
-        u'user': user_id,
-        u'manager': manager_id,
-        u'project': project_id,
-    }
-    if args.description:
-        job[u'description'] = args.description
-
-    print()
-    print('The job:')
-    json.dump(job, sys.stdout, indent=4, sort_keys=True)
-
-    url = urljoin(server_url, '/api/flamenco/jobs')
-    print()
-    print('Press [ENTER] to POST to %s' % url)
-    input()
-
-    resp = requests.post(url, json=job, auth=(auth_token, ''))
-    if resp.status_code == 204:
-        print('Job created.')
-        print(resp.headers)
-    else:
-        print('Response:')
-        if resp.headers['content-type'] == 'application/json':
-            pprint.pprint(resp.json())
-        else:
-            print(resp.text)
-
-
-def find_credentials():
-    """Finds BlenderID credentials.
-
-    :rtype: str
-    :returns: the authentication token to use.
-    """
-    import glob
-
-    # Find BlenderID profile file.
-    configpath = user_config_dir('blender', 'Blender Foundation', roaming=True)
-    found = glob.glob(os.path.join(configpath, '*'))
-    for confpath in reversed(sorted(found)):
-        profiles_path = os.path.join(confpath, 'config', 'blender_id', 'profiles.json')
-        if not os.path.exists(profiles_path):
-            continue
-
-        print('Reading credentials from %s' % profiles_path)
-        with open(profiles_path) as infile:
-            profiles = json.load(infile, encoding='utf8')
-        if profiles:
-            break
-    else:
-        print('Unable to find Blender ID credentials. Log in with the Blender ID add-on in '
-              'Blender first.')
-        raise SystemExit()
-
-    active_profile = profiles[u'active_profile']
-    profile = profiles[u'profiles'][active_profile]
-    print('Logging in as %s' % profile[u'username'])
-
-    return profile[u'token']
-
-
-def main():
-    parser = argparse.ArgumentParser()
-    parser.add_argument('blendfile', help='The blendfile to render. It is assumed that a worker '
-                                          'can find this file, since we do not yet have upload/'
-                                          'download/copy commands.')
-    parser.add_argument('frames',
-                        help='Frame range to render, in "printer range" notation (1-4,15-30). '
-                             'Should not contain any spaces.')
-    parser.add_argument('-r', '--render-output',
-                        help='Where to render to, defaults to whatever is defined in the blendfile.')
-    parser.add_argument('-o', '--format',
-                        help='The file format to output to, defaults to whatever is defined '
-                             'in the blendfile.')
-    parser.add_argument('-c', '--chunk-size',
-                        help='The maximum number of frames to render on a single worker.')
-    parser.add_argument('-u', '--server-url', default='https://cloud.blender.org/',
-                        help='URL of the Flamenco server.')
-    parser.add_argument('-t', '--token',
-                        help='Authentication token to use. If not given, your token from the '
-                             'Blender ID add-on is used.')
-    parser.add_argument('-b', '--blender-cmd', default='{blender}',
-                        help='Blender command, defaults to "{blender}".')
-    parser.add_argument('-n', '--name', help='Optional job name, defaults to "render {filename}".')
-    parser.add_argument('-d', '--description', help='Optional job description.')
-    parser.add_argument('-p', '--progressive',
-                        help='Progressive render information, '
-                             'in the format "sample_count:num_chunks"')
-    parser.add_argument('--jobtype', default='blender-render',
-                        help='Sets the job type; set automatically when using --progressive')
-
-    args = parser.parse_args()
-
-    settings = {
-        'filepath': args.blendfile,
-        'frames': args.frames,
-        'blender_cmd': args.blender_cmd,
-    }
-
-    if args.render_output:
-        settings['render_output'] = args.render_output
-    if args.format:
-        settings['format'] = args.format
-    if args.chunk_size:
-        settings['chunk_size'] = int(args.chunk_size)
-    if args.progressive:
-        scount, nchunks = args.progressive.split(':')
-        settings['cycles_sample_count'] = int(scount)
-        settings['cycles_num_chunks'] = int(nchunks)
-        args.jobtype = 'blender-render-progressive'
-    if not args.token:
-        args.token = find_credentials()
-
-    create_render_job(args.server_url, args.token, settings, args)
-
-
-def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
-    r"""Return full path to the user-specific config dir for this application.
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname. You may
-            pass False to disable it.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "roaming" (boolean, default False) can be set True to use the Windows
-            roaming appdata directory. That means that for users on a Windows
-            network setup for roaming profiles, this user data will be
-            sync'd on login. See
-            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
-            for a discussion of issues.
-    Typical user config directories are:
-        Mac OS X:               same as user_data_dir
-        Unix:                   ~/.config/<AppName>     # or in $XDG_CONFIG_HOME, if defined
-        Win *:                  same as user_data_dir
-    For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
-    That means, by default "~/.config/<AppName>".
-    """
-    if system in {"win32", "darwin"}:
-        path = user_data_dir(appname, appauthor, None, roaming)
-    else:
-        path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
-        if appname:
-            path = os.path.join(path, appname)
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
-    r"""Return full path to the user-specific data dir for this application.
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname. You may
-            pass False to disable it.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "roaming" (boolean, default False) can be set True to use the Windows
-            roaming appdata directory. That means that for users on a Windows
-            network setup for roaming profiles, this user data will be
-            sync'd on login. See
-            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
-            for a discussion of issues.
-    Typical user data directories are:
-        Mac OS X:               ~/Library/Application Support/<AppName>
-        Unix:                   ~/.local/share/<AppName>    # or in $XDG_DATA_HOME, if defined
-        Win XP (not roaming):   C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
-        Win XP (roaming):       C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>
-        Win 7  (not roaming):   C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>
-        Win 7  (roaming):       C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName>
-    For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
-    That means, by default "~/.local/share/<AppName>".
-    """
-    if system == "win32":
-        raise RuntimeError("Sorry, Windows is not supported for now.")
-    elif system == 'darwin':
-        path = os.path.expanduser('~/Library/Application Support/')
-        if appname:
-            path = os.path.join(path, appname)
-    else:
-        path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
-        if appname:
-            path = os.path.join(path, appname)
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-if __name__ == '__main__':
-    main()
diff --git a/deploy_docs.sh b/deploy_docs.sh
deleted file mode 100755
index 3d71095919e948bf52fd0c1d8532dc2635e33f42..0000000000000000000000000000000000000000
--- a/deploy_docs.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-cd docs
-command -v mkdocs 2>/dev/null 2>&1 || { echo >&2 "Command mkdocs not found. Are you in the right venv?"; exit 1; }
-mkdocs build
-rsync -auv ./site/* armadillica@flamenco.io:/home/armadillica/flamenco.io/docs
diff --git a/docs/docs/developer_docs/architecture.md b/docs/docs/developer_docs/architecture.md
deleted file mode 100644
index 0cba65084dec79ff420b847f076014513ed8b6ed..0000000000000000000000000000000000000000
--- a/docs/docs/developer_docs/architecture.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# System architecture
-
-The architecture of Flamenco is simple, hierarchical.
-
-In a production setup we have one Server and one or more Managers which control one or 
-more Workers each.
-
-![Architecture diagram](img/architecture_diagram.svg)
-
-With this configuration it is possible to have a very generic and simple API on the Server, and 
-develop/maintain different type of front-ends for it.
-
-Communication between components happens via HTTP. In particular, Server and Manager use a simple 
-and well-defined REST API. This allows third parties to easily implement their Manager, and 
-integrate it into Flamenco. Flamenco ships with its own Free and Open Source Manager and Worker
-implementations.
-
-The whole system is designed with bottom-up communication in mind. For example:
-
-- Worker has a loop that sends requests to the Manager
-- Worker sends request a task to the Manager
-- Manager checks Tasks availability with Server
-- Server replies to Manager with available Tasks
-- Manager replies to Worker with a Task to execute
-- Worker executes the Commands of a Task and reports progress to the Manager
-
-By using update buffers on Managers and Worker components we can keep the overall 
-infrastructure as resilient, responsive and available a possible.
-
-## Server
-
-In a Flamenco network, there can be only one server. The functionality of the server consists in:
-
-- storing a list of Managers
-- storing Jobs
-- generating and storing Tasks (starting from a Job)
-- dispatch Tasks to a Manager
-- serving entry points to inspect the status of:
-    + Jobs
-    + Tasks
-    + Workers
-
-The Server software is based on [Pillar](https://pillarframework.org/), the Free and Open Source
-CMS that provides agnostic user authentication, resource and project management. It requires:
-
-- Linux, macOS or Windows
-- Python 2.7 (soon to become Python 3)
-- MongoDB
-
-## Manager
-
-The goal of the Manager, as the name suggests, is to handle the workload provided by the Server
-and leverage the computing resources available (Workers) to complete the Tasks as soon as possible.
-
-Because the communication between Server and Manager happens via a semi-RESTful API, a Manager
-can be implemented in many ways. At Blender we implemented a Manager in Go, which is available
-as Free and Open Source software. It requires:
-
-- Linux, macOS or Windows
-- Golang
-- MongoDB
-
-## Worker
-
-The lowest-level component of the Flamenco infrastructure, a Worker is directly responsible for
-the execution of a Task, which is composed by an ordered series of Commands. Similarly to the
-Manager, Blender provides a Free and Open Source implementation, with the following requirements:
-
-- Linux, macOS or Windows
-- Python 3.5 or greater
-
-## Jobs, Tasks and Commands
-
-Flamenco is designed to handle several types of jobs, mostly serving computer animated film 
-production, for example:
-
-- 3D animation rendering
-- simulation baking
-- distributed still image rendering
-- video encoding
-
-A Job is the highest level structure, containing all the necessary information on how to process 
-the Job itself.
-In order to distribute the execution of a Job, we split it into Tasks, according to the instructions 
-provided. This process is called *Job compilation*.
-
-A task is essentially a list of Commands. Each worker can claim one (or more tasks) to execute,
-which means it will sequentially run all the Commands contained in it. 
-
-- keeping a log of operations related to Jobs (task logging happens on the manager)
-- collecting and storing all the data needed to complete a Job
-
-## Components and processes documentation
-
-In the rest of the documentation we cover more in depth the different components of the
-architecture, as well as the various processes (Job creation, Manager and Worker management, etc.).
diff --git a/docs/docs/developer_docs/img/architecture_diagram.svg b/docs/docs/developer_docs/img/architecture_diagram.svg
deleted file mode 100644
index 0e04360d75b9a19b33043648c72e6014e52d0b5e..0000000000000000000000000000000000000000
--- a/docs/docs/developer_docs/img/architecture_diagram.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="851px" height="371px" version="1.1" content="&lt;mxfile userAgent=&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36&quot; version=&quot;6.0.3.3&quot; editor=&quot;www.draw.io&quot; type=&quot;google&quot;&gt;&lt;diagram name=&quot;Page-1&quot;&gt;7VnLcpswFP0aZtpFPAgBdpaNm6aLZKYznjbNUgEFqGWuRwg/+vUVRrwscEmaYvrwxuhwka7OOb4Xg4Hnq90NJ+vwDnzKDMv0dwZ+b1gWstBUfmXIPkdmjpkDAY98FVQBi+g7VWARlkY+TRqBAoCJaN0EPYhj6okGRjiHbTPsCVhz1TUJqAYsPMJ09D7yRXi0iwz/SKMgLFZGpjrzSLxlwCGN1XqGhZ8On/z0ihRzqfgkJD5saxC+NvCcA4j8aLWbU5ZxW9CWX/eh4+zUoo9T7BD86PvoyUIXWXC2zoawVO3tcywiwagv0Vuyp1wlIvbF5hl4S5pNiAx8VWyY01i8LANby0BbcRtGgi7WxMvGW2kpuXAoVkzlkAgOSzoHBlwiMcS0TGxDuaC7I9GqXDv4UKnfUFhRwffyIjXFpZJF2RbZarxtMUFYMwCeKpAo4wXl1BVX8kDR1U5dS/7P5Br/nGrqS6OrIXARQgAxYdcVenVwb6l/TYZvVIi9+q2SVICEqhluAdYqju4i8VUemxNHjR4aZspS6NyxghJIuUc7tllUBMID2il0u86cMiKiTXP9NtEOl77jnOxrAWuIYpHUZv6UAZV9bMtp+MdyjwQ8iseueSpeHuQZVPYpt9LLURor9gv8UHNAt7K9vRHL5GtTZMNsDlMz3oBecV7DK7oZnHYzlFPkOamrKtV/t+kcc2DTIfc1q1C3B095q68/B3Qd+lXb9e0rXdnV2sSC8k3LnUBThGd1aXnjYx4+fVs1OtmYsds0OZrpnRlZLZ3ZfoXGrBE4HcbQA5vW6mFa91yevfznakgfOWbnkkP/W3FHYvmvSNYQ800UX4SQJvTtmAvKURcsx2cpKAhpVP0NFcXp0wbNdp0GaIMvuRv+s2tKL0HwuQSx/wvSKsjZqrxzqsrPGaT+mEu8bY+pxLsal1eM+HTE/JXcKP5sdE7+Zhp/98CXiZA/AYhHzKLljonFYvEajV/uRsyeg0bFnv6AddTsuc6o2NPbyWQyGTF9zmxMDQTpFXDc9E0vh3OfHFYvzfKHltWbSXz9Aw==&lt;/diagram&gt;&lt;/mxfile&gt;" style="background-color: rgb(255, 255, 255);"><defs/><g transform="translate(0.5,0.5)"><rect x="0" y="0" width="850" height="370" fill="#ffffff" stroke="none" pointer-events="none"/><path d="M 335 80 L 335 110 Q 335 120 325 120 L 280 120 Q 270 120 270 130 L 270 153.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 270 158.88 L 266.5 151.88 L 270 153.63 L 273.5 151.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 335 80 L 335 110 Q 335 120 345 120 L 400 120 Q 410 120 410 130 L 410 153.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 410 158.88 L 406.5 151.88 L 410 153.63 L 413.5 151.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 335 80 L 335 110 Q 335 120 345 120 L 540 120 Q 550 120 550 130 L 550 153.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 550 158.88 L 546.5 151.88 L 550 153.63 L 553.5 151.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="275" y="40" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(316.5,53.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="36" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 36px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Server</div></div></foreignObject><text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">Server</text></switch></g><path d="M 270 200 L 270 225 Q 270 235 260 235 L 100 235 Q 90 235 90 245 L 90 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 90 268.88 L 86.5 261.88 L 90 263.63 L 93.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 270 200 L 270 225 Q 270 235 260 235 L 240 235 Q 230 235 230 245 L 230 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 230 268.88 L 226.5 261.88 L 230 263.63 L 233.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="210" y="160" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(217.5,173.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="104" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 106px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Manager (in-house)</div></div></foreignObject><text x="52" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">Manager (in-house)</text></switch></g><path d="M 410 200 L 410 225 Q 410 235 420 235 L 470 235 Q 480 235 480 245 L 480 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 480 268.88 L 476.5 261.88 L 480 263.63 L 483.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 410 200 L 410 225 Q 410 235 420 235 L 610 235 Q 620 235 620 245 L 620 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 620 268.88 L 616.5 261.88 L 620 263.63 L 623.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 410 200 L 410 225 Q 410 235 420 235 L 750 235 Q 760 235 760 245 L 760 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 760 268.88 L 756.5 261.88 L 760 263.63 L 763.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="350" y="160" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(364.5,173.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="90" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 92px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Manager (Cloud)</div></div></foreignObject><text x="45" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">Manager (Cloud)</text></switch></g><rect x="30" y="270" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(74.5,283.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="30" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 32px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Blade</div></div></foreignObject><text x="15" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">Blade</text></switch></g><rect x="170" y="270" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(197.5,283.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="64" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 64px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Workstation</div></div></foreignObject><text x="32" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">Workstation</text></switch></g><rect x="420" y="270" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(470.5,283.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="18" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 19px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">VM</div></div></foreignObject><text x="9" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">VM</text></switch></g><rect x="560" y="270" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(610.5,283.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="18" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 19px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">VM</div></div></foreignObject><text x="9" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">VM</text></switch></g><rect x="490" y="160" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(544.5,173.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="10" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 12px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">...</div></div></foreignObject><text x="5" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">...</text></switch></g><rect x="700" y="270" width="120" height="40" rx="6" ry="6" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(754.5,283.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="10" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 12px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">...</div></div></foreignObject><text x="5" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">...</text></switch></g></g></svg>
\ No newline at end of file
diff --git a/docs/docs/developer_docs/img/scheduling_diagram.svg b/docs/docs/developer_docs/img/scheduling_diagram.svg
deleted file mode 100644
index f93d6c84b483221f795f120990d70e5972757626..0000000000000000000000000000000000000000
--- a/docs/docs/developer_docs/img/scheduling_diagram.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1487px" height="1599px" version="1.1" content="&lt;mxfile userAgent=&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36&quot; version=&quot;6.0.3.3&quot; editor=&quot;www.draw.io&quot; type=&quot;google&quot;&gt;&lt;diagram name=&quot;Page-1&quot;&gt;7Vxdc9o4FP01TJ9gLH/zWJLQ3Zl221k60+1TR9gCtDEWteUm7K9fyZZtLMngEAxpQh6IJduyrHN077lXgoF1s378kMDN6hMJUTQwjfBxYN0OTNO0fJf94zXbosZ3jKJimeCwqAJ1xQz/h0RleVmGQ5Q2LqSERBRvmpUBiWMU0EYdTBLy0LxsQaLmUzdwiZSKWQAjtfYbDulK1AJ3XJ/4A+HlSjzaN8ULr2F5sXiTdAVD8rBTZd0NrJuEEFocrR9vUMQHrxyX4r5py9mqYwmKaacbxgsUAGQYoePYhm8MzaKFXzDKxMuKjtJt+fYPK0zRbAMDXn5gCA+syYquI1YC7DClCblHNyQiCauJScwum4hWUULRY2tXQTUAjDmIrBFNtuwSccMQ2GLQtk02PNQQjMeibrUz+sBwHYG9wH1ZNV4PDTsQo9MyUgA6cxc5C+iz4YJgCJSRmqGEveHAdCP25MmcHy1p9fI7I8hQ3/DDbB19xAsU4XyMNijBrFuID1skqr/UdZMD487ITiG7JanKUQQ3KZ7nTzVYTYKCLEnxL/Q3Sos5xWtJRvmTbqq5kl9KsjhEoShVLOWFZQTTVBwHZI2D8qIc93I+8B4sWI/E5AXGaUgAmhSwHIUCwNNSwDB6oICtUGCK45A/Jb+PjRNexohX/Evmad5P1k1OBUgzXsaxhi3e5N3PDGUofDcwWZ+MdzCgDLSyFMA4QNEwQeyilPKrvFsd5+SaRtcoG52E/4fpfVvHjC59CyLICBoO59vhGsbM7iW6XsvtHP0SxcN53+7MAXMj49zMK33oMAd3Zs6G4JjmvHAmA+dWmookoSuyJDGMdifjBSeI1hC1m023OWXGqtU0Lf2U6WHGlO5kZ8osEA1WgopX3CrcJNgcT8XN1cBm9oKaAtqncp5dPduJPJtVipQ9rk2nbirJc1px46rztPAfxTQ1SkM8Fca3PrMg3LE8kOT+jdlhc78dbsLraNSraZxtQnsKvIVYqWGk5IriQf3pmiqKwDwXiqXb3kExWKHgvik92zDMZ3CNd7YJIWVB9RXrElzP0oBra8D1egHXaQVXIFaKdRkwWOj8wwx4e8iWLZhNSayxxQBogHZ7CSLVWTxDNLfAwyJM2onTcqssB09XZHeSRE0D7WtklNbNWr3MYQXZb12n4lVIHyukPeNwjqisawa8oA8OqGb8w93XPLkyhRvMPhcRXKM4ILzlIqpK+dO8iSgNWdM8OTIN0SZd8oT60+Y7H0wcwOh9xPWddTsnlJI1O4Hi8D1PhvO6iDDPIqHYRMvkaOEoKhO7A9Na5H+tKKJQyaJLGLIukywJUMvQtUz1BEWQp5YaDekwE7d+4Qav5odtjUdNLQ7K9HzZSNErcZ+5kz2XmgK+sb8hCpMlokpDbNjhducyYZJbu1zJR+k5NSeLFmuGVsN1HGnV6C/CKe8QWdTO6NQkJBvETk1CmK5yswKK04JY/iXoWeB3YXqyuL8Tqw7SU2moheenYJAaYC5wklNIyBbejdH9COam0P2Z8RWvSRAhyGPQlA0hqquf5i+nCTOoh51hL/6rdDJjXqi8i3Ui1zYEkiHwVd/m6dRNxYSTujZfwTjN5imHN24AfQVPC57pXRS9sYJe2+JVL4tEuvUeuoKcOCv4iycmghWMl3kHUswCnkG+asU+l8y45okq1ibry3pzXTg6BT0dSTYDTeSkWyjqhZxADYp7kM2C0H8uhp9IiBeYUWEmqLZCMHwqHV6w0m5Phfgy7G47nF0Vi9LIsYJaaagnQV0+pzdBDdTdIm9RUXen4dg6AQ3lRo4VzkpDPQrnMje5w5QEbVDuGBEDfavShA2tscZxlkvmQxRij8ebFBXYl6rrhuGZkOhCuusE3ss2JegNnbY6l/NS9wWllCSo0lZHTPfXJDVsWQibKlj+uXK0QE3QXcHaA5atmVnnA0tNK3z5PBO6sFgW+y3l2YFEqKVH6JmZJnnHiWNJ22S7qjZb3qskN9Tid0/iLtUkRIJoltQ7GV69qDqQpjwPeVwAOmF+kDzuuBsLT0EeU12ga48yhR/gISY/LOPL9pjyLxKj4SfIdzda7zmSFC5fcUD53Ly3zAPjSGsEjAMN9WiNTFX5SdaI58MwD/nWIuNwCQOFHjH9pzzDjr9z2ozYxHtpjs80Oxg4sxc+ApmPtnk+Gqnrb3hRUch4gOnTCMRxmIlirT7v6trdEA8KakVowRtLWSyI4+XHvJRzQGN89ojXi/u/IrXTv73qqJ6emqqyfUf7HG2qSr3bk+52nBGwTd/xxOf5OK0Kta8FnYuVhnW+aPS7LRVxZ3OOtSJbs9I3djRhVz9xl6kuFiVZHDO7cJTMfk3xcbVLtNw1aneLj/tJPVlqnrkZIGsU7LTY+tufNGUjmWwrvcEL3y/lKfarjXEHd2IZejo80504UgLTk7+z2mMYZKlhUE0aEQfxRuNltcbGDiv65FwqODSc5+HOSw9ySv1rjAxg72hgMDIYB4ryju25PWUqp4U+Gmvx7Ai9ZSvsUwOqsT1yd/4cU2rWHp0vwLLUAKtlUcThSKDgza6IeFbToIw1+2DPtiJiqQFNlWhZw+0QD5mcOJxb+W0cUm1ggG01gmxm6J9tYPb7J6cX/+TZ9si36j+JXLYjG4E+/ZW6ClBlWbb8K0zTmOTcmuTvDVMSl1kXfuKab2n3Tn2RR/7lDqPbyvxJ2KIJPD/ffu4f9RPbEiCJFWPke+DZtqSDWDmUfhv3whlX4oxvHilfHFkHyQ31yT01bmYubgXjMELhj0Iz/8BhWiwQiGg4zxEX3/H6wb2hckEfrvEFrmrtpWYXV2j3E6pVP6FRO7/jmGlLWy5953zMLLPZajoOPaIgo5jofprmmo1rautD2TjriK+UsWL9+18F1PWvqFl3/wM=&lt;/diagram&gt;&lt;/mxfile&gt;" style="background-color: rgb(255, 255, 255);"><defs/><g transform="translate(0.5,0.5)"><rect x="0" y="0" width="1485" height="1597.5" fill="#ffffff" stroke="none" pointer-events="none"/><rect x="225" y="37.5" width="255" height="60" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><path d="M 352.5 97.5 L 352.5 1537.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" stroke-dasharray="4.5 4.5" pointer-events="none"/><g transform="translate(329.5,61.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="30" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 30px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Server<br /></div></div></foreignObject><text x="15" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Server&lt;br&gt;</text></switch></g><rect x="135" y="172.5" width="345" height="150" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(172.5,176.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="179" height="94" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Find all assigned jobs with status in<br />{'queued', 'active', 'cancel-requested'}<br /><br />Find all their tasks with status in <br />{'queued', 'claimed-by-manager', 'active',<br />'cancel-requested'}<br /><br />queued → claimed-by-manager<br /></div></div></foreignObject><text x="90" y="52" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="315" y="892.5" width="90" height="30" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(327.5,899.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="43" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">fetch task<br /></div></div></foreignObject><text x="22" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">fetch task&lt;br&gt;</text></switch></g><rect x="757.5" y="37.5" width="285" height="60" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><path d="M 900 97.5 L 900 1522.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" stroke-dasharray="4.5 4.5" pointer-events="none"/><g transform="translate(869.5,61.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="40" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 40px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Manager</div></div></foreignObject><text x="20" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Manager</text></switch></g><rect x="750" y="802.5" width="300" height="30" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(765.5,809.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="179" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">find task queued/claimed task for worker<br /></div></div></foreignObject><text x="90" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">find task queued/claimed task for worker&lt;br&gt;</text></switch></g><rect x="772.5" y="967.5" width="180" height="30" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(791.5,974.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="94" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">assign task to worker<br /></div></div></foreignObject><text x="47" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">assign task to worker&lt;br&gt;</text></switch></g><rect x="757.5" y="1132.5" width="210" height="105" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(785.5,1168.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="102" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">check assigned worker<br />queue task updates<br /></div></div></foreignObject><text x="51" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">check assigned worker&lt;br&gt;queue task updates&lt;br&gt;</text></switch></g><rect x="775.5" y="1402.5" width="165" height="90" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(788.5,1430.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="92" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">check task status<br />and assigned worker<br /></div></div></foreignObject><text x="46" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">check task status&lt;br&gt;and assigned worker&lt;br&gt;</text></switch></g><rect x="742.5" y="1290" width="300" height="45" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(760.5,1304.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="175" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Set to-cancel tasks to cancel-requested<br /></div></div></foreignObject><text x="88" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Set to-cancel tasks to cancel-requested&lt;br&gt;</text></switch></g><rect x="1260" y="37.5" width="202.5" height="60" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><path d="M 1361.25 97.5 L 1361.25 1552.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" stroke-dasharray="4.5 4.5" pointer-events="none"/><g transform="translate(1336.5,61.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="33" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 33px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Worker<br /></div></div></foreignObject><text x="17" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Worker&lt;br&gt;</text></switch></g><path d="M 899.25 174 L 555 174 Q 540 174 525 174 L 495.35 174" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 483.35 174 L 495.35 168 L 495.35 180 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(508.5,154.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="240" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">GET /api/flamenco/managers/{manager-id}/depsgraph<br /></div></div></foreignObject><text x="120" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">GET /api/flamenco/managers/{manager-id}/depsgraph&lt;br&gt;</text></switch></g><path d="M 480 313.5 L 892.54 313.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 880.9 321 L 895.9 313.5 L 880.9 306" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(652.5,293.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="49" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">list of tasks<br /></div></div></foreignObject><text x="25" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">list of tasks&lt;br&gt;</text></switch></g><path d="M 30 112.5 L 165 112.5 L 165 135 L 150 157.5 L 30 157.5 Z" fill="#ffffff" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><path d="M 165 112.5 L 1080 112.5 L 1080 382.5 L 30 382.5 L 30 157.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(32.5,119.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="88" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 88px; white-space: normal; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">first request a.k.a "clean slate"<br /></div></div></foreignObject><text x="44" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">first request a.k.a "clean slate"&lt;br&gt;</text></switch></g><path d="M 30 397.5 L 165 397.5 L 165 420 L 150 442.5 L 30 442.5 Z" fill="#ffffff" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><path d="M 165 397.5 L 1080 397.5 L 1080 667.5 L 30 667.5 L 30 442.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(32.5,413.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="88" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 88px; white-space: normal; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">subsequent request<br /></div></div></foreignObject><text x="44" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">subsequent request&lt;br&gt;</text></switch></g><rect x="135" y="457.5" width="345" height="120" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(156.5,473.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="201" height="58" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Find all assigned tasks with status in <br />{'queued', 'claimed-by-manager'}<br />that have changed since the given timestamp<br /><br />queued → claimed-by-manager<br /></div></div></foreignObject><text x="101" y="34" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 869.25 459 L 555 459 Q 540 459 525 459 L 495.35 459" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 483.35 459 L 495.35 453 L 495.35 465 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(494.5,421.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="240" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">GET /api/flamenco/managers/{manager-id}/depsgraph<br />with If-Modified-Since header<br /></div></div></foreignObject><text x="120" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">GET /api/flamenco/managers/{manager-id}/depsgraph&lt;br&gt;with If-Modified-Since header&lt;br&gt;</text></switch></g><path d="M 480 574.5 L 862.54 574.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 850.9 582 L 865.9 574.5 L 850.9 567" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(637.5,554.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="49" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">list of tasks<br /></div></div></foreignObject><text x="25" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">list of tasks&lt;br&gt;</text></switch></g><path d="M 886.88 459 L 913.13 442.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><ellipse cx="900" cy="510" rx="52.5" ry="52.5" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><path d="M 886.88 459 L 913.13 472.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(857.5,492.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="56" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 56px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">repeat every<br />1 minute<br /></div></div></foreignObject><text x="28" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="840" y="322.5" width="120" height="45" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(853.5,337.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="61" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">store all tasks<br /></div></div></foreignObject><text x="31" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">store all tasks&lt;br&gt;</text></switch></g><rect x="840" y="592.5" width="120" height="45" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(853.5,607.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="61" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">store all tasks<br /></div></div></foreignObject><text x="31" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">store all tasks&lt;br&gt;</text></switch></g><path d="M 1360.5 787.5 L 915.35 787.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 903.35 787.5 L 915.35 781.5 L 915.35 793.5 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1090.5,767.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="51" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">POST /task</div></div></foreignObject><text x="26" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">POST /task</text></switch></g><path d="M 900 1027.5 L 1353.79 1027.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 1342.15 1035 L 1357.15 1027.5 L 1342.15 1020" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1095.5,1007.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="47" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">return task<br /></div></div></foreignObject><text x="24" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">return task&lt;br&gt;</text></switch></g><path d="M 900 892.5 L 375.35 892.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 363.35 892.5 L 375.35 886.5 L 375.35 898.5 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(518.5,854.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="148" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">GET /api/flamenco/tasks/{task-id}<br />with If-None-Match: etag<br /></div></div></foreignObject><text x="74" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">GET /api/flamenco/tasks/{task-id}&lt;br&gt;with If-None-Match: etag&lt;br&gt;</text></switch></g><path d="M 405 921 L 892.54 921" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 880.9 928.5 L 895.9 921 L 880.9 913.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(578.5,901.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="98" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">return task, if modified<br /></div></div></foreignObject><text x="49" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">return task, if modified&lt;br&gt;</text></switch></g><path d="M 900 937.5 L 937.5 937.5 L 937.5 847.85" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 937.5 835.85 L 943.5 847.85 L 931.5 847.85 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(943.5,895.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="87" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">if task was modified<br /></div></div></foreignObject><text x="44" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">if task was modified&lt;br&gt;</text></switch></g><path d="M 30 712.5 L 180 712.5 L 180 735 L 165 757.5 L 30 757.5 Z" fill="#ffffff" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><path d="M 180 712.5 L 1455 712.5 L 1455 1057.5 L 30 1057.5 L 30 757.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(50.5,728.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="74" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 76px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Task assignment<br /></div></div></foreignObject><text x="37" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Task assignment&lt;br&gt;</text></switch></g><rect x="1305" y="1102.5" width="120" height="420" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><g transform="translate(1324.5,1304.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="54" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">running task<br /></div></div></foreignObject><text x="27" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">running task&lt;br&gt;</text></switch></g><path d="M 1305 1132.5 L 982.85 1132.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 970.85 1132.5 L 982.85 1126.5 L 982.85 1138.5 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1039.5,1112.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="128" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">POST /tasks/{task-id}/update<br /></div></div></foreignObject><text x="64" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">POST /tasks/{task-id}/update&lt;br&gt;</text></switch></g><path d="M 760.5 1240.5 L 367.35 1236.89" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 355.35 1236.78 L 367.41 1230.89 L 367.3 1242.89 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(400.5,1218.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="208" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">POST /api/f/mngrs/{mngr-id}/task-update-batch<br /></div></div></foreignObject><text x="104" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">POST /api/f/mngrs/{mngr-id}/task-update-batch&lt;br&gt;</text></switch></g><path d="M 1351.88 1404 L 1378.13 1387.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><ellipse cx="1365" cy="1455" rx="52.5" ry="52.5" fill="#ffffff" stroke="#000000" stroke-width="1.5" pointer-events="none"/><path d="M 1351.88 1404 L 1378.13 1417.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1346.5,1437.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="24" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 26px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">every<br />5 sec<br /></div></div></foreignObject><text x="12" y="16" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 1327.25 1403.25 L 955.85 1402.53" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><path d="M 943.85 1402.51 L 955.87 1396.53 L 955.84 1408.53 Z" fill="#000000" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1053.5,1382.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="107" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">GET /may-i-run/{task-id}<br /></div></div></foreignObject><text x="54" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">GET /may-i-run/{task-id}&lt;br&gt;</text></switch></g><path d="M 940.5 1488 L 1313.29 1489.47" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 1301.62 1496.93 L 1316.65 1489.49 L 1301.68 1481.93" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1038.5,1468.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="122" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">return yes/no + reason if no<br /></div></div></foreignObject><text x="61" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">return yes/no + reason if no&lt;br&gt;</text></switch></g><path d="M 970.5 1224 L 1298.29 1224" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 1286.65 1231.5 L 1301.65 1224 L 1286.65 1216.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1116.5,1204.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="29" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">TODO</div></div></foreignObject><text x="15" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">TODO</text></switch></g><path d="M 351.75 1290 L 735.79 1290" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="none"/><path d="M 724.15 1297.5 L 739.15 1290 L 724.15 1282.5" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(399.5,1270.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="196" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">{handled_update_ids: [], cancel_task_ids: []}<br /></div></div></foreignObject><text x="98" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">{handled_update_ids: [], cancel_task_ids: []}&lt;br&gt;</text></switch></g><path d="M 30 1087.5 L 180 1087.5 L 180 1110 L 165 1132.5 L 30 1132.5 Z" fill="#ffffff" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><path d="M 180 1087.5 L 1455 1087.5 L 1455 1552.5 L 30 1552.5 L 30 1132.5" fill="none" stroke="#000000" stroke-width="1.5" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(56.5,1103.5)scale(1.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="66" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 68px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Task execution<br /></div></div></foreignObject><text x="33" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Helvetica">Task execution&lt;br&gt;</text></switch></g></g></svg>
\ No newline at end of file
diff --git a/docs/docs/developer_docs/roadmap.md b/docs/docs/developer_docs/roadmap.md
deleted file mode 100644
index c2ceddb0a9c1ac76a6a7975506ba901c7d32660f..0000000000000000000000000000000000000000
--- a/docs/docs/developer_docs/roadmap.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Roadmap
-The day-to-day planning for development is available on 
-[developer.blender.org](https://developer.blender.org/project/board/58/). In this section we summarize
-the high level goals for the projects.
-
-## Self-provisionable Server
-Make it possible for developers to run the full stack (Server, Manager and Worker) in a local 
-environment. While this is easy to do for Manager and Worker, the challenge is to get the
-Server (and its Pillar core) disconnected from Blender Cloud.
-
-## Pre-built packages
-Provide pre-built and easily installable components for regular user. Packaging will vary depending
-on the component:
-
-- Server: Python package (pip installable)
-- Manager: Standalone platform-dependent binary
-- Worker: Python package (possibly standalone)
-
-## Complete Server API docs
-To make it easy to implement own manager.
-
-## More features
-Resumable jobs, job callbacks, resource allocation, filtering.
\ No newline at end of file
diff --git a/docs/docs/developer_docs/scheduling.md b/docs/docs/developer_docs/scheduling.md
deleted file mode 100644
index 62ec721c7eeb43c66d7acbb298965342e4e24764..0000000000000000000000000000000000000000
--- a/docs/docs/developer_docs/scheduling.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# Scheduling
-
-The scheduling system is supposed to hand out Tasks from the Server to each Worker, through a
-Manager. By design, the communication between Server and Workers is *always* mediated by the
-Manager, to allow completely customizeable resource management on the computing infrastructure 
-available.
-
-At the core of the scheduling system lays the *Dependency Graph*. The Dependency Graph is a DAG
-(Directed Acyclic Graph) where each node represents a Task. Tasks are initially stored in the
-Server database, in a dedicated collection and are passed on to the Manager upon request.
-
-The DG is generated with a database query to the Tasks collection and, depending on the query, 
-can return hundred-thousands of Tasks, which are then stored by the Manager in its own 
-database, so that they can be served to the Workers.
-
-[![Architecture diagram](img/scheduling_diagram.svg)](img/scheduling_diagram.svg)
-
-## Priority rules
-
-The priority for the execution of a Task is determined by three factors:
-
-- position in the DG
-- job priority
-- task priority
-
-Therefore, the Task with no parent Task (or all its parent Tasks completed), with the highest 
-Job priority, with the highest Task priority will be dispatched first.
-
-## Task requirements and resource allocation
-
-**Note: This feature is not available yet.**
-
-When a Worker queries the Manager for a Task, we use the *services* offered by it as a query
-parameter to find the highest priority Task that can be executed. For example, a Worker 
-might offer `blender_render`, but not `ffmpeg`. This also extends to hardware settings,
-so that we can specify a minimum amount of RAM or CPU cores required by a Task.
-
diff --git a/docs/docs/img/logo_flamenco_white.svg b/docs/docs/img/logo_flamenco_white.svg
deleted file mode 100644
index c557151cdfed591eac231774ea5c97b44809164e..0000000000000000000000000000000000000000
--- a/docs/docs/img/logo_flamenco_white.svg
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="512"
-   height="512"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="logo_flamenco.svg"
-   inkscape:export-filename="/shared/software/attract3/logo/attract_logo_bw_1080.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90">
-  <defs
-     id="defs4" />
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.49497475"
-     inkscape:cx="153.60622"
-     inkscape:cy="196.16365"
-     inkscape:document-units="px"
-     inkscape:current-layer="text2984"
-     showgrid="false"
-     fit-margin-top="10"
-     fit-margin-left="10"
-     fit-margin-right="10"
-     fit-margin-bottom="10"
-     inkscape:showpageshadow="false"
-     inkscape:window-width="1281"
-     inkscape:window-height="708"
-     inkscape:window-x="327"
-     inkscape:window-y="612"
-     inkscape:window-maximized="0" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-81.656231,-11.7557)">
-    <g
-       id="g2995"
-       transform="matrix(0.66925035,0,0,0.66925035,371.3471,-72.927844)"
-       style="fill:black;fill-opacity:1;stroke:none;fill-rule:nonzero">
-      <g
-         style="font-size:708.35473633px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:black;font-family:Open Sans;-inkscape-font-specification:Open Sans"
-         id="text2984">
-        <path
-           d="m -48.041991,633.10581 c -5.667221,-0.47221 -11.570172,-2.36115 -17.708869,-5.66684 -6.139439,-3.77785 -11.334035,-7.79186 -15.583804,-12.04203 -5.194952,-6.61126 -8.97284,-14.40315 -11.333676,-23.37571 -2.361524,-8.97241 -2.597642,-17.70878 -0.708354,-26.20912 2.360836,-9.91686 7.319314,-18.65323 14.875449,-26.20913 8.027654,-8.02788 17.000138,-12.98636 26.91748,-14.87545 3.777503,-0.94433 8.972099,-1.18045 15.583804,-0.70835 7.08314,1.4e-4 12.513854,0.70849 16.292159,2.12506 8.499831,3.30579 15.5833716,8.26427 21.2506423,14.87545 6.1386298,6.13919 10.3887537,13.69497 12.7503857,22.66735 1.416256,4.25023 1.888492,9.91706 1.416709,17.00052 -4.53e-4,7.08362 -0.708807,12.51434 -2.125064,16.29216 -2.361631,6.61137 -6.1395189,12.75044 -11.3336759,18.41722 -4.7227994,5.19464 -10.3896316,9.44477 -17.0005141,12.75038 -10.86185,5.19464 -21.959397,6.84746 -33.292672,4.95849 M -386.63556,599.81313 c -0.47228,-0.9444 -0.23616,-11.09748 0.70836,-30.45925 -0.94452,23.6119 0.23607,-10.86133 3.54177,-103.41979 -5e-5,-6.13887 0.23607,-17.47253 0.70836,-34.00103 l 1.41671,-41.08457 c 0.94441,-29.7506 2.36112,-51.70957 4.25013,-65.87699 1.88888,-14.63898 4.7223,-25.26429 8.50025,-31.87597 1.41664,-2.83304 5.66677,-9.44434 12.75039,-19.83393 7.55569,-10.3888 14.167,-19.12517 19.83393,-26.20912 7.55567,-10.38878 15.11145,-19.59738 22.66735,-27.62584 8.02789,-8.02757 19.83379,-18.41676 35.41774,-31.16761 12.75021,-10.86095 21.48658,-17.70837 26.20912,-20.54229 4.72218,-3.30515 9.91677,-5.43021 15.58381,-6.37519 14.16688,-2.83291 40.37598,3.07004 78.62737,17.70887 38.72308,14.6398 92.321865,38.95996 160.7965293,72.96054 73.1961417,37.30706 131.9895307,69.41911 176.3803307,96.33624 13.69423,8.50057 23.13895,15.11187 28.33419,19.83394 5.66618,4.72265 9.91631,9.91725 12.75038,15.5838 0.94382,2.36146 1.41605,4.25041 1.41671,5.66684 0.47158,0.94475 0.47158,2.36145 0,4.25013 l -2.12506,5.66683 c -1.41737,2.36145 -9.6815,11.57005 -24.79242,27.62584 -15.11218,15.58403 -27.62644,27.86216 -37.5428,36.83444 -12.27873,11.33387 -20.77898,18.65353 -25.50077,21.959 -4.25069,3.30583 -8.73694,4.95866 -13.45874,4.95848 -6.61186,1.8e-4 -13.93152,-1.65265 -21.958996,-4.95848 -7.556311,-3.30547 -20.778919,-10.62513 -39.667865,-21.959 -39.66832,-24.08383 -89.253102,-51.00128 -148.754494,-80.75244 -41.557115,-21.25033 -80.516585,-39.90366 -116.878535,-55.96002 -35.41793,-16.05569 -53.3629,-22.90311 -53.83496,-20.54229 l -3.54177,148.7545 c -0.47241,12.27834 -1.41688,20.77859 -2.83342,25.50077 -0.4724,2.36136 -2.36135,6.61149 -5.66684,12.75038 -9.91712,20.77856 -25.97314,42.2653 -48.16812,64.46028 -13.22272,12.75048 -25.73698,23.3758 -37.5428,31.87597 -11.80598,8.50032 -20.07011,12.75045 -24.79242,12.75038 -1.41676,7e-5 -2.36123,-0.94441 -2.83342,-2.83342"
-           style="fill:white;fill-opacity:1"
-           id="path2986" />
-      </g>
-    </g>
-  </g>
-</svg>
diff --git a/docs/docs/index.md b/docs/docs/index.md
deleted file mode 100644
index 881218d9e051ac2c182bb5137b2387234876b1f1..0000000000000000000000000000000000000000
--- a/docs/docs/index.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Flamenco Docs
-
-Welcome to the Flamenco Documentation pages! Here we collect both development and user docs.
-Flamenco is primarily a distributed render management solution, but it is designed to
-support any kind of job that can be split across multiple machines.
-
-Currently Flamenco is used for Render Management at Blender Institute, so it's heavily
-tested for Blender jobs, but it is quite trivial to add more.
-
-## Main features
-
-* Every component runs on Linux, macOS and Windows
-* Automatic detection of clients
-* Powerful user and project management tools
-* Dependency-graph-based priority system
-* Resilient design (every individual component can fail without consequences)
-* Extensible Jobs, Tasks and Commands
-
-## Status of the documentation
-
-We are currently updating the documentation after a large rewrite of Flamenco, therefore
-the user manual is not available, and the developer docs are work in progress. We have
-removed any legacy content though, so everything that can be found here is up to date,
-or has been highlighted as upcoming functionality.
diff --git a/docs/docs/user_manual/basics.md b/docs/docs/user_manual/basics.md
deleted file mode 100644
index 6ebb81d0ccb1897762cef0e4c49166315b01cff4..0000000000000000000000000000000000000000
--- a/docs/docs/user_manual/basics.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Installation
-
-Flamenco is still under development, therefore this installation guide is rather technical.
-In the future it will be a straightforward process, in two variants.
-
-## Using the cloud.blender.org Server
-
-**Note: This feature is not available yet.**
-
-In this case, only two components of the stack are controlled by the user: Manager and 
-Workers. The setup:
-
-- On Blender Cloud: create and initialize a Project to be used with Flamenco
-- On Blender Cloud: Create a Manager (and collect the identification token)
-- Download the Manager binary, add the identification token to the configuration, start 
-the Manager (it will automatically connect with Blender Cloud)
-- Download the Worker bundle and start it (it will automatically connect with the Manager)
-
-## Using a self-provisioned Server
-
-**Note: This feature is not available yet.**
-
-- Download and start the server (using Docker)
-- Follow the steps for setting up with Blender Cloud, updating the configuration to point
-to the self-provisioned Server, rather than cloud.blender.org
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
deleted file mode 100644
index 5ff3e24b89bc7792fd95936fb7608591dc4cdf64..0000000000000000000000000000000000000000
--- a/docs/mkdocs.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-# Project information
-site_name: 'Flamenco'
-site_description: 'Free and Open Source render management'
-site_author: 'The Flamenco Team'
-site_url: 'https://flamenco.io/'
-
-# Repository
-repo_name: 'armadillica/flamenco'
-repo_url: 'https://github.com/armadillica/flamenco'
-
-# Copyright
-copyright: 'Copyright &copy; 2016 Blender Institute - CC-BY-SA v4.0.'
-
-theme: 'material'
-
-# Options
-extra:
-  logo: 'img/logo_flamenco_white.svg'
-  palette:
-    primary: 'red'
-    accent: 'red'
-  social:
-    - type: 'github'
-      link: 'https://github.com/armadillica'
-    - type: 'twitter'
-      link: 'https://twitter.com/flamenco_io'
-
-# Google Analytics
-google_analytics:
-  - 'UA-1418081-11'
-  - 'auto'
diff --git a/packages/flamenco-worker-python/flamenco-worker.cfg b/flamenco-worker.cfg
similarity index 100%
rename from packages/flamenco-worker-python/flamenco-worker.cfg
rename to flamenco-worker.cfg
diff --git a/packages/flamenco-worker-python/flamenco_worker/__init__.py b/flamenco_worker/__init__.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/__init__.py
rename to flamenco_worker/__init__.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/attrs_extra.py b/flamenco_worker/attrs_extra.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/attrs_extra.py
rename to flamenco_worker/attrs_extra.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/cli.py b/flamenco_worker/cli.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/cli.py
rename to flamenco_worker/cli.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/config.py b/flamenco_worker/config.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/config.py
rename to flamenco_worker/config.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/documents.py b/flamenco_worker/documents.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/documents.py
rename to flamenco_worker/documents.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/may_i_run.py b/flamenco_worker/may_i_run.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/may_i_run.py
rename to flamenco_worker/may_i_run.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/merge-exr.blend b/flamenco_worker/merge-exr.blend
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/merge-exr.blend
rename to flamenco_worker/merge-exr.blend
diff --git a/packages/flamenco-worker-python/flamenco_worker/patch_asyncio.py b/flamenco_worker/patch_asyncio.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/patch_asyncio.py
rename to flamenco_worker/patch_asyncio.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/runner.py b/flamenco_worker/runner.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/runner.py
rename to flamenco_worker/runner.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/tz.py b/flamenco_worker/tz.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/tz.py
rename to flamenco_worker/tz.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/upstream.py b/flamenco_worker/upstream.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/upstream.py
rename to flamenco_worker/upstream.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/upstream_update_queue.py b/flamenco_worker/upstream_update_queue.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/upstream_update_queue.py
rename to flamenco_worker/upstream_update_queue.py
diff --git a/packages/flamenco-worker-python/flamenco_worker/worker.py b/flamenco_worker/worker.py
similarity index 100%
rename from packages/flamenco-worker-python/flamenco_worker/worker.py
rename to flamenco_worker/worker.py
diff --git a/packages/flamenco-manager-go/README.md b/packages/flamenco-manager-go/README.md
deleted file mode 100644
index 571d0b8fdf30ff5a337da1215438299b2a705a86..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/README.md
+++ /dev/null
@@ -1,110 +0,0 @@
-# Flamenco Manager
-
-This is the Flamenco Manager implementation in Go.
-
-## Running as service via systemd
-
-1. Build and configure Flamenco Manager (see below).
-2. Edit `flamenco-manager.service` to update it for the installation location, then place the file
-   in `/etc/systemd/system`.
-3. Run `systemctl daemon-reload` to pick up on the new/edited file.
-4. Run `systemctl start flamenco-manager` to start Flamenco Manager.
-5. Run `systemctl enable flamenco-manager` to ensure it starts at boot too.
-
-## CLI arguments
-
-Flamenco Manager accepts the following CLI arguments:
-
-- `-debug`: Enable debug-level logging
-- `-verbose`: Enable info-level logging (no-op if `-debug` is also given)
-- `-json`: Log in JSON format, instead of plain text
-- `cleanslate`: Start with a clean slate; erases all tasks from the local MongoDB,
-  then exits Flamenco Manager. This can be run while another Flamenco Manager is
-  running, but this scenario has not been well-tested yet.
-
-
-## Starting development
-
-`$FM` denotes the directory containing a checkout of Flamenco Manager, that is, the absolute path
-of this `flamenco-manager-go` directory.
-
-0. Make sure you have MongoDB up and running (on localhost)
-1. Install Go 1.8 or newer
-2. `export GOPATH=$FM`
-3. `cd $FM/src/flamenco-manager`
-4. Download all dependencies with `go get`
-5. Download Flamenco test dependencies with `go get -t ./...`
-6. Run the unittests with `go test ./...`
-7. Build your first Flamenco Manager with `go build`; this will create an executable
-   `flamenco-manager` in `$FM/src/flamenco-manager` as well as an executable in the current folder
-8. Copy `flamenco-manager-example.yaml` and name it `flamenco-manager.yaml` and then update
-   it with the info generated after creating a manager document on the Server
-
-### Testing
-
-To run all unit tests, run `go test ./flamenco -v`. To run a specific GoCheck test, run
-`go test ./flamenco -v --run TestWithGocheck -check.f SchedulerTestSuite.TestVariableReplacement`
-where the argument to `--run` determines which suite to run, and `-check.f` determines the
-exact test function of that suite. Once all tests have been moved over to use GoCheck, the
-`--run` parameter will probably not be needed any more.
-
-
-## Communication between Server and Manager
-
-Flamenco Manager is responsible for initiating all communication between Server and Manager,
-since Manager should be able to run behind some firewall/router, without being reachable by Server.
-
-In the text below, `some_fields` refer to configuration file settings.
-
-### Fetching tasks
-
-1. When a Worker ask for a task, it is served a task in state `queued` or `claimed-by-manager` in
-   the local task queue (MongoDB collection "flamenco_tasks"). In this case, Manager performs a
-   conditional GET (based on etag) to Server at /api/flamenco/tasks/{task-id} to see if the task
-   has been updated since queued. If this is so, the task is updated in the queue and the queue
-   is re-examined.
-2. When the queue is empty, the manager fetches N new tasks from the Server, where N is the number
-   of registered workers.
-
-### Task updates and canceling running tasks
-
-0. Pushes happen as POST to "/api/flamenco/managers/{manager-id}/task-update-batch"
-1. Task updates queued by workers are pushed every `task_update_push_max_interval_seconds`, or
-   when `task_update_push_max_count` updates are queued, whichever happens sooner.
-2. An empty list of task updates is pushed every `cancel_task_fetch_max_interval_seconds`, unless an
-   actual push (as described above) already happened within that time.
-3. The response to a push contains the database IDs of the accepted task updates, as well as
-   a list of task database IDs of tasks that should be canceled. If this list is non-empty, the
-   tasks' statuses are updated accordingly.
-
-
-## Timeouts of active tasks
-
-When a worker starts working on a task, that task moves to status "active". The worker then
-regularly calls `/may-i-run/{task-id}` to verify that it is still allowed to run that task. If this
-end-point is not called within `active_task_timeout_interval_seconds` seconds, it will go to status
-"failed". The default for this setting is 60 seconds, which is likely to be too short, so please
-configure it for your environment.
-
-This timeout check will start running 5 minutes after the Manager has started up. This allows
-workers to let it know they are still alive, in case the manager was unreachable for longer than
-the timeout period. For now this startup delay is hard-coded.
-
-
-## Known issues & limitations
-
-1. The downloading of tasks doesn't consider job types. This means that workers can be starved
-   waiting for tasks, when there are 1000nds of tasks and workers of type X and only a relatively
-   low number of workers and tasks of type Y.
-
-## MISSING FEATURES / TO DO
-
-In no particular order:
-
-- Task queue cleanup. At the moment tasks are stored in the queue forever, since that makes
-  it possible to notice a task was canceled while a worker was running it. Eventually such
-  tasks should be cleaned up, though.
-- GZip compression on the pushes to Server. This is especially important for task updates, since
-  they contain potentially very large log entries.
-- A way for Flamenco Server to get an overview of Workers, and set their status.
-- the Task struct in `documents.go` should be synced with the Eve schema.
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/docker/Dockerfile b/packages/flamenco-manager-go/src/flamenco-manager/docker/Dockerfile
deleted file mode 100644
index 66b0e014bac68c338e78dbece6be5e59243360eb..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/docker/Dockerfile
+++ /dev/null
@@ -1,8 +0,0 @@
-FROM scratch
-MAINTAINER Dr. Sybren <sybren@blender.studio>
-
-EXPOSE 80
-
-ADD flamenco-manager /
-ADD flamenco-manager.yaml /
-CMD ["/flamenco-manager"]
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/docker/build-via-docker.sh b/packages/flamenco-manager-go/src/flamenco-manager/docker/build-via-docker.sh
deleted file mode 100755
index 0538f83976b382106b1f0abb4043d8d23d4de9ef..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/docker/build-via-docker.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash -e
-
-GID=$(id --group)
-
-# Use Docker to get Go in a way that allows overwriting the
-# standard library with statically linked versions.
-docker run -i --rm \
-    -v $(pwd):/docker \
-    -v "${GOPATH}:/go-local" \
-    --env GOPATH=/go-local \
-     golang /bin/bash -e << EOT
-go version
-cd \${GOPATH}/src/flamenco-manager
-CGO_ENABLED=0 go get -a -ldflags '-s'
-cp \${GOPATH}/bin/flamenco-manager /docker
-chown $UID:$GID /docker/flamenco-manager
-EOT
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager-example.yaml b/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager-example.yaml
deleted file mode 100644
index 7b4968d9a576c20559be7ef2fb343426d405da37..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager-example.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-database_url: mongodb://localhost/flamanager
-listen: '[::0]:8083'
-own_url: http://192.168.3.108:8083/
-flamenco: https://cloud.blender.org/
-manager_id: 58514ce59837734ea16e9060
-manager_secret: theworldistheworld
-tlskey: tls/privkey.pem
-tlscert: tls/cert.pem
-
-# How often the Manager should ask the Server for new tasks when the local queue is empty.
-download_task_sleep_seconds: 60
-
-# The number of seconds between rechecks when there are no more tasks for workers.
-# If set to 0, will not throttle at all.
-# If set to -1, will never check when a worker asks for a task (so only every
-# download_task_sleep_seconds seconds).
-download_task_recheck_throttle_seconds: 10
-
-# These settings determine the task update batching behaviour. All task updates are batched,
-# and the batch is sent whenever the max seconds since the last push have passed, or when
-# the batch is at its maximum size, whichever happens first.
-task_update_push_max_interval_seconds: 5
-task_update_push_max_count: 20
-
-# An empty list of task updates is pushed every `cancel_task_fetch_max_interval_seconds`,
-# unless an actual task update push already happened within that time. This controls how
-# fast the Manager can respond to task cancel requests.
-cancel_task_fetch_max_interval_seconds: 10
-
-# When a task has status "active", but it hasn't been touched by a worker in
-# this many seconds, it will go to state "failed". Being "touched" means that
-# a worker called /may-i-run/{task-id} for this task.
-active_task_timeout_interval_seconds: 60
-
-variables:
-    blender:
-        windows: c:/temp/blender.exe
-        linux: /opt/myblenderbuild/blender
-        darwin: /opt/myblenderbuild/blender
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager.service b/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager.service
deleted file mode 100644
index ebc5d0593cddab564adf4bf99acbe94a66d651bf..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco-manager.service
+++ /dev/null
@@ -1,20 +0,0 @@
-[Unit]
-Description=Flamenco Manager
-Documentation=https://flamenco.io/
-After=mongodb.service
-
-[Service]
-Type=simple
-
-ExecStart=/home/flamanager/flamenco-manager
-WorkingDirectory=/home/flamanager
-User=flamanager
-Group=flamanager
-
-Restart=on-failure
-RestartSec=1s
-
-EnvironmentFile=-/etc/default/locale
-
-[Install]
-WantedBy=multi-user.target
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/closable.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/closable.go
deleted file mode 100644
index d9be5d4e8969773af6b417b930b4d89616902dd8..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/closable.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package flamenco
-
-import (
-	"sync"
-
-	log "github.com/Sirupsen/logrus"
-)
-
-// closable offers a way to cleanly shut down a running goroutine.
-type closable struct {
-	doneChan chan struct{}
-	doneWg   *sync.WaitGroup
-}
-
-// makeClosable constructs a new closable struct
-func makeClosable() closable {
-	return closable{make(chan struct{}), new(sync.WaitGroup)}
-}
-
-// closableAdd(delta) should be combined with 'delta' calls to closableDone()
-func (closable *closable) closableAdd(delta int) bool {
-	log.Debugf("Closable: doneWg.Add(%d) ok", delta)
-	closable.doneWg.Add(delta)
-	return true
-}
-
-// closableDone marks one "thing" as "done"
-func (closable *closable) closableDone() {
-	log.Debugf("Closable: doneWg.Done() ok")
-	closable.doneWg.Done()
-}
-
-// closableCloseAndWait marks the goroutine as "done",
-// and waits for all things added with closableAdd() to be "done" too.
-func (closable *closable) closableCloseAndWait() {
-	close(closable.doneChan)
-	log.Debugf("Closable: waiting for shutdown to finish.")
-	closable.doneWg.Wait()
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/db.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/db.go
deleted file mode 100644
index 857748b623a9f3987143e0305e4e124fa351fd99..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/db.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package flamenco
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-
-	log "github.com/Sirupsen/logrus"
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-type countresult struct {
-	Count int `bson:"count"`
-}
-
-// M is a shortcut for bson.M to make longer queries easier to read.
-type M bson.M
-
-// MongoSession returns a MongoDB session.
-//
-// The database name should be configured in the database URL.
-// You can use this default database using session.DB("").
-func MongoSession(config *Conf) *mgo.Session {
-	var err error
-	var session *mgo.Session
-
-	log.Infof("Connecting to MongoDB at %s", config.DatabaseUrl)
-	if session, err = mgo.Dial(config.DatabaseUrl); err != nil {
-		panic(err)
-	}
-	session.SetMode(mgo.Monotonic, true)
-
-	ensureIndices(session)
-
-	return session
-}
-
-func ensureIndices(session *mgo.Session) {
-	db := session.DB("")
-
-	index := mgo.Index{
-		Key:        []string{"status", "priority"},
-		Unique:     false,
-		DropDups:   false,
-		Background: false,
-		Sparse:     false,
-	}
-	if err := db.C("flamenco_tasks").EnsureIndex(index); err != nil {
-		panic(err)
-	}
-
-	index = mgo.Index{
-		Key:        []string{"task_id", "received_on_manager"},
-		Unique:     false,
-		DropDups:   false,
-		Background: false,
-		Sparse:     false,
-	}
-	if err := db.C("task_update_queue").EnsureIndex(index); err != nil {
-		panic(err)
-	}
-}
-
-// Count returns the number of documents in the given collection.
-func Count(coll *mgo.Collection) (int, error) {
-	aggrOps := []bson.M{
-		bson.M{
-			"$group": bson.M{
-				"_id":   nil,
-				"count": bson.M{"$sum": 1},
-			},
-		},
-	}
-	pipe := coll.Pipe(aggrOps)
-	result := countresult{}
-	if err := pipe.One(&result); err != nil {
-		if err == mgo.ErrNotFound {
-			// An empty collection is not an error.
-			return 0, nil
-		}
-		return -1, err
-	}
-
-	return result.Count, nil
-}
-
-// GetSettings returns the settings as saved in our MongoDB.
-func GetSettings(db *mgo.Database) *SettingsInMongo {
-	settings := &SettingsInMongo{}
-	err := db.C("settings").Find(bson.M{}).One(settings)
-	if err != nil && err != mgo.ErrNotFound {
-		log.Panic("db.GetSettings: Unable to get settings: ", err)
-	}
-
-	return settings
-}
-
-// SaveSettings stores the given settings in MongoDB.
-func SaveSettings(db *mgo.Database, settings *SettingsInMongo) {
-	_, err := db.C("settings").Upsert(bson.M{}, settings)
-	if err != nil && err != mgo.ErrNotFound {
-		log.Panic("db.SaveSettings: Unable to save settings: ", err)
-	}
-}
-
-// CleanSlate erases all tasks in the flamenco_tasks collection.
-func CleanSlate(db *mgo.Database) {
-	fmt.Println("")
-	fmt.Println("Performing Clean Slate operation, this will erase all tasks from the local DB.")
-	fmt.Println("After performing the Clean Slate, Flamenco-Manager will shut down.")
-	fmt.Println("Press [ENTER] to continue, [Ctrl+C] to abort.")
-	bufio.NewReader(os.Stdin).ReadLine()
-
-	info, err := db.C("flamenco_tasks").RemoveAll(bson.M{})
-	if err != nil {
-		log.WithError(err).Panic("unable to erase all tasks")
-	}
-	log.Warningf("Erased %d tasks", info.Removed)
-
-	settings := GetSettings(db)
-	settings.DepsgraphLastModified = nil
-	SaveSettings(db, settings)
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/documents.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/documents.go
deleted file mode 100644
index 60e9cf9cf0d90a90fa203aaf741797a700cc24e3..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/documents.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package flamenco
-
-import (
-	"time"
-
-	"gopkg.in/mgo.v2/bson"
-)
-
-// Command is an executable part of a Task
-type Command struct {
-	Name     string `bson:"name" json:"name"`
-	Settings bson.M `bson:"settings" json:"settings"`
-}
-
-// Task contains a Flamenco task, with some BSON-only fields for local Manager use.
-type Task struct {
-	ID          bson.ObjectId   `bson:"_id,omitempty" json:"_id,omitempty"`
-	Etag        string          `bson:"_etag,omitempty" json:"_etag,omitempty"`
-	Job         bson.ObjectId   `bson:"job,omitempty" json:"job"`
-	Manager     bson.ObjectId   `bson:"manager,omitempty" json:"manager"`
-	Project     bson.ObjectId   `bson:"project,omitempty" json:"project"`
-	User        bson.ObjectId   `bson:"user,omitempty" json:"user"`
-	Name        string          `bson:"name" json:"name"`
-	Status      string          `bson:"status" json:"status"`
-	Priority    int             `bson:"priority" json:"priority"`
-	JobPriority int             `bson:"job_priority" json:"job_priority"`
-	JobType     string          `bson:"job_type" json:"job_type"`
-	Commands    []Command       `bson:"commands" json:"commands"`
-	Log         string          `bson:"log,omitempty" json:"log,omitempty"`
-	Activity    string          `bson:"activity,omitempty" json:"activity,omitempty"`
-	Parents     []bson.ObjectId `bson:"parents,omitempty" json:"parents,omitempty"`
-	Worker      string          `bson:"worker,omitempty" json:"worker,omitempty"`
-
-	// Internal bookkeeping
-	WorkerID       *bson.ObjectId `bson:"worker_id,omitempty" json:"-"`
-	LastWorkerPing *time.Time     `bson:"last_worker_ping,omitempty" json:"-"`
-}
-
-type aggregationPipelineResult struct {
-// For internal MongoDB querying only
-	Task *Task `bson:"task"`
-}
-
-// ScheduledTasks contains a dependency graph response from Server.
-type ScheduledTasks struct {
-	Depsgraph []Task `json:"depsgraph"`
-}
-
-// TaskUpdate is both sent from Worker to Manager, as well as from Manager to Server.
-type TaskUpdate struct {
-	ID                        bson.ObjectId `bson:"_id" json:"_id"`
-	TaskID                    bson.ObjectId `bson:"task_id" json:"task_id,omitempty"`
-	TaskStatus                string        `bson:"task_status,omitempty" json:"task_status,omitempty"`
-	ReceivedOnManager         time.Time     `bson:"received_on_manager" json:"received_on_manager"`
-	Activity                  string        `bson:"activity,omitempty" json:"activity,omitempty"`
-	TaskProgressPercentage    int           `bson:"task_progress_percentage" json:"task_progress_percentage"`
-	CurrentCommandIdx         int           `bson:"current_command_idx" json:"current_command_idx"`
-	CommandProgressPercentage int           `bson:"command_progress_percentage" json:"command_progress_percentage"`
-	Log                       string        `bson:"log,omitempty" json:"log,omitempty"`
-	Worker                    string        `bson:"worker" json:"worker"`
-}
-
-// TaskUpdateResponse is received from Server.
-type TaskUpdateResponse struct {
-	ModifiedCount    int             `json:"modified_count"`
-	HandledUpdateIds []bson.ObjectId `json:"handled_update_ids,omitempty"`
-	CancelTasksIds   []bson.ObjectId `json:"cancel_task_ids,omitempty"`
-}
-
-// WorkerRegistration is sent by the Worker to register itself at this Manager.
-type WorkerRegistration struct {
-	Secret            string   `json:"secret"`
-	Platform          string   `json:"platform"`
-	SupportedJobTypes []string `json:"supported_job_types"`
-	Nickname          string   `json:"nickname"`
-}
-
-// Worker contains all information about a specific Worker.
-// Some fields come from the WorkerRegistration, whereas others are filled by us.
-type Worker struct {
-	ID                bson.ObjectId `bson:"_id,omitempty" json:"_id,omitempty"`
-	Secret            string        `bson:"-" json:"-"`
-	HashedSecret      []byte        `bson:"hashed_secret" json:"-"`
-	Nickname          string        `bson:"nickname" json:"nickname"`
-	Address           string        `bson:"address" json:"address"`
-	Status            string        `bson:"status" json:"status"`
-	Platform          string        `bson:"platform" json:"platform"`
-	CurrentTask       bson.ObjectId `bson:"current_task,omitempty" json:"current_task,omitempty"`
-	TimeCost          int           `bson:"time_cost" json:"time_cost"`
-	LastActivity      *time.Time    `bson:"last_activity,omitempty" json:"last_activity,omitempty"`
-	SupportedJobTypes []string      `bson:"supported_job_types" json:"supported_job_types"`
-}
-
-// StartupNotification sent to upstream Flamenco Server upon startup. This is a combination
-// of settings (see settings.go) and information from the database.
-type StartupNotification struct {
-	// Settings
-	ManagerURL         string                       `json:"manager_url"`
-	VariablesByVarname map[string]map[string]string `json:"variables"`
-
-	// From our local database
-	NumberOfWorkers int `json:"nr_of_workers"`
-}
-
-// MayKeepRunningResponse is sent to workers to indicate whether they can keep running their task.
-type MayKeepRunningResponse struct {
-	MayKeepRunning bool   `json:"may_keep_running"`
-	Reason         string `json:"reason,omitempty"`
-}
-
-// SettingsInMongo contains settings we want to be able to update from
-// within Flamenco Manager itself, so those are stored in MongoDB.
-type SettingsInMongo struct {
-	DepsgraphLastModified *string `bson:"depsgraph_last_modified"`
-}
-
-// StatusReport is sent in response to a query on the / URL.
-type StatusReport struct {
-	NrOfWorkers int    `json:"nr_of_workers"`
-	NrOfTasks   int    `json:"nr_of_tasks"`
-	Version     string `json:"version"`
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/flamenco-manager.yaml b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/flamenco-manager.yaml
deleted file mode 100644
index 081a77a173cdf3b24e62622b327f9940fdb83345..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/flamenco-manager.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-# This file is loaded by unit tests in the 'flamenco' package.
-database_url: mongodb://localhost/flamanager_test
-listen: '[::0]:8083'
-own_url: http://192.168.3.108:8083/
-flamenco: http://localhost:51234/
-manager_id: 5852bc5198377351f95d103e
-manager_secret: SRVwA7wAxPRfudvqTDOLXwPn1cDRIlADz5Ef9kHk7d52Us
-download_task_sleep_seconds: 300
-download_task_recheck_throttle_seconds: -1
-cancel_task_fetch_max_interval_seconds: 10
-
-variables:
-    blender:
-        windows: c:/temp/blender.exe
-        linux: /opt/myblenderbuild/blender
-        darwin: /opt/myblenderbuild/blender
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/gocheck_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/gocheck_test.go
deleted file mode 100644
index 08cd2b88e04eec8ac7eb0ad348c9f568212bb1a3..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/gocheck_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Common test functionality, and integration with GoCheck.
- */
-package flamenco
-
-import (
-	"testing"
-
-	check "gopkg.in/check.v1"
-	"gopkg.in/mgo.v2/bson"
-)
-
-// Hook up gocheck into the "go test" runner.
-// You only need one of these per package, or tests will run multiple times.
-func TestWithGocheck(t *testing.T) { check.TestingT(t) }
-
-func ConstructTestTask(task_id, job_type string) Task {
-	return ConstructTestTaskWithPrio(task_id, job_type, 50)
-}
-
-func ConstructTestTaskWithPrio(task_id, job_type string, priority int) Task {
-	return Task{
-		ID:       bson.ObjectIdHex(task_id),
-		Etag:     "1234567",
-		Job:      bson.ObjectIdHex("bbbbbbbbbbbbbbbbbbbbbbbb"),
-		Manager:  bson.ObjectIdHex("cccccccccccccccccccccccc"),
-		Project:  bson.ObjectIdHex("dddddddddddddddddddddddd"),
-		User:     bson.ObjectIdHex("eeeeeeeeeeeeeeeeeeeeeeee"),
-		Name:     "Test task",
-		Status:   "queued",
-		Priority: priority,
-		JobType:  job_type,
-		Commands: []Command{
-			Command{"echo", bson.M{"message": "Running Blender from {blender}"}},
-			Command{"sleep", bson.M{"time_in_seconds": 3}},
-		},
-		Parents: []bson.ObjectId{
-			bson.ObjectIdHex("ffffffffffffffffffffffff"),
-		},
-		Worker: "worker1",
-	}
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/http.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/http.go
deleted file mode 100644
index 157e113a3564580d2a237325b5a7779143888aba..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/http.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package flamenco
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-
-	log "github.com/Sirupsen/logrus"
-)
-
-// For timestamp parsing
-const IsoFormat = "2006-01-02T15:04:05-0700"
-
-/**
- * Decodes JSON and writes a Bad Request status if it fails.
- */
-func DecodeJson(w http.ResponseWriter, r io.Reader, document interface{},
-	logprefix string) error {
-	dec := json.NewDecoder(r)
-
-	if err := dec.Decode(document); err != nil {
-		log.Warningf("%s Unable to decode JSON: %s", logprefix, err)
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintf(w, "Unable to decode JSON: %s\n", err)
-		return err
-	}
-
-	return nil
-}
-
-/**
- * Sends a JSON document to some URL via HTTP.
- * :param tweakrequest: can be used to tweak the request before sending it, for
- *    example by adding authentication headers. May be nil.
- * :param responsehandler: is called when a non-error response has been read.
- *    May be nil.
- */
-func SendJson(logprefix, method string, url *url.URL,
-	payload interface{},
-	tweakrequest func(req *http.Request),
-	responsehandler func(resp *http.Response, body []byte) error,
-) error {
-	payload_bytes, err := json.Marshal(payload)
-	if err != nil {
-		log.Errorf("%s: Unable to marshal JSON: %s", logprefix, err)
-		return err
-	}
-
-	// TODO Sybren: enable GZip compression.
-	req, err := http.NewRequest("POST", url.String(), bytes.NewBuffer(payload_bytes))
-	if err != nil {
-		log.Errorf("%s: Unable to create request: %s", logprefix, err)
-		return err
-	}
-	req.Header.Add("Content-Type", "application/json")
-	if tweakrequest != nil {
-		tweakrequest(req)
-	}
-
-	client := &http.Client{}
-	resp, err := client.Do(req)
-	if err != nil {
-		log.Warningf("%s: Unable to POST to %s: %s", logprefix, url, err)
-		return err
-	}
-
-	body, err := ioutil.ReadAll(resp.Body)
-	defer resp.Body.Close()
-	if err != nil {
-		log.Warningf("%s: Error %d POSTing to %s: %s",
-			logprefix, resp.StatusCode, url, err)
-		return err
-	}
-
-	if resp.StatusCode >= 300 {
-		suffix := ""
-		if resp.StatusCode != 404 {
-			suffix = fmt.Sprintf("\n    body:\n%s", body)
-		}
-		log.Warningf("%s: Error %d POSTing to %s%s",
-			logprefix, resp.StatusCode, url, suffix)
-		return fmt.Errorf("%s: Error %d POSTing to %s", logprefix, resp.StatusCode, url)
-	}
-
-	if responsehandler != nil {
-		return responsehandler(resp, body)
-	}
-
-	return nil
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/math.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/math.go
deleted file mode 100644
index b24e7cc1725e2eb0c608fb3b342fc02d92237430..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/math.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package flamenco
-
-func MaxInt(a, b int) int {
-	if a < b {
-		return b
-	}
-	return a
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler.go
deleted file mode 100644
index 7fce5d8232eb4759e8ae046cd70edea755b61509..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler.go
+++ /dev/null
@@ -1,204 +0,0 @@
-package flamenco
-
-import (
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	auth "github.com/abbot/go-http-auth"
-
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-type TaskScheduler struct {
-	config   *Conf
-	upstream *UpstreamConnection
-	session  *mgo.Session
-
-	/* Timestamp of the last time we kicked the task downloader because there weren't any
-	 * tasks left for workers. */
-	lastUpstreamCheck time.Time
-}
-
-func CreateTaskScheduler(config *Conf, upstream *UpstreamConnection, session *mgo.Session) *TaskScheduler {
-	return &TaskScheduler{
-		config,
-		upstream,
-		session,
-		time.Time{},
-	}
-}
-
-func (ts *TaskScheduler) ScheduleTask(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
-	mongo_sess := ts.session.Copy()
-	defer mongo_sess.Close()
-	db := mongo_sess.DB("")
-
-	// Fetch the worker's info
-	projection := bson.M{"platform": 1, "supported_job_types": 1, "address": 1, "nickname": 1}
-	worker, err := FindWorker(r.Username, projection, db)
-	if err != nil {
-		log.Warningf("ScheduleTask: Unable to find worker, requested from %s: %s", r.RemoteAddr, err)
-		w.WriteHeader(http.StatusForbidden)
-		fmt.Fprintf(w, "Unable to find worker: %s", err)
-		return
-	}
-	WorkerSeen(worker, r.RemoteAddr, db)
-	log.Infof("ScheduleTask: Worker %s asking for a task", worker.Identifier())
-
-	var task *Task
-	var was_changed bool
-	for attempt := 0; attempt < 1000; attempt++ {
-		// Fetch the first available task of a supported job type.
-		task = ts.fetchTaskFromQueueOrManager(w, db, worker)
-		if task == nil {
-			// A response has already been written to 'w'.
-			return
-		}
-
-		was_changed = ts.upstream.RefetchTask(task)
-		if !was_changed {
-			break
-		}
-
-		log.Debugf("Task %s was changed, reexamining queue.", task.ID.Hex())
-	}
-	if was_changed {
-		log.Errorf("Infinite loop detected, tried 1000 tasks and they all changed...")
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	// Update the task status to "active", pushing it as a task update to the manager too.
-	task.Status = "active"
-	tupdate := TaskUpdate{TaskID: task.ID, TaskStatus: task.Status}
-	local_updates := bson.M{
-		"worker_id":        worker.ID,
-		"last_worker_ping": UtcNow(),
-	}
-	if err := QueueTaskUpdateWithExtra(&tupdate, db, local_updates); err != nil {
-		log.Errorf("Unable to queue task update while assigning task %s to worker %s: %s",
-			task.ID.Hex(), worker.Identifier(), err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	// Perform variable replacement on the task.
-	ReplaceVariables(ts.config, task, worker)
-
-	// Set it to this worker.
-	w.Header().Set("Content-Type", "application/json")
-	encoder := json.NewEncoder(w)
-	encoder.Encode(task)
-
-	log.Infof("ScheduleTask: assigned task %s to worker %s",
-		task.ID.Hex(), worker.Identifier())
-
-	// Push a task log line stating we've assigned this task to the given worker.
-	// This is done here, instead of by the worker, so that it's logged even if the worker fails.
-	msg := fmt.Sprintf("Manager assigned task to worker %s", worker.Identifier())
-	LogTaskActivity(worker, task.ID, msg, time.Now().Format(IsoFormat)+": "+msg, db)
-}
-
-/**
- * Fetches a task from either the queue, or if it is empty, from the manager.
- */
-func (ts *TaskScheduler) fetchTaskFromQueueOrManager(
-	w http.ResponseWriter, db *mgo.Database, worker *Worker) *Task {
-
-	if len(worker.SupportedJobTypes) == 0 {
-		log.Warningf("TaskScheduler: worker %s has no supported job types.", worker.Identifier())
-		w.WriteHeader(http.StatusNotAcceptable)
-		fmt.Fprintln(w, "You do not support any job types.")
-		return nil
-	}
-
-	result := aggregationPipelineResult{}
-	tasks_coll := db.C("flamenco_tasks")
-
-	pipe := tasks_coll.Pipe([]M{
-		// 1: Select only tasks that have a runnable status & acceptable job type.
-		M{"$match": M{
-			"status": M{"$in": []string{"queued", "claimed-by-manager"}},
-			// "job_type": M{"$in": []string{"sleeping", "testing"}},
-		}},
-		// 2: Unwind the parents array, so that we can do a lookup in the next stage.
-		M{"$unwind": M{
-			"path": "$parents",
-			"preserveNullAndEmptyArrays": true,
-		}},
-		// 3: Look up the parent document for each unwound task.
-		// This produces 1-length "parent_doc" arrays.
-		M{"$lookup": M{
-			"from":         "flamenco_tasks",
-			"localField":   "parents",
-			"foreignField": "_id",
-			"as":           "parent_doc",
-		}},
-		// 4: Unwind again, to turn the 1-length "parent_doc" arrays into a subdocument.
-		M{"$unwind": M{
-			"path": "$parent_doc",
-			"preserveNullAndEmptyArrays": true,
-		}},
-		// 5: Group by task ID to undo the unwind, and create an array parent_statuses
-		// with booleans indicating whether the parent status is "completed".
-		M{"$group": M{
-			"_id": "$_id",
-			"parent_statuses": M{"$push": M{
-				"$eq": []interface{}{
-					"completed",
-					M{"$ifNull": []string{"$parent_doc.status", "completed"}}}}},
-			// This allows us to keep all dynamic properties of the original task document:
-			"task": M{"$first": "$$ROOT"},
-		}},
-		// 6: Turn the list of "parent_statuses" booleans into a single boolean
-		M{"$project": M{
-			"_id":               0,
-			"parents_completed": M{"$allElementsTrue": []string{"$parent_statuses"}},
-			"task":              1,
-		}},
-		// 7: Select only those tasks for which the parents have completed.
-		M{"$match": M{
-			"parents_completed": true,
-		}},
-		// 8: just keep the task info, the "parents_runnable" is no longer needed.
-		M{"$project": M{"task": 1}},
-		// 9: Sort by priority, with highest prio first. If prio is equal, use newest task.
-		M{"$sort": bson.D{
-			{"task.job_priority", -1},
-			{"task.priority", -1},
-			{"task._id", 1},
-		}},
-		// 10: Only return one task.
-		M{"$limit": 1},
-	})
-
-	err := pipe.One(&result)
-	if err == mgo.ErrNotFound {
-		log.Infof("TaskScheduler: no more tasks available for %s", worker.Identifier())
-		ts.maybeKickTaskDownloader()
-		w.WriteHeader(204)
-		return nil
-	}
-	if err != nil {
-		log.Errorf("TaskScheduler: Error fetching task for %s: %s", worker.Identifier(), err)
-		w.WriteHeader(500)
-		return nil
-	}
-
-	return result.Task
-}
-
-func (ts *TaskScheduler) maybeKickTaskDownloader() {
-	dtrt := ts.config.DownloadTaskRecheckThrottle
-	if dtrt < 0 || time.Now().Sub(ts.lastUpstreamCheck) <= dtrt {
-		return
-	}
-
-	log.Infof("TaskScheduler: kicking task downloader")
-	ts.lastUpstreamCheck = time.Now()
-	ts.upstream.KickDownloader(false)
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler_test.go
deleted file mode 100644
index c33c9f84c16e7354a3f38cfc27f9dd22095f0674..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/scheduler_test.go
+++ /dev/null
@@ -1,420 +0,0 @@
-package flamenco
-
-import (
-	"encoding/json"
-	"net/http"
-	"net/http/httptest"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	auth "github.com/abbot/go-http-auth"
-	"github.com/stretchr/testify/assert"
-
-	check "gopkg.in/check.v1"
-	"gopkg.in/jarcoal/httpmock.v1"
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-type SchedulerTestSuite struct {
-	worker_lnx Worker
-	worker_win Worker
-
-	db       *mgo.Database
-	upstream *UpstreamConnection
-	sched    *TaskScheduler
-}
-
-var _ = check.Suite(&SchedulerTestSuite{})
-
-func parseJson(c *check.C, resp_rec *httptest.ResponseRecorder, expected_status int, parsed interface{}) {
-	assert.Equal(c, 200, resp_rec.Code)
-	headers := resp_rec.Header()
-	assert.Equal(c, "application/json", headers.Get("Content-Type"))
-
-	decoder := json.NewDecoder(resp_rec.Body)
-	if err := decoder.Decode(&parsed); err != nil {
-		c.Fatalf("Unable to decode JSON: %s", err)
-	}
-}
-
-func (s *SchedulerTestSuite) SetUpTest(c *check.C) {
-	httpmock.Activate()
-
-	config := GetTestConfig()
-	session := MongoSession(&config)
-	s.db = session.DB("")
-
-	s.upstream = ConnectUpstream(&config, session)
-	s.sched = CreateTaskScheduler(&config, s.upstream, session)
-
-	// Store workers in DB, on purpose in the opposite order as the tasks.
-	s.worker_lnx = Worker{
-		Platform:          "linux",
-		SupportedJobTypes: []string{"sleeping"},
-		Nickname:          "worker_lnx",
-	}
-	if err := StoreNewWorker(&s.worker_lnx, s.db); err != nil {
-		c.Fatal("Unable to insert test worker_lnx", err)
-	}
-	s.worker_win = Worker{
-		Platform:          "windows",
-		SupportedJobTypes: []string{"testing"},
-		Nickname:          "worker_win",
-	}
-	if err := StoreNewWorker(&s.worker_win, s.db); err != nil {
-		c.Fatal("Unable to insert test worker_win", err)
-	}
-
-}
-
-func (s *SchedulerTestSuite) TearDownTest(c *check.C) {
-	log.Info("SchedulerTestSuite tearing down test, dropping database.")
-	s.upstream.Close()
-	s.db.DropDatabase()
-	httpmock.DeactivateAndReset()
-}
-
-/**
- * In this test we don't mock the upstream HTTP connection, so it's normal to see
- * errors about failed requests. These are harmless. As a matter of fact, testing
- * in such error conditions is good; task scheduling should keep working.
- */
-func (s *SchedulerTestSuite) TestVariableReplacement(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTask("aaaaaaaaaaaaaaaaaaaaaaaa", "testing")
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task", err)
-	}
-	task2 := ConstructTestTask("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping")
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	// Perform HTTP request
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	// Check the response JSON
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-	assert.Equal(t, "active", json_task.Status)
-	assert.Equal(t, "sleeping", json_task.JobType)
-	assert.Equal(t, "Running Blender from /opt/myblenderbuild/blender",
-		json_task.Commands[0].Settings["message"])
-
-	// Check worker with other job type
-	ar = &auth.AuthenticatedRequest{Request: *request, Username: s.worker_win.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	// Check the response JSON
-	parseJson(t, resp_rec, 200, &json_task)
-	assert.Equal(t, "active", json_task.Status)
-	assert.Equal(t, "testing", json_task.JobType)
-	assert.Equal(t, "Running Blender from c:/temp/blender.exe",
-		json_task.Commands[0].Settings["message"])
-
-}
-
-func (s *SchedulerTestSuite) TestSchedulerOrderByPriority(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task1", err)
-	}
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	// Perform HTTP request to the scheduler.
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	// We should have gotten task 2, because it has the highest priority.
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-	assert.Equal(t, task2.ID.Hex(), json_task.ID.Hex())
-}
-
-func (s *SchedulerTestSuite) TestSchedulerOrderByJobPriority(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	task1.JobPriority = 10
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task1", err)
-	}
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	task2.JobPriority = 5
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	// Perform HTTP request to the scheduler.
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	// We should have gotten task 1, because its job has the highest priority.
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-	assert.Equal(t, task1.ID.Hex(), json_task.ID.Hex())
-}
-
-/**
- * The failure case, where the TaskScheduler cannot reach the Server to check
- * the task for updates, is already implicitly handled in the TestVariableReplacement
- * test case; a Responder for that endpoint isn't registered there, and thus it results
- * in a connection error.
- */
-func (s *SchedulerTestSuite) TestSchedulerVerifyUpstreamCanceled(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task1", err)
-	}
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	timeout := TimeoutAfter(1 * time.Second)
-	defer close(timeout)
-
-	// Mock that the task with highest priority was actually canceled on the Server.
-	httpmock.RegisterResponder(
-		"GET",
-		"http://localhost:51234/api/flamenco/tasks/2aaaaaaaaaaaaaaaaaaaaaaa",
-		func(req *http.Request) (*http.Response, error) {
-			defer func() { timeout <- false }()
-			log.Info("GET from manager received on server, sending back updated task.")
-
-			// same task, but with changed status.
-			changed_task := task2
-			changed_task.Status = "canceled"
-			return httpmock.NewJsonResponse(200, &changed_task)
-		},
-	)
-
-	// Perform HTTP request to the scheduler.
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	timedout := <-timeout
-	assert.False(t, timedout, "HTTP GET to Flamenco Server not performed")
-
-	// Check the response JSON
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-
-	// We should have gotten task 1, because task 2 was canceled.
-	assert.Equal(t, task1.ID.Hex(), json_task.ID.Hex())
-
-	// In our queue, task 2 should have been canceled, since it was canceled on the server.
-	found_task2 := Task{}
-	err := s.db.C("flamenco_tasks").FindId(task2.ID).One(&found_task2)
-	assert.Equal(t, nil, err)
-	assert.Equal(t, "canceled", found_task2.Status)
-}
-
-func (s *SchedulerTestSuite) TestSchedulerVerifyUpstreamPrioChange(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task1", err)
-	}
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	timeout := TimeoutAfter(1 * time.Second)
-	defer close(timeout)
-
-	// Mock that the task with highest priority was actually canceled on the Server.
-	httpmock.RegisterResponder(
-		"GET",
-		"http://localhost:51234/api/flamenco/tasks/2aaaaaaaaaaaaaaaaaaaaaaa",
-		func(req *http.Request) (*http.Response, error) {
-			defer func() { timeout <- false }()
-			log.Info("GET from manager received on server, sending back updated task.")
-
-			// same task, but with changed status.
-			changed_task := task2
-			changed_task.Priority = 5
-			return httpmock.NewJsonResponse(200, &changed_task)
-		},
-	)
-
-	// Perform HTTP request to the scheduler.
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	timedout := <-timeout
-	assert.False(t, timedout, "HTTP GET to Flamenco Server not performed")
-
-	// Check the response JSON
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-
-	// We should have gotten task 1, because task 2 was lowered in prio.
-	assert.Equal(t, task1.ID.Hex(), json_task.ID.Hex())
-
-	// In our queue, task 2 should have been lowered in prio, and task1 should be active.
-	found_task := Task{}
-	err := s.db.C("flamenco_tasks").FindId(task2.ID).One(&found_task)
-	assert.Equal(t, nil, err)
-	assert.Equal(t, "queued", found_task.Status)
-	assert.Equal(t, 5, found_task.Priority)
-
-	err = s.db.C("flamenco_tasks").FindId(task1.ID).One(&found_task)
-	assert.Equal(t, nil, err)
-	assert.Equal(t, "active", found_task.Status)
-	assert.Equal(t, 50, found_task.Priority)
-}
-
-func (s *SchedulerTestSuite) TestSchedulerVerifyUpstreamDeleted(t *check.C) {
-	// Store task in DB.
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	if err := s.db.C("flamenco_tasks").Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task1", err)
-	}
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	if err := s.db.C("flamenco_tasks").Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	timeout := TimeoutAfter(1 * time.Second)
-	defer close(timeout)
-
-	// Mock that the task with highest priority was actually canceled on the Server.
-	httpmock.RegisterResponder(
-		"GET",
-		"http://localhost:51234/api/flamenco/tasks/2aaaaaaaaaaaaaaaaaaaaaaa",
-		func(req *http.Request) (*http.Response, error) {
-			defer func() { timeout <- false }()
-			log.Info("GET from manager received on server, sending back 404.")
-			return httpmock.NewStringResponse(404, ""), nil
-		},
-	)
-
-	// Perform HTTP request to the scheduler.
-	resp_rec := httptest.NewRecorder()
-	request, _ := http.NewRequest("GET", "/task", nil)
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: s.worker_lnx.ID.Hex()}
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	timedout := <-timeout
-	assert.False(t, timedout, "HTTP GET to Flamenco Server not performed")
-
-	// Check the response JSON
-	json_task := Task{}
-	parseJson(t, resp_rec, 200, &json_task)
-
-	// We should have gotten task 1, because task 2 was deleted.
-	assert.Equal(t, task1.ID.Hex(), json_task.ID.Hex())
-
-	// In our queue, task 2 should have been canceled, and task1 should be active.
-	found_task := Task{}
-	err := s.db.C("flamenco_tasks").FindId(task2.ID).One(&found_task)
-	assert.Equal(t, nil, err)
-	assert.Equal(t, "canceled", found_task.Status)
-	assert.Equal(t, 100, found_task.Priority)
-
-	err = s.db.C("flamenco_tasks").FindId(task1.ID).One(&found_task)
-	assert.Equal(t, nil, err)
-	assert.Equal(t, "active", found_task.Status)
-	assert.Equal(t, 50, found_task.Priority)
-}
-
-func (s *SchedulerTestSuite) TestParentTaskNotCompleted(c *check.C) {
-	tasks_coll := s.db.C("flamenco_tasks")
-
-	// Task 1 is being worked on by worker_win
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	task1.Status = "active"
-	task1.WorkerID = &s.worker_win.ID
-	assert.Nil(c, tasks_coll.Insert(task1))
-
-	// Task 2 is unavailable due to its parent not being completed.
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	task2.Parents = []bson.ObjectId{task1.ID}
-	task2.Status = "claimed-by-manager"
-	assert.Nil(c, tasks_coll.Insert(task2))
-
-	// Fetch a task from the queue
-	resp_rec, _ := WorkerTestRequest(s.worker_lnx.ID, "TEST", "/whatevah")
-	task := s.sched.fetchTaskFromQueueOrManager(resp_rec, s.db, &s.worker_lnx)
-
-	// We should not get any task back, since task1 is already taken, and task2
-	// has a non-completed parent.
-	assert.Nil(c, task, "Expected nil, got task %v instead", task)
-	assert.Equal(c, http.StatusNoContent, resp_rec.Code)
-}
-
-func (s *SchedulerTestSuite) TestParentTaskCompleted(c *check.C) {
-	tasks_coll := s.db.C("flamenco_tasks")
-
-	// Task 1 has been completed by worker_win
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	task1.Status = "completed"
-	task1.WorkerID = &s.worker_win.ID
-	assert.Nil(c, tasks_coll.Insert(task1))
-
-	// Task 2 is available due to its parent being completed.
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	task2.Parents = []bson.ObjectId{task1.ID}
-	task2.Status = "claimed-by-manager"
-	assert.Nil(c, tasks_coll.Insert(task2))
-
-	// Fetch a task from the queue
-	resp_rec, _ := WorkerTestRequest(s.worker_lnx.ID, "TEST", "/whatevah")
-	task := s.sched.fetchTaskFromQueueOrManager(resp_rec, s.db, &s.worker_lnx)
-	assert.Equal(c, http.StatusOK, resp_rec.Code)
-
-	// We should get task 2.
-	assert.NotNil(c, task, "Expected task %s, got nil instead", task2.ID.Hex())
-	if task != nil { // prevent nil pointer dereference
-		assert.Equal(c, task.ID, task2.ID, "Expected task %s, got task %s instead",
-			task2.ID.Hex(), task.ID.Hex())
-	}
-}
-
-func (s *SchedulerTestSuite) TestParentTaskOneCompletedOneNot(c *check.C) {
-	tasks_coll := s.db.C("flamenco_tasks")
-
-	// Task 1 is being worked on by worker_win
-	task1 := ConstructTestTaskWithPrio("1aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	task1.Status = "active"
-	task1.WorkerID = &s.worker_win.ID
-	assert.Nil(c, tasks_coll.Insert(task1))
-
-	// Task 2 is already completed.
-	task2 := ConstructTestTaskWithPrio("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 50)
-	task2.Status = "completed"
-	task2.WorkerID = &s.worker_win.ID
-	assert.Nil(c, tasks_coll.Insert(task2))
-
-	// Task 3 is unavailable due to one of its parent not being completed.
-	task3 := ConstructTestTaskWithPrio("3aaaaaaaaaaaaaaaaaaaaaaa", "sleeping", 100)
-	task3.Parents = []bson.ObjectId{task1.ID, task2.ID}
-	task3.Status = "claimed-by-manager"
-	assert.Nil(c, tasks_coll.Insert(task3))
-
-	// Fetch a task from the queue
-	resp_rec, _ := WorkerTestRequest(s.worker_lnx.ID, "TEST", "/whatevah")
-	task := s.sched.fetchTaskFromQueueOrManager(resp_rec, s.db, &s.worker_lnx)
-
-	// We should not get any task back.
-	assert.Nil(c, task, "Expected nil, got task %v instead", task)
-	assert.Equal(c, http.StatusNoContent, resp_rec.Code)
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/settings.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/settings.go
deleted file mode 100644
index 9b787344e0c953811ae4a6ccddba8d55479f5eee..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/settings.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package flamenco
-
-import (
-	"io/ioutil"
-	"net/url"
-	"os"
-	"path"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-
-	"gopkg.in/yaml.v2"
-)
-
-type Conf struct {
-	DatabaseUrl   string   `yaml:"database_url"`
-	Listen        string   `yaml:"listen"`
-	OwnUrl        string   `yaml:"own_url"`
-	FlamencoStr   string   `yaml:"flamenco"`
-	Flamenco      *url.URL `yaml:"-"`
-	ManagerId     string   `yaml:"manager_id"`
-	ManagerSecret string   `yaml:"manager_secret"`
-	TLSKey        string   `yaml:"tlskey"`
-	TLSCert       string   `yaml:"tlscert"`
-
-	DownloadTaskSleep_ int           `yaml:"download_task_sleep_seconds"`
-	DownloadTaskSleep  time.Duration `yaml:"-"`
-
-	/* The number of seconds between rechecks when there are no more tasks for workers.
-	 * If set to 0, will not throttle at all.
-	 * If set to -1, will never check when a worker asks for a task (so only every
-	 * download_task_sleep_seconds seconds). */
-	DownloadTaskRecheckThrottle_ int           `yaml:"download_task_recheck_throttle_seconds"`
-	DownloadTaskRecheckThrottle  time.Duration `yaml:"-"`
-
-	/* Variables, stored differently in YAML and these settings.
-	 * Variables:             variable name -> platform -> value
-	 * VariablesPerPlatform:  platform -> variable name -> value
-	 */
-	VariablesByVarname  map[string]map[string]string `yaml:"variables"`
-	VariablesByPlatform map[string]map[string]string `yaml:"-"`
-
-	TaskUpdatePushMaxInterval_ int           `yaml:"task_update_push_max_interval_seconds"`
-	TaskUpdatePushMaxInterval  time.Duration `yaml:"-"`
-	TaskUpdatePushMaxCount     int           `yaml:"task_update_push_max_count"`
-	CancelTaskFetchInterval_   int           `yaml:"cancel_task_fetch_max_interval_seconds"`
-	CancelTaskFetchInterval    time.Duration `yaml:"-"`
-
-	ActiveTaskTimeoutInterval_ int           `yaml:"active_task_timeout_interval_seconds"`
-	ActiveTaskTimeoutInterval  time.Duration `yaml:"-"`
-}
-
-func GetConf() Conf {
-	yamlFile, err := ioutil.ReadFile("flamenco-manager.yaml")
-	if err != nil {
-		log.Fatalf("GetConf err   #%v ", err)
-	}
-
-	// Construct the struct with some more or less sensible defaults.
-	c := Conf{
-		DownloadTaskSleep_:           300,
-		DownloadTaskRecheckThrottle_: 10,
-		TaskUpdatePushMaxInterval_:   30,
-		TaskUpdatePushMaxCount:       10,
-		CancelTaskFetchInterval_:     10,
-		ActiveTaskTimeoutInterval_:   60,
-	}
-	err = yaml.Unmarshal(yamlFile, &c)
-	if err != nil {
-		log.Fatalf("Unmarshal: %v", err)
-	}
-
-	// Parse URL
-	c.Flamenco, err = url.Parse(c.FlamencoStr)
-	if err != nil {
-		log.Fatalf("Bad Flamenco URL: %v", err)
-	}
-
-	// Transpose the variables matrix.
-	c.VariablesByPlatform = make(map[string]map[string]string)
-	for varname, perplatform := range c.VariablesByVarname {
-		for platform, varvalue := range perplatform {
-			if c.VariablesByPlatform[platform] == nil {
-				c.VariablesByPlatform[platform] = make(map[string]string)
-			}
-			c.VariablesByPlatform[platform][varname] = varvalue
-		}
-	}
-
-	// Convert durations. TODO: use actual unmarshaling code for this.
-	c.DownloadTaskSleep = time.Duration(c.DownloadTaskSleep_) * time.Second
-	c.DownloadTaskRecheckThrottle = time.Duration(c.DownloadTaskRecheckThrottle_) * time.Second
-	c.TaskUpdatePushMaxInterval = time.Duration(c.TaskUpdatePushMaxInterval_) * time.Second
-	c.CancelTaskFetchInterval = time.Duration(c.CancelTaskFetchInterval_) * time.Second
-	c.ActiveTaskTimeoutInterval = time.Duration(c.ActiveTaskTimeoutInterval_) * time.Second
-
-	return c
-}
-
-/**
- * Configuration for unit tests.
- */
-func GetTestConfig() Conf {
-	cwd, err := os.Getwd()
-	if err != nil {
-		log.Fatal(err)
-		os.Exit(1)
-	}
-
-	if path.Base(cwd) != "flamenco" {
-		log.Panic("Expecting tests to run from flamenco package dir.")
-		os.Exit(2)
-	}
-
-	return GetConf()
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/statusreport.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/statusreport.go
deleted file mode 100644
index 3af607505cdc214f5e9644e42dd383806af05ccf..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/statusreport.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package flamenco
-
-import (
-	"encoding/json"
-	"fmt"
-	"net/http"
-
-	log "github.com/Sirupsen/logrus"
-	mgo "gopkg.in/mgo.v2"
-)
-
-/**
- * Reports the status of the manager in JSON.
- */
-func SendStatusReport(w http.ResponseWriter, r *http.Request, session *mgo.Session,
-	flamenco_version string) {
-	log.Info(r.RemoteAddr, "Status request received")
-
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-	db := mongo_sess.DB("")
-
-	var task_count, worker_count int
-	var err error
-	if task_count, err = Count(db.C("flamenco_tasks")); err != nil {
-		fmt.Printf("ERROR : %s\n", err.Error())
-		return
-	}
-	if worker_count, err = Count(db.C("flamenco_workers")); err != nil {
-		fmt.Printf("ERROR : %s\n", err.Error())
-		return
-	}
-
-	w.Header().Set("Content-Type", "application/json")
-	w.Header().Set("Cache-Control", "no-cache")
-	w.Header().Set("Connection", "close")
-
-	statusreport := StatusReport{
-		worker_count,
-		task_count,
-		flamenco_version,
-	}
-
-	encoder := json.NewEncoder(w)
-	encoder.Encode(statusreport)
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_timeout_check.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_timeout_check.go
deleted file mode 100644
index 5b9941c8e51c6b0b15f76edec73cf8be1008638b..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_timeout_check.go
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Checks active tasks to see if their worker is still alive & running.
- */
-package flamenco
-
-import (
-	"fmt"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	mgo "gopkg.in/mgo.v2"
-)
-
-// Interval for checking all active tasks for timeouts.
-const TASK_TIMEOUT_CHECK_INTERVAL = 5 * time.Second
-const TASK_TIMEOUT_CHECK_INITIAL_SLEEP = 5 * time.Minute
-
-type TaskTimeoutChecker struct {
-	closable
-	config  *Conf
-	session *mgo.Session
-}
-
-func CreateTaskTimeoutChecker(config *Conf, session *mgo.Session) *TaskTimeoutChecker {
-	return &TaskTimeoutChecker{
-		makeClosable(),
-		config, session,
-	}
-}
-
-func (self *TaskTimeoutChecker) Go() {
-	session := self.session.Copy()
-	defer session.Close()
-	db := session.DB("")
-
-	self.closableAdd(1)
-	defer self.closableDone()
-	defer log.Info("TaskTimeoutChecker: shutting down.")
-
-	// Start with a delay, so that workers get a chance to push their updates
-	// after the manager has started up.
-	ok := KillableSleep("TaskTimeoutChecker-initial", TASK_TIMEOUT_CHECK_INITIAL_SLEEP, &self.closable)
-	if !ok {
-		log.Info("TaskTimeoutChecker: Killable sleep was killed, not even starting checker.")
-		return
-	}
-
-	timer := Timer("TaskTimeoutCheck", TASK_TIMEOUT_CHECK_INTERVAL, false, &self.closable)
-
-	for _ = range timer {
-		self.Check(db)
-	}
-
-}
-
-func (self *TaskTimeoutChecker) Close() {
-	self.closableCloseAndWait()
-	log.Debug("TaskTimeoutChecker: shutdown complete.")
-}
-
-func (self *TaskTimeoutChecker) Check(db *mgo.Database) {
-	timeout_threshold := UtcNow().Add(-self.config.ActiveTaskTimeoutInterval)
-	log.Debugf("Failing all active tasks that have not been touched since %s", timeout_threshold)
-
-	var timedout_tasks []Task
-	// find all active tasks that either have never been pinged, or were pinged long ago.
-	query := M{
-		"status": "active",
-		"$or": []M{
-			M{"last_worker_ping": M{"$lte": timeout_threshold}},
-			M{"last_worker_ping": M{"$exists": false}},
-		},
-	}
-	projection := M{
-		"_id":              1,
-		"last_worker_ping": 1,
-		"worker_id":        1,
-		"worker":           1,
-		"name":             1,
-	}
-	if err := db.C("flamenco_tasks").Find(query).Select(projection).All(&timedout_tasks); err != nil {
-		log.Warningf("Error finding timed-out tasks: %s", err)
-	}
-
-	for _, task := range timedout_tasks {
-		log.Warningf("    - Task %s (%s) timed out", task.Name, task.ID.Hex())
-		var ident string
-		if task.Worker != "" {
-			ident = task.Worker
-		} else if task.WorkerID != nil {
-			ident = task.WorkerID.Hex()
-		} else {
-			ident = "-no worker-"
-		}
-
-		tupdate := TaskUpdate{
-			TaskID:     task.ID,
-			TaskStatus: "failed",
-			Activity:   fmt.Sprintf("Task timed out on worker %s", ident),
-			Log: fmt.Sprintf(
-				"%s Task %s (%s) timed out, was active but untouched since %s. "+
-					"Was handled by worker %s",
-				UtcNow().Format(IsoFormat), task.Name, task.ID.Hex(), task.LastWorkerPing, ident),
-		}
-		QueueTaskUpdate(&tupdate, db)
-	}
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates.go
deleted file mode 100644
index 80b4ce15050c72f5c397f3e654fe26a3605e4fe4..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates.go
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Receives task updates from workers, queues them, and forwards them to the Flamenco Server.
- */
-package flamenco
-
-import (
-	"fmt"
-	"net/http"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	auth "github.com/abbot/go-http-auth"
-
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-const QUEUE_MGO_COLLECTION = "task_update_queue"
-const TASK_QUEUE_INSPECT_PERIOD = 1 * time.Second
-
-type TaskUpdatePusher struct {
-	closable
-	config   *Conf
-	upstream *UpstreamConnection
-	session  *mgo.Session
-}
-
-/**
- * Receives a task update from a worker, and queues it for sending to Flamenco Server.
- */
-func QueueTaskUpdateFromWorker(w http.ResponseWriter, r *auth.AuthenticatedRequest,
-	db *mgo.Database, task_id bson.ObjectId) {
-
-	// Get the worker
-	worker, err := FindWorker(r.Username, bson.M{"address": 1, "nickname": 1}, db)
-	if err != nil {
-		log.Warningf("QueueTaskUpdate: Unable to find worker %s at address: %s",
-			r.Username, r.RemoteAddr, err)
-		w.WriteHeader(http.StatusForbidden)
-		fmt.Fprintf(w, "Unable to find worker address: %s", err)
-		return
-	}
-	WorkerSeen(worker, r.RemoteAddr, db)
-	log.Infof("QueueTaskUpdateFromWorker: Received task update for task %s from %s",
-		task_id.Hex(), worker.Identifier())
-
-	// Parse the task JSON
-	tupdate := TaskUpdate{}
-	defer r.Body.Close()
-	if err := DecodeJson(w, r.Body, &tupdate, fmt.Sprintf("%s QueueTaskUpdate:", worker.Identifier())); err != nil {
-		return
-	}
-	tupdate.TaskID = task_id
-	tupdate.Worker = worker.Identifier()
-
-	// Check that this worker is allowed to update this task.
-	task := Task{}
-	if err := db.C("flamenco_tasks").FindId(task_id).One(&task); err != nil {
-		log.Warningf("%s QueueTaskUpdateFromWorker: unable to find task %s for worker %s",
-			r.RemoteAddr, task_id.Hex(), worker.Identifier())
-		w.WriteHeader(http.StatusNotFound)
-		fmt.Fprintf(w, "Task %s is unknown.", task_id.Hex())
-		return
-	}
-	if task.WorkerID != nil && *task.WorkerID != worker.ID {
-		log.Warningf("%s QueueTaskUpdateFromWorker: task %s update rejected from %s (%s), task is assigned to %s",
-			r.RemoteAddr, task_id.Hex(), worker.ID.Hex(), worker.Identifier(), task.WorkerID.Hex())
-		w.WriteHeader(http.StatusConflict)
-		fmt.Fprintf(w, "Task %s is assigned to another worker.", task_id.Hex())
-		return
-	}
-
-	// Only set the task's worker.ID if it's not already set to the current worker.
-	var setWorkerID *bson.ObjectId
-	if task.WorkerID == nil {
-		setWorkerID = &worker.ID
-	}
-	WorkerPingedTask(setWorkerID, tupdate.TaskID, db)
-
-	if err := QueueTaskUpdate(&tupdate, db); err != nil {
-		log.Warningf("%s: %s", worker.Identifier(), err)
-		w.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(w, "Unable to store update: %s\n", err)
-		return
-	}
-
-	w.WriteHeader(204)
-}
-
-func QueueTaskUpdate(tupdate *TaskUpdate, db *mgo.Database) error {
-	return QueueTaskUpdateWithExtra(tupdate, db, bson.M{})
-}
-
-/* Same as QueueTaskUpdate(), but with extra updates to be performed on the local flamenco_tasks
- * collection.
- */
-func QueueTaskUpdateWithExtra(tupdate *TaskUpdate, db *mgo.Database, extra_updates bson.M) error {
-	// For ensuring the ordering of updates. time.Time has nanosecond precision.
-	tupdate.ReceivedOnManager = time.Now().UTC()
-	tupdate.ID = bson.NewObjectId()
-
-	// Store the update in the queue for sending to the Flamenco Server later.
-	task_update_queue := db.C(QUEUE_MGO_COLLECTION)
-	if err := task_update_queue.Insert(&tupdate); err != nil {
-		return fmt.Errorf("QueueTaskUpdate: error inserting task update in queue: %s", err)
-	}
-
-	// Locally apply the change to our cached version of the task too, if it is a valid transition.
-	// This prevents a task being reported active on the worker from overwriting the
-	// cancel-requested state we received from the Server.
-	task_coll := db.C("flamenco_tasks")
-	updates := extra_updates
-	if tupdate.TaskStatus != "" {
-		// Before blindly applying the task status, first check if the transition is valid.
-		if TaskStatusTransitionValid(task_coll, tupdate.TaskID, tupdate.TaskStatus) {
-			updates["status"] = tupdate.TaskStatus
-		} else {
-			log.Warningf("QueueTaskUpdate: not locally applying status=%s for %s",
-				tupdate.TaskStatus, tupdate.TaskID.Hex())
-		}
-	}
-	if tupdate.Activity != "" {
-		updates["activity"] = tupdate.Activity
-	}
-	if len(updates) > 0 {
-		log.Debugf("QueueTaskUpdate: applying update %s to task %s", updates, tupdate.TaskID.Hex())
-		if err := task_coll.UpdateId(tupdate.TaskID, bson.M{"$set": updates}); err != nil {
-			if err != mgo.ErrNotFound {
-				return fmt.Errorf("QueueTaskUpdate: error updating local task cache: %s", err)
-			} else {
-				log.Warningf("QueueTaskUpdate: cannot find task %s to update locally", tupdate.TaskID.Hex())
-			}
-		}
-	} else {
-		log.Debugf("QueueTaskUpdate: nothing to do locally for task %s", tupdate.TaskID.Hex())
-	}
-
-	return nil
-}
-
-/**
- * Performs a query on the database to determine the current status, then checks whether
- * the new status is acceptable.
- */
-func TaskStatusTransitionValid(task_coll *mgo.Collection, task_id bson.ObjectId, new_status string) bool {
-	/* The only actual test we do is when the transition is from cancel-requested
-	   to something else. If the new status is valid for cancel-requeted, we don't
-	   even need to go to the database to fetch the current status. */
-	if ValidForCancelRequested(new_status) {
-		return true
-	}
-
-	task_curr := Task{}
-	if err := task_coll.FindId(task_id).Select(bson.M{"status": 1}).One(&task_curr); err != nil {
-		log.Warningf("Unable to find task %s - not accepting status update to %s", err, new_status)
-		return false
-	}
-
-	// We already know the new status is not valid for cancel-requested.
-	// All other statuses are fine, though.
-	return task_curr.Status != "cancel-requested"
-}
-
-func ValidForCancelRequested(new_status string) bool {
-	// Valid statuses to which a task can go after being cancel-requested
-	valid_statuses := map[string]bool{
-		"canceled":  true, // the expected case
-		"failed":    true, // it may have failed on the worker before it could be canceled
-		"completed": true, // it may have completed on the worker before it could be canceled
-	}
-
-	valid, found := valid_statuses[new_status]
-	return valid && found
-}
-
-func CreateTaskUpdatePusher(config *Conf, upstream *UpstreamConnection, session *mgo.Session) *TaskUpdatePusher {
-	return &TaskUpdatePusher{
-		makeClosable(),
-		config,
-		upstream,
-		session,
-	}
-}
-
-/**
- * Closes the task update pusher by stopping all timers & goroutines.
- */
-func (self *TaskUpdatePusher) Close() {
-	log.Info("TaskUpdatePusher: shutting down, waiting for shutdown to complete.")
-	self.closableCloseAndWait()
-	log.Info("TaskUpdatePusher: shutdown complete.")
-}
-
-func (self *TaskUpdatePusher) Go() {
-	log.Info("TaskUpdatePusher: Starting")
-	mongo_sess := self.session.Copy()
-	defer mongo_sess.Close()
-
-	var last_push time.Time
-	db := mongo_sess.DB("")
-	queue := db.C(QUEUE_MGO_COLLECTION)
-
-	if !self.closableAdd(1) {
-		return
-	}
-	defer self.closableDone()
-
-	// Investigate the queue periodically.
-	timer_chan := Timer("TaskUpdatePusherTimer",
-		TASK_QUEUE_INSPECT_PERIOD, false, &self.closable)
-
-	for _ = range timer_chan {
-		// log.Info("TaskUpdatePusher: checking task update queue")
-		update_count, err := Count(queue)
-		if err != nil {
-			log.Warningf("TaskUpdatePusher: ERROR checking queue: %s", err)
-			continue
-		}
-
-		time_since_last_push := time.Now().Sub(last_push)
-		may_regular_push := update_count > 0 &&
-			(update_count >= self.config.TaskUpdatePushMaxCount ||
-				time_since_last_push >= self.config.TaskUpdatePushMaxInterval)
-		may_empty_push := time_since_last_push >= self.config.CancelTaskFetchInterval
-		if !may_regular_push && !may_empty_push {
-			continue
-		}
-
-		// Time to push!
-		if update_count > 0 {
-			log.Debugf("TaskUpdatePusher: %d updates are queued", update_count)
-		}
-		if err := self.push(db); err != nil {
-			log.Warning("TaskUpdatePusher: unable to push to upstream Flamenco Server: ", err)
-			continue
-		}
-
-		// Only remember we've pushed after it was succesful.
-		last_push = time.Now()
-	}
-}
-
-/**
- * Push task updates to the queue, and handle the response.
- * This response can include a list of task IDs to cancel.
- *
- * NOTE: this function assumes there is only one thread/process doing the pushing,
- * and that we can safely leave documents in the queue until they have been pushed. */
-func (self *TaskUpdatePusher) push(db *mgo.Database) error {
-	var result []TaskUpdate
-
-	queue := db.C(QUEUE_MGO_COLLECTION)
-
-	// Figure out what to send.
-	query := queue.Find(bson.M{}).Limit(self.config.TaskUpdatePushMaxCount)
-	if err := query.All(&result); err != nil {
-		return err
-	}
-
-	// Perform the sending.
-	if len(result) > 0 {
-		log.Infof("TaskUpdatePusher: pushing %d updates to upstream Flamenco Server", len(result))
-	} else {
-		log.Debugf("TaskUpdatePusher: pushing %d updates to upstream Flamenco Server", len(result))
-	}
-	response, err := self.upstream.SendTaskUpdates(&result)
-	if err != nil {
-		// TODO Sybren: implement some exponential backoff when things fail to get sent.
-		return err
-	}
-
-	if len(response.HandledUpdateIds) != len(result) {
-		log.Warningf("TaskUpdatePusher: server accepted %d of %d items.",
-			len(response.HandledUpdateIds), len(result))
-	}
-
-	// If succesful, remove the accepted updates from the queue.
-	/* If there is an error, don't return just yet - we also want to cancel any task
-	   that needs cancelling. */
-	var err_unqueue error = nil
-	if len(response.HandledUpdateIds) > 0 {
-		_, err_unqueue = queue.RemoveAll(bson.M{"_id": bson.M{"$in": response.HandledUpdateIds}})
-	}
-	err_cancel := self.handle_incoming_cancel_requests(response.CancelTasksIds, db)
-
-	if err_unqueue != nil {
-		log.Warningf("TaskUpdatePusher: This is awkward; we have already sent the task updates "+
-			"upstream, but now we cannot un-queue them. Expect duplicates: %s", err)
-		return err_unqueue
-	}
-
-	return err_cancel
-}
-
-/**
- * Handles the canceling of tasks, as mentioned in the task batch update response.
- */
-func (self *TaskUpdatePusher) handle_incoming_cancel_requests(cancel_task_ids []bson.ObjectId, db *mgo.Database) error {
-	if len(cancel_task_ids) == 0 {
-		return nil
-	}
-
-	log.Infof("TaskUpdatePusher: canceling %d tasks", len(cancel_task_ids))
-	tasks_coll := db.C("flamenco_tasks")
-
-	// Fetch all to-be-canceled tasks
-	var tasks_to_cancel []Task
-	err := tasks_coll.Find(bson.M{
-		"_id": bson.M{"$in": cancel_task_ids},
-	}).Select(bson.M{
-		"_id":    1,
-		"status": 1,
-	}).All(&tasks_to_cancel)
-	if err != nil {
-		log.Warningf("TaskUpdatePusher: ERROR unable to fetch tasks: %s", err)
-		return err
-	}
-
-	// Remember which tasks we actually have seen, so we know which ones we don't have cached.
-	canceled_count := 0
-	seen_tasks := map[bson.ObjectId]bool{}
-	go_to_cancel_requested := make([]bson.ObjectId, 0, len(cancel_task_ids))
-
-	queue_task_cancel := func(task_id bson.ObjectId) {
-		tupdate := TaskUpdate{
-			TaskID:     task_id,
-			TaskStatus: "canceled",
-		}
-		if err := QueueTaskUpdate(&tupdate, db); err != nil {
-			log.Warningf("TaskUpdatePusher: Unable to queue task update for canceled task %s, "+
-				"expect the task to hang in cancel-requested state.", task_id)
-		} else {
-			canceled_count++
-		}
-	}
-
-	for _, task_to_cancel := range tasks_to_cancel {
-		seen_tasks[task_to_cancel.ID] = true
-
-		if task_to_cancel.Status == "active" {
-			// This needs to be canceled through the worker, and thus go to cancel-requested.
-			go_to_cancel_requested = append(go_to_cancel_requested, task_to_cancel.ID)
-		} else {
-			queue_task_cancel(task_to_cancel.ID)
-		}
-	}
-
-	// Mark tasks as cancel-requested.
-	update_info, err := tasks_coll.UpdateAll(
-		bson.M{"_id": bson.M{"$in": go_to_cancel_requested}},
-		bson.M{"$set": bson.M{"status": "cancel-requested"}},
-	)
-	if err != nil {
-		log.Warningf("TaskUpdatePusher: unable to mark tasks as cancel-requested: %s", err)
-	} else {
-		log.Infof("TaskUpdatePusher: marked %d tasks as cancel-requested: %s",
-			update_info.Matched, go_to_cancel_requested)
-	}
-
-	// Just push a "canceled" update to the Server about tasks we know nothing about.
-	for _, task_id := range cancel_task_ids {
-		seen, _ := seen_tasks[task_id]
-		if seen {
-			continue
-		}
-		log.Warningf("TaskUpdatePusher: unknown task: %s", task_id.Hex())
-		queue_task_cancel(task_id)
-	}
-
-	log.Infof("TaskUpdatePusher: marked %d tasks as canceled", canceled_count)
-
-	if update_info.Matched+canceled_count < len(cancel_task_ids) {
-		log.Warningf("TaskUpdatePusher: I was unable to cancel %d tasks for some reason.",
-			len(cancel_task_ids)-(update_info.Matched+canceled_count))
-	}
-
-	return err
-}
-
-func LogTaskActivity(worker *Worker, task_id bson.ObjectId, activity, log_line string, db *mgo.Database) {
-	tupdate := TaskUpdate{
-		TaskID:   task_id,
-		Activity: activity,
-		Log:      log_line,
-	}
-	if err := QueueTaskUpdate(&tupdate, db); err != nil {
-		log.Errorf("LogTaskActivity: Unable to queue task(%s) update for worker %s: %s",
-			task_id.Hex(), worker.Identifier(), err)
-	}
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates_test.go
deleted file mode 100644
index 6f17811ae58b87a31045da8f17ab7aaf95a38f51..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/task_updates_test.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package flamenco
-
-import (
-	"bytes"
-	"encoding/json"
-	"net/http"
-	"time"
-
-	"github.com/stretchr/testify/assert"
-
-	log "github.com/Sirupsen/logrus"
-	check "gopkg.in/check.v1"
-	"gopkg.in/jarcoal/httpmock.v1"
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-type TaskUpdatesTestSuite struct {
-	config   Conf
-	session  *mgo.Session
-	db       *mgo.Database
-	upstream *UpstreamConnection
-}
-
-var _ = check.Suite(&TaskUpdatesTestSuite{})
-
-func (s *TaskUpdatesTestSuite) SetUpTest(c *check.C) {
-	httpmock.Activate()
-
-	s.config = GetTestConfig()
-	s.session = MongoSession(&s.config)
-	s.db = s.session.DB("")
-	s.upstream = ConnectUpstream(&s.config, s.session)
-}
-
-func (s *TaskUpdatesTestSuite) TearDownTest(c *check.C) {
-	log.Info("SchedulerTestSuite tearing down test, dropping database.")
-	s.upstream.Close()
-	s.db.DropDatabase()
-	httpmock.DeactivateAndReset()
-}
-
-func (s *TaskUpdatesTestSuite) TestCancelRunningTasks(t *check.C) {
-	tasks_coll := s.db.C("flamenco_tasks")
-
-	task1 := ConstructTestTask("1aaaaaaaaaaaaaaaaaaaaaaa", "testing")
-	if err := tasks_coll.Insert(task1); err != nil {
-		t.Fatal("Unable to insert test task", err)
-	}
-	task2 := ConstructTestTask("2aaaaaaaaaaaaaaaaaaaaaaa", "sleeping")
-	if err := tasks_coll.Insert(task2); err != nil {
-		t.Fatal("Unable to insert test task 2", err)
-	}
-
-	timeout := TimeoutAfter(1 * time.Second)
-	defer close(timeout)
-
-	// Mock that the task with highest priority was actually canceled on the Server.
-	httpmock.RegisterResponder(
-		"POST",
-		"http://localhost:51234/api/flamenco/managers/5852bc5198377351f95d103e/task-update-batch",
-		func(req *http.Request) (*http.Response, error) {
-			defer func() { timeout <- false }()
-			log.Info("POST from manager received on server, sending back TaskUpdateResponse.")
-
-			resp := TaskUpdateResponse{
-				CancelTasksIds: []bson.ObjectId{task2.ID},
-			}
-			return httpmock.NewJsonResponse(200, &resp)
-		},
-	)
-
-	// Set up some decent timeouts so we don't have to wait forevah.
-	s.config.TaskUpdatePushMaxInterval = 30 * time.Second
-	s.config.TaskUpdatePushMaxCount = 4000
-	s.config.CancelTaskFetchInterval = 300 * time.Millisecond
-
-	tup := CreateTaskUpdatePusher(&s.config, s.upstream, s.session)
-	defer tup.Close()
-
-	go tup.Go()
-
-	timedout := <-timeout
-	assert.False(t, timedout, "HTTP POST to Flamenco Server not performed")
-
-	// Give the tup.Go() coroutine (and subsequent calls) time to run.
-	// the "timeout <- false" call in the responder is triggered before
-	// that function is done working.
-	time.Sleep(100 * time.Millisecond)
-
-	// Check that one task was canceled and the other was not.
-	task_db := Task{}
-	assert.Nil(t, tasks_coll.FindId(task1.ID).One(&task_db))
-	assert.Equal(t, "queued", task_db.Status)
-	assert.Nil(t, tasks_coll.FindId(task2.ID).One(&task_db))
-	assert.Equal(t, "canceled", task_db.Status)
-}
-
-func (s *TaskUpdatesTestSuite) TestMultipleWorkersForOneTask(c *check.C) {
-	tasks_coll := s.db.C("flamenco_tasks")
-
-	task1 := ConstructTestTask("1aaaaaaaaaaaaaaaaaaaaaaa", "testing")
-	assert.Nil(c, tasks_coll.Insert(task1))
-
-	worker1 := Worker{
-		Platform:          "linux",
-		SupportedJobTypes: []string{"testing"},
-	}
-	worker2 := Worker{
-		Platform:          "linux",
-		SupportedJobTypes: []string{"testing"},
-	}
-	assert.Nil(c, StoreNewWorker(&worker1, s.db))
-	assert.Nil(c, StoreNewWorker(&worker2, s.db))
-
-	// Task should not be assigned to any worker
-	assert.Nil(c, task1.WorkerID)
-
-	tupdate := TaskUpdate{
-		TaskID:   task1.ID,
-		Activity: "doing stuff by worker1",
-	}
-	payload_bytes, err := json.Marshal(tupdate)
-	assert.Nil(c, err)
-	resp_rec, ar := WorkerTestRequestWithBody(worker1.ID, bytes.NewBuffer(payload_bytes), "POST", "/tasks/1aaaaaaaaaaaaaaaaaaaaaaa/update")
-	QueueTaskUpdateFromWorker(resp_rec, ar, s.db, task1.ID)
-	assert.Equal(c, 204, resp_rec.Code)
-
-	// Because of this update, the task should be assigned to worker 1
-	assert.Nil(c, tasks_coll.FindId(task1.ID).One(&task1))
-	assert.Equal(c, task1.WorkerID, task1.WorkerID)
-	assert.Equal(c, task1.Activity, "doing stuff by worker1")
-
-	// An update by worker 2 should fail.
-	tupdate.Activity = "doing stuff by worker2"
-	payload_bytes, err = json.Marshal(tupdate)
-	assert.Nil(c, err)
-	resp_rec, ar = WorkerTestRequestWithBody(worker2.ID, bytes.NewBuffer(payload_bytes), "POST", "/tasks/1aaaaaaaaaaaaaaaaaaaaaaa/update")
-	QueueTaskUpdateFromWorker(resp_rec, ar, s.db, task1.ID)
-	assert.Equal(c, http.StatusConflict, resp_rec.Code)
-
-	// The task should still be assigned to worker 1
-	assert.Nil(c, tasks_coll.FindId(task1.ID).One(&task1))
-	assert.Equal(c, task1.WorkerID, task1.WorkerID)
-	assert.Equal(c, task1.Activity, "doing stuff by worker1")
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/timer.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/timer.go
deleted file mode 100644
index f07f47c5a04795029d077268c3c59f583e71ba50..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/timer.go
+++ /dev/null
@@ -1,114 +0,0 @@
-package flamenco
-
-import (
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-)
-
-type TimerPing struct{}
-
-/**
- * Generic timer for periodic signals.
- *
- * :param sleep_first: if true: sleep first, then ping. If false: ping first, then sleep.
- */
-func Timer(name string, sleep_duration time.Duration, sleep_first bool, closable *closable) <-chan TimerPing {
-	timer_chan := make(chan TimerPing, 1) // don't let the timer block
-
-	go func() {
-		if !closable.closableAdd(1) {
-			log.Infof("Timer '%s' goroutine shutting down.", name)
-			return
-		}
-		defer closable.closableDone()
-		defer close(timer_chan)
-
-		last_timer := time.Time{}
-		if sleep_first {
-			last_timer = time.Now()
-		}
-
-		for {
-			select {
-			case <-closable.doneChan:
-				log.Infof("Timer '%s' goroutine shutting down.", name)
-				return
-			default:
-				// Only sleep a little bit, so that we can check 'done' quite often.
-				time.Sleep(50 * time.Millisecond)
-			}
-
-			now := time.Now()
-			if now.Sub(last_timer) > sleep_duration {
-				// Timeout occurred
-				last_timer = now
-				timer_chan <- TimerPing{}
-			}
-		}
-	}()
-
-	return timer_chan
-}
-
-/**
- * Sleep that can be killed by closing the "done_chan" channel.
- *
- * :returns: "ok", so true when the sleep stopped normally, and false if it was killed.
- */
-func KillableSleep(name string, sleep_duration time.Duration, closable *closable) bool {
-
-	if !closable.closableAdd(1) {
-		return false
-	}
-	defer closable.closableDone()
-	defer log.Infof("Sleep '%s' goroutine is shut down.", name)
-
-	sleep_start := time.Now()
-	for {
-		select {
-		case <-closable.doneChan:
-			log.Infof("Sleep '%s' goroutine shutting down.", name)
-			return false
-		default:
-			// Only sleep a little bit, so that we can check 'done' quite often.
-			time.Sleep(50 * time.Millisecond)
-		}
-
-		now := time.Now()
-		if now.Sub(sleep_start) > sleep_duration {
-			// Timeout occurred
-			break
-		}
-	}
-
-	return true
-}
-
-func UtcNow() *time.Time {
-	now := time.Now().UTC()
-	return &now
-}
-
-/* TimeoutAfter: Sends a 'true' to the channel after the given timeout.
- * Send a 'false' to the channel yourself if you want to notify the receiver that
- * a timeout didn't happen.
- *
- * The channel is buffered with size 2, so both your 'false' and this routine's 'true'
- * write won't block.
- */
-func TimeoutAfter(duration time.Duration) chan bool {
-	timeout := make(chan bool, 2)
-
-	go func() {
-		time.Sleep(duration)
-		defer func() {
-			// Recover from a panic. This panic can happen when the caller closed the
-			// channel while we were sleeping.
-			recover()
-		}()
-		timeout <- true
-	}()
-
-	return timeout
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream.go
deleted file mode 100644
index 9167dc6674c5034af9f220bef56bef252c2d786d..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream.go
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- * Periodically fetches new tasks from the Flamenco Server, and sends updates back.
- */
-package flamenco
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-// Gives the system some time to start up (and open listening HTTP port)
-const STARTUP_NOTIFICATION_INITIAL_DELAY = 500 * time.Millisecond
-
-// Duration between consecutive retries of sending the startup notification.
-const STARTUP_NOTIFICATION_RETRY = 30 * time.Second
-
-type UpstreamConnection struct {
-	closable
-	config  *Conf
-	session *mgo.Session
-
-	// Send any boolean here to kick the task downloader into downloading new tasks.
-	download_kick chan chan bool
-}
-
-func ConnectUpstream(config *Conf, session *mgo.Session) *UpstreamConnection {
-	upconn := UpstreamConnection{
-		makeClosable(),
-		config,
-		session,
-		make(chan chan bool),
-	}
-	upconn.download_task_loop()
-
-	return &upconn
-}
-
-/**
- * Closes the upstream connection by stopping all upload/download loops.
- */
-func (self *UpstreamConnection) Close() {
-	log.Debugf("UpstreamConnection: shutting down, waiting for shutdown to complete.")
-	close(self.download_kick) // TODO: maybe move this between closing of done channel and waiting
-	self.closableCloseAndWait()
-	log.Info("UpstreamConnection: shutdown complete.")
-}
-
-func (self *UpstreamConnection) KickDownloader(synchronous bool) {
-	if synchronous {
-		pingback := make(chan bool)
-		self.download_kick <- pingback
-		log.Info("KickDownloader: Waiting for task downloader to finish.")
-
-		// wait for the download to be complete, or the connection to be shut down.
-		if !self.closableAdd(1) {
-			log.Debugf("KickDownloader: Aborting waiting for task downloader; shutting down.")
-			return
-		}
-		defer self.closableDone()
-
-		for {
-			select {
-			case <-pingback:
-				log.Debugf("KickDownloader: done.")
-				return
-			case <-self.doneChan:
-				log.Debugf("KickDownloader: Aborting waiting for task downloader; shutting down.")
-				return
-			}
-		}
-	} else {
-		log.Debugf("KickDownloader: asynchronous kick, just kicking.")
-		self.download_kick <- nil
-	}
-}
-
-func (self *UpstreamConnection) download_task_loop() {
-	timer_chan := Timer("download_task_loop",
-		self.config.DownloadTaskSleep,
-		false,
-		&self.closable,
-	)
-
-	go func() {
-		mongo_sess := self.session.Copy()
-		defer mongo_sess.Close()
-
-		if !self.closableAdd(1) {
-			return
-		}
-		defer self.closableDone()
-		defer log.Info("download_task_loop: Task download goroutine shutting down.")
-
-		for {
-			select {
-			case <-self.doneChan:
-				return
-			case _, ok := <-timer_chan:
-				if !ok {
-					return
-				}
-				log.Info("download_task_loop: Going to fetch tasks due to periodic timeout.")
-				download_tasks_from_upstream(self.config, mongo_sess)
-			case pingback_chan, ok := <-self.download_kick:
-				if !ok {
-					return
-				}
-				log.Info("download_task_loop: Going to fetch tasks due to kick.")
-				download_tasks_from_upstream(self.config, mongo_sess)
-				if pingback_chan != nil {
-					pingback_chan <- true
-				}
-			}
-		}
-	}()
-}
-
-/**
- * Downloads a chunkn of tasks from the upstream Flamenco Server.
- */
-func download_tasks_from_upstream(config *Conf, mongo_sess *mgo.Session) {
-	db := mongo_sess.DB("")
-
-	url_str := fmt.Sprintf("/api/flamenco/managers/%s/depsgraph", config.ManagerId)
-	rel_url, err := url.Parse(url_str)
-	if err != nil {
-		log.Warningf("Error parsing '%s' as URL; unable to fetch tasks.", url_str)
-		return
-	}
-
-	get_url := config.Flamenco.ResolveReference(rel_url)
-	req, err := http.NewRequest("GET", get_url.String(), nil)
-	if err != nil {
-		log.Warningf("Unable to create GET request: %s", err)
-		return
-	}
-	req.SetBasicAuth(config.ManagerSecret, "")
-
-	// Set If-Modified-Since header on our request.
-	settings := GetSettings(db)
-	if settings.DepsgraphLastModified != nil {
-		log.Infof("Getting tasks from upstream Flamenco %s If-Modified-Since %s", get_url,
-			*settings.DepsgraphLastModified)
-		req.Header.Set("X-Flamenco-If-Updated-Since", *settings.DepsgraphLastModified)
-	} else {
-		log.Infof("Getting tasks from upstream Flamenco %s", get_url)
-	}
-
-	client := &http.Client{}
-	resp, err := client.Do(req)
-	if err != nil {
-		log.Warningf("Unable to GET %s: %s", get_url, err)
-		return
-	}
-	if resp.StatusCode == http.StatusNotModified {
-		log.Debug("Server-side depsgraph was not modified, nothing to do.")
-		return
-	}
-	if resp.StatusCode == http.StatusNoContent {
-		log.Info("No tasks for us; sleeping.")
-		return
-	}
-	if resp.StatusCode >= 300 {
-		body, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			log.Errorf("Error %d GETing %s: %s", resp.StatusCode, get_url, err)
-			return
-		}
-		log.Errorf("Error %d GETing %s: %s", resp.StatusCode, get_url, body)
-		return
-	}
-
-	// Parse the received tasks.
-	var scheduled_tasks ScheduledTasks
-	decoder := json.NewDecoder(resp.Body)
-	defer resp.Body.Close()
-
-	if err = decoder.Decode(&scheduled_tasks); err != nil {
-		log.Warning("Unable to decode scheduled tasks JSON:", err)
-		return
-	}
-
-	// Insert them into the MongoDB
-	depsgraph := scheduled_tasks.Depsgraph
-	if len(depsgraph) > 0 {
-		log.Infof("Received %d tasks from upstream Flamenco Server.", len(depsgraph))
-	} else {
-		// This shouldn't happen, as it should actually have been a 204 or 306.
-		log.Debugf("Received %d tasks from upstream Flamenco Server.", len(depsgraph))
-	}
-	tasks_coll := db.C("flamenco_tasks")
-	for _, task := range depsgraph {
-		change, err := tasks_coll.Upsert(bson.M{"_id": task.ID}, task)
-		if err != nil {
-			log.Errorf("unable to insert new task %s: %s", task.ID.Hex(), err)
-			continue
-		}
-
-		if change.Updated > 0 {
-			log.Debug("Upstream server re-queued existing task ", task.ID.Hex())
-		} else if change.Matched > 0 {
-			log.Debugf("Upstream server re-queued existing task %s, but nothing changed",
-				task.ID.Hex())
-		}
-	}
-
-	// Check if we had a Last-Modified header, since we need to remember that.
-	last_modified := resp.Header.Get("X-Flamenco-Last-Updated")
-	if last_modified != "" {
-		log.Info("Last modified task was at ", last_modified)
-		settings.DepsgraphLastModified = &last_modified
-		SaveSettings(db, settings)
-	}
-}
-
-func (self *UpstreamConnection) ResolveUrl(relative_url string, a ...interface{}) (*url.URL, error) {
-	rel_url, err := url.Parse(fmt.Sprintf(relative_url, a...))
-	if err != nil {
-		return &url.URL{}, err
-	}
-	url := self.config.Flamenco.ResolveReference(rel_url)
-
-	return url, nil
-}
-
-func (self *UpstreamConnection) SendJson(logprefix, method string, url *url.URL,
-	payload interface{},
-	responsehandler func(resp *http.Response, body []byte) error,
-) error {
-	authenticate := func(req *http.Request) {
-		req.SetBasicAuth(self.config.ManagerSecret, "")
-	}
-
-	return SendJson(logprefix, method, url, payload, authenticate, responsehandler)
-}
-
-/**
- * Sends a StartupNotification document to upstream Flamenco Server.
- * Keeps trying in a goroutine until the notification was succesful.
- */
-func (self *UpstreamConnection) SendStartupNotification() {
-
-	notification := StartupNotification{
-		ManagerURL:         self.config.OwnUrl,
-		VariablesByVarname: self.config.VariablesByVarname,
-		NumberOfWorkers:    0,
-	}
-
-	url, err := self.ResolveUrl("/api/flamenco/managers/%s/startup", self.config.ManagerId)
-	if err != nil {
-		panic(fmt.Sprintf("SendStartupNotification: unable to construct URL: %s\n", err))
-	}
-
-	// Performs the actual sending.
-	send_startup_notification := func(mongo_sess *mgo.Session) error {
-		notification.NumberOfWorkers = WorkerCount(mongo_sess.DB(""))
-
-		err := self.SendJson("SendStartupNotification", "POST", url, &notification, nil)
-		if err != nil {
-			log.Warningf("SendStartupNotification: Unable to send: %s", err)
-			return err
-		}
-
-		log.Infof("SendStartupNotification: Done sending notification to upstream Flamenco")
-		return nil
-	}
-
-	go func() {
-		// Register as a loop that responds to 'done' being closed.
-		if !self.closableAdd(1) {
-			log.Warning("SendStartupNotification: shutting down early without sending startup notification.")
-			return
-		}
-		defer self.closableDone()
-
-		mongo_sess := self.session.Copy()
-		defer mongo_sess.Close()
-
-		ok := KillableSleep("SendStartupNotification-initial", STARTUP_NOTIFICATION_INITIAL_DELAY,
-			&self.closable)
-		if !ok {
-			log.Warning("SendStartupNotification: shutting down without sending startup notification.")
-			return
-		}
-		timer_chan := Timer("SendStartupNotification", STARTUP_NOTIFICATION_RETRY,
-			false, &self.closable)
-
-		for _ = range timer_chan {
-			log.Info("SendStartupNotification: trying to send notification.")
-			err := send_startup_notification(mongo_sess)
-			if err == nil {
-				return
-			}
-		}
-
-		log.Warning("SendStartupNotification: shutting down without succesfully sending notification.")
-	}()
-}
-
-/**
- * Performs a POST to /api/flamenco/managers/{manager-id}/task-update-batch to
- * send a batch of task updates to the Server.
- */
-func (self *UpstreamConnection) SendTaskUpdates(updates *[]TaskUpdate) (*TaskUpdateResponse, error) {
-	url, err := self.ResolveUrl("/api/flamenco/managers/%s/task-update-batch",
-		self.config.ManagerId)
-	if err != nil {
-		panic(fmt.Sprintf("SendTaskUpdates: unable to construct URL: %s\n", err))
-	}
-
-	response := TaskUpdateResponse{}
-	parse_response := func(resp *http.Response, body []byte) error {
-		err := json.Unmarshal(body, &response)
-		if err != nil {
-			log.Warningf("SendTaskUpdates: error parsing server response: %s", err)
-			return err
-		}
-		return nil
-	}
-	err = self.SendJson("SendTaskUpdates", "POST", url, updates, parse_response)
-
-	return &response, err
-}
-
-/**
- * Re-fetches a task from the Server, but only if its etag changed.
- * - If the etag changed, the differences between the old and new status are handled.
- * - If the Server cannot be reached, this error is ignored and the task is untouched.
- * - If the Server returns an error code other than 500 Internal Server Error,
- *   (Forbidden, Not Found, etc.) the task is removed from the local task queue.
- *
- * If the task was untouched, this function returns false.
- * If it was changed or removed, this function return true.
- */
-func (self *UpstreamConnection) RefetchTask(task *Task) bool {
-	get_url, err := self.ResolveUrl("/api/flamenco/tasks/%s", task.ID.Hex())
-	log.Infof("Verifying task with Flamenco Server %s", get_url)
-
-	req, err := http.NewRequest("GET", get_url.String(), nil)
-	if err != nil {
-		log.Errorf("WARNING: Unable to create GET request: %s", err)
-		return false
-	}
-	req.SetBasicAuth(self.config.ManagerSecret, "")
-	req.Header["If-None-Match"] = []string{task.Etag}
-
-	client := &http.Client{}
-	resp, err := client.Do(req)
-	if err != nil {
-		log.Warningf("Unable to re-fetch task: %s", err)
-		return false
-	}
-
-	if resp.StatusCode == http.StatusNotModified {
-		// Nothing changed, we're good to go.
-		log.Infof("Cached task %s is still the same on the Server", task.ID.Hex())
-		return false
-	}
-
-	if resp.StatusCode >= 500 {
-		// Internal errors, we'll ignore that.
-		log.Warningf("Error %d trying to re-fetch task %s",
-			resp.StatusCode, task.ID.Hex())
-		return false
-	}
-	if 300 <= resp.StatusCode && resp.StatusCode < 400 {
-		// Redirects, we'll ignore those too for now.
-		log.Warningf("Redirect %d trying to re-fetch task %s, not following redirect.",
-			resp.StatusCode, task.ID.Hex())
-		return false
-	}
-
-	// Either the task is gone (or gone-ish, i.e. 4xx code) or it has changed.
-	// If it is gone, we handle it as canceled.
-	new_task := Task{}
-
-	if resp.StatusCode >= 400 || resp.StatusCode == 204 {
-		// Not found, access denied, that kind of stuff. Locally cancel the task.
-		// TODO: probably better to go to "failed".
-		log.Warningf("Code %d when re-fetching task %s; canceling local copy",
-			resp.StatusCode, task.ID.Hex())
-
-		new_task = *task
-		new_task.Status = "canceled"
-	} else {
-		// Parse the new task we received.
-		decoder := json.NewDecoder(resp.Body)
-		defer resp.Body.Close()
-
-		if err = decoder.Decode(&new_task); err != nil {
-			// We can't decode what's being sent. Remove it from the queue, as we no longer know
-			// whether this task is valid at all.
-			log.Warningf("Unable to decode updated tasks JSON from %s: %s", get_url, err)
-
-			new_task = *task
-			new_task.Status = "canceled"
-		}
-	}
-
-	// save the task to the queue.
-	log.Infof("Cached task %s was changed on the Server, status=%s, priority=%d.",
-		task.ID.Hex(), new_task.Status, new_task.Priority)
-	tasks_coll := self.session.DB("").C("flamenco_tasks")
-	tasks_coll.UpdateId(task.ID,
-		bson.M{"$set": new_task})
-
-	return true
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream_test.go
deleted file mode 100644
index 43f363963d0d473bc2832a77137410287f5135d2..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/upstream_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package flamenco
-
-import (
-	"net/http"
-	"testing"
-	"time"
-
-	"github.com/stretchr/testify/assert"
-
-	log "github.com/Sirupsen/logrus"
-	httpmock "gopkg.in/jarcoal/httpmock.v1"
-)
-
-func TestStartupNotification(t *testing.T) {
-	config := GetTestConfig()
-	session := MongoSession(&config)
-
-	httpmock.Activate()
-	defer httpmock.DeactivateAndReset()
-
-	timeout := make(chan bool, 1)
-	go func() {
-		time.Sleep(STARTUP_NOTIFICATION_INITIAL_DELAY + 100*time.Millisecond)
-		timeout <- true
-	}()
-
-	httpmock.RegisterResponder(
-		"POST",
-		"http://localhost:51234/api/flamenco/managers/5852bc5198377351f95d103e/startup",
-		func(req *http.Request) (*http.Response, error) {
-			// TODO: test contents of request
-			log.Info("HTTP POST to Flamenco was performed.")
-			defer func() { timeout <- false }()
-			return httpmock.NewStringResponse(204, ""), nil
-		},
-	)
-
-	upstream := ConnectUpstream(&config, session)
-	defer upstream.Close()
-
-	upstream.SendStartupNotification()
-
-	timedout := <-timeout
-	assert.False(t, timedout, "HTTP POST to Flamenco not performed")
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl.go
deleted file mode 100644
index 1ff76804e74dff24055bf7db32eb60ab1edef107..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package flamenco
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-)
-
-var stringType reflect.Type = reflect.TypeOf("somestring")
-
-/**
- * Variable replacement for tasks.
- */
-func ReplaceVariables(config *Conf, task *Task, worker *Worker) {
-	varmap := config.VariablesByPlatform[worker.Platform]
-
-	for _, cmd := range task.Commands {
-		for key, value := range cmd.Settings {
-			// Only do replacement on string types
-			if reflect.TypeOf(value) != stringType {
-				continue
-			}
-
-			strvalue := reflect.ValueOf(value).String()
-			for varname, varvalue := range varmap {
-				placeholder := fmt.Sprintf("{%s}", varname)
-				strvalue = strings.Replace(strvalue, placeholder, varvalue, -1)
-			}
-
-			cmd.Settings[key] = strvalue
-		}
-	}
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl_test.go
deleted file mode 100644
index bd1e53e53f5eda97c1b69f5938607f1ab185aecc..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/varrepl_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package flamenco
-
-import (
-	"flag"
-	"os"
-	"testing"
-
-	log "github.com/Sirupsen/logrus"
-	"github.com/stretchr/testify/assert"
-
-	"gopkg.in/mgo.v2/bson"
-)
-
-func TestMain(m *testing.M) {
-	flag.Parse()
-	log.SetLevel(log.InfoLevel)
-
-	config := GetTestConfig()
-	session := MongoSession(&config)
-	db := session.DB("")
-
-	if err := db.DropDatabase(); err != nil {
-		panic("Unable to drop test database!")
-	}
-
-	os.Exit(m.Run())
-}
-
-func TestReplaceVariables(t *testing.T) {
-	config := GetTestConfig()
-	task := Task{
-		Commands: []Command{
-			Command{"echo", bson.M{"message": "Running Blender from {blender} {blender}"}},
-			Command{"sleep", bson.M{"{blender}": 3}},
-		},
-	}
-	worker := Worker{
-		Platform: "linux",
-	}
-
-	ReplaceVariables(&config, &task, &worker)
-
-	// Substitution should happen as often as needed.
-	assert.Equal(t,
-		"Running Blender from /opt/myblenderbuild/blender /opt/myblenderbuild/blender",
-		task.Commands[0].Settings["message"],
-	)
-
-	// No substitution on keys, just on values.
-	assert.Equal(t, 3, task.Commands[1].Settings["{blender}"])
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers.go
deleted file mode 100644
index 2082c1290b8c87fb6a37a3e94c8f35e1646a18cd..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers.go
+++ /dev/null
@@ -1,283 +0,0 @@
-package flamenco
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/http"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-	auth "github.com/abbot/go-http-auth"
-
-	"golang.org/x/crypto/bcrypt"
-
-	mgo "gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-)
-
-/**
- * Returns the worker's address, with the nickname in parentheses (if set).
- *
- * Make sure that you include the nickname in the projection when you fetch
- * the worker from MongoDB.
- */
-func (worker *Worker) Identifier() string {
-	if len(worker.Nickname) > 0 {
-		return fmt.Sprintf("%s (%s)", worker.Address, worker.Nickname)
-	}
-	return worker.Address
-}
-
-func RegisterWorker(w http.ResponseWriter, r *http.Request, db *mgo.Database) {
-	var err error
-
-	log.Info(r.RemoteAddr, "Worker registering")
-
-	// Parse the given worker information.
-	winfo := WorkerRegistration{}
-	if err = DecodeJson(w, r.Body, &winfo, fmt.Sprintf("%s RegisterWorker:", r.RemoteAddr)); err != nil {
-		return
-	}
-
-	// Store it in MongoDB after hashing the password and assigning an ID.
-	worker := Worker{}
-	worker.Secret = winfo.Secret
-	worker.Platform = winfo.Platform
-	worker.SupportedJobTypes = winfo.SupportedJobTypes
-	worker.Nickname = winfo.Nickname
-	worker.Address = r.RemoteAddr
-
-	if err = StoreNewWorker(&worker, db); err != nil {
-		log.Errorf(r.RemoteAddr, "Unable to store worker:", err)
-
-		w.WriteHeader(500)
-		w.Header().Set("Content-Type", "text/plain")
-		fmt.Fprintln(w, "Unable to store worker")
-
-		return
-	}
-
-	w.Header().Set("Content-Type", "application/json")
-	encoder := json.NewEncoder(w)
-	encoder.Encode(worker)
-}
-
-func StoreNewWorker(winfo *Worker, db *mgo.Database) error {
-	var err error
-
-	// Store it in MongoDB after hashing the password and assigning an ID.
-	winfo.ID = bson.NewObjectId()
-	winfo.HashedSecret, err = bcrypt.GenerateFromPassword([]byte(winfo.Secret), bcrypt.DefaultCost)
-	if err != nil {
-		log.Errorf("Unable to hash password:", err)
-		return err
-	}
-
-	workers_coll := db.C("flamenco_workers")
-	if err = workers_coll.Insert(winfo); err != nil {
-		log.Errorf("Unable to insert worker in DB:", err)
-		return err
-	}
-
-	return nil
-}
-
-/**
- * Returns the hashed secret of the worker.
- */
-func WorkerSecret(user string, db *mgo.Database) string {
-	projection := bson.M{"hashed_secret": 1}
-	worker, err := FindWorker(user, projection, db)
-
-	if err != nil {
-		log.Warning("Error fetching hashed password: ", err)
-		return ""
-	}
-
-	return string(worker.HashedSecret)
-}
-
-/**
- * Returns the worker given its ID.
- */
-func FindWorker(worker_id string, projection interface{}, db *mgo.Database) (*Worker, error) {
-	worker := Worker{}
-
-	if !bson.IsObjectIdHex(worker_id) {
-		return &worker, errors.New("Invalid ObjectID")
-	}
-	workers_coll := db.C("flamenco_workers")
-	err := workers_coll.FindId(bson.ObjectIdHex(worker_id)).Select(projection).One(&worker)
-
-	return &worker, err
-}
-
-/**
- * Returns the number of registered workers.
- */
-func WorkerCount(db *mgo.Database) int {
-	count, err := Count(db.C("flamenco_workers"))
-	if err != nil {
-		return -1
-	}
-	return count
-}
-
-func WorkerMayRunTask(w http.ResponseWriter, r *auth.AuthenticatedRequest,
-	db *mgo.Database, task_id bson.ObjectId) {
-
-	// Get the worker
-	worker, err := FindWorker(r.Username, M{"_id": 1, "address": 1, "nickname": 1}, db)
-	if err != nil {
-		log.Warningf("%s WorkerMayRunTask: Unable to find worker: %s",
-			r.RemoteAddr, err)
-		w.WriteHeader(http.StatusForbidden)
-		fmt.Fprintf(w, "Unable to find worker: %s", err)
-		return
-	}
-	WorkerSeen(worker, r.RemoteAddr, db)
-	log.Debugf("WorkerMayRunTask: %s asking if it is allowed to keep running task %s",
-		worker.Identifier(), task_id.Hex())
-
-	response := MayKeepRunningResponse{}
-
-	// Get the task and check its status.
-	task := Task{}
-	if err := db.C("flamenco_tasks").FindId(task_id).One(&task); err != nil {
-		log.Warningf("%s WorkerMayRunTask: unable to find task %s for worker %s",
-			r.RemoteAddr, task_id.Hex(), worker.ID.Hex())
-		response.Reason = fmt.Sprintf("unable to find task %s", task_id.Hex())
-	} else if task.WorkerID != nil && *task.WorkerID != worker.ID {
-		log.Warningf("%s WorkerMayRunTask: task %s was assigned from worker %s to %s",
-			r.RemoteAddr, task_id.Hex(), worker.ID.Hex(), task.WorkerID.Hex())
-		response.Reason = fmt.Sprintf("task %s reassigned to another worker", task_id.Hex())
-	} else if !IsRunnableTaskStatus(task.Status) {
-		log.Warningf("%s WorkerMayRunTask: task %s is in not-runnable status %s, worker %s will stop",
-			r.RemoteAddr, task_id.Hex(), task.Status, worker.ID.Hex())
-		response.Reason = fmt.Sprintf("task %s in non-runnable status %s", task_id.Hex(), task.Status)
-	} else {
-		response.MayKeepRunning = true
-		WorkerPingedTask(&worker.ID, task_id, db)
-	}
-
-	// Send the response
-	w.Header().Set("Content-Type", "application/json")
-	encoder := json.NewEncoder(w)
-	encoder.Encode(response)
-}
-
-func IsRunnableTaskStatus(status string) bool {
-	runnable_statuses := map[string]bool{
-		"active":             true,
-		"claimed-by-manager": true,
-		"queued":             true,
-	}
-
-	runnable, found := runnable_statuses[status]
-	return runnable && found
-}
-
-/*
- * Mark the task as pinged by the worker.
- * If worker_id is not nil, sets the worker_id field of the task. Otherwise doesn't
- * touch that field and only updates last_worker_ping.
- */
-func WorkerPingedTask(worker_id *bson.ObjectId, task_id bson.ObjectId, db *mgo.Database) {
-	tasks_coll := db.C("flamenco_tasks")
-
-	updates := bson.M{
-		"last_worker_ping": UtcNow(),
-	}
-	if worker_id != nil {
-		updates["worker_id"] = *worker_id
-	}
-
-	if err := tasks_coll.UpdateId(task_id, bson.M{"$set": updates}); err != nil {
-		log.Errorf("WorkerPingedTask: ERROR unable to update last_worker_ping on task %s: %s",
-			task_id.Hex(), err)
-	}
-}
-
-/**
- * Registers that we have seen this worker at a certain address.
- */
-func WorkerSeen(worker *Worker, remote_addr string, db *mgo.Database) {
-	worker.LastActivity = UtcNow()
-
-	updates := bson.M{
-		"last_activity": worker.LastActivity,
-	}
-
-	if worker.Address != remote_addr {
-		worker.Address = remote_addr
-		updates["address"] = remote_addr
-	}
-
-	if err := db.C("flamenco_workers").UpdateId(worker.ID, bson.M{"$set": updates}); err != nil {
-		log.Errorf("WorkerSeen: unable to update worker %s in MongoDB: %s", worker.ID, err)
-	}
-}
-
-/**
- * Re-queues all active tasks (should be only one) that are assigned to this worker.
- */
-func WorkerSignOff(w http.ResponseWriter, r *auth.AuthenticatedRequest, db *mgo.Database) {
-	// Get the worker
-	worker, err := FindWorker(r.Username, bson.M{"_id": 1, "address": 1, "nickname": 1}, db)
-	if err != nil {
-		log.Warningf("%s WorkerSignOff: Unable to find worker: %s", r.RemoteAddr, err)
-		w.WriteHeader(http.StatusForbidden)
-		return
-	}
-	w_ident := worker.Identifier()
-
-	log.Warningf("%s Worker %s signing off", r.RemoteAddr, w_ident)
-
-	// Update the tasks assigned to the worker.
-	var tasks []Task
-	query := bson.M{
-		"worker_id": worker.ID,
-		"status":    "active",
-	}
-	sent_header := false
-	if err := db.C("flamenco_tasks").Find(query).All(&tasks); err != nil {
-		log.Warningf("WorkerSignOff: unable to find active tasks of worker %s in MongoDB: %s",
-			w_ident, err)
-		w.WriteHeader(http.StatusInternalServerError)
-		sent_header = true
-	} else {
-		tupdate := TaskUpdate{
-			TaskStatus: "claimed-by-manager",
-			Worker:     "-", // no longer assigned to any worker
-			Activity:   fmt.Sprintf("Re-queued task after worker %s signed off", w_ident),
-			Log: fmt.Sprintf("%s: Manager re-queued task after worker %s signed off",
-				time.Now(), w_ident),
-		}
-
-		for _, task := range tasks {
-			tupdate.TaskID = task.ID
-			if err := QueueTaskUpdate(&tupdate, db); err != nil {
-				if !sent_header {
-					w.WriteHeader(http.StatusInternalServerError)
-					sent_header = true
-				}
-				fmt.Fprintf(w, "Error updating task %s: %s\n", task.ID.Hex(), err)
-				log.Errorf("WorkerSignOff: unable to update task %s for worker %s in MongoDB: %s",
-					task.ID.Hex(), w_ident, err)
-			}
-		}
-	}
-
-	// Update the worker itself, to show it's down in the DB too.
-	worker.Status = "down"
-	updates := bson.M{
-		"status": worker.Status,
-	}
-	if err := db.C("flamenco_workers").UpdateId(worker.ID, bson.M{"$set": updates}); err != nil {
-		if !sent_header {
-			w.WriteHeader(http.StatusInternalServerError)
-		}
-		log.Errorf("WorkerSignOff: unable to update worker %s in MongoDB: %s", w_ident, err)
-	}
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers_test.go b/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers_test.go
deleted file mode 100644
index d49c84e725d672daebd521783e3f2d16bcb6394d..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/flamenco/workers_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package flamenco
-
-import (
-	"fmt"
-	"io"
-	"net/http"
-	"net/http/httptest"
-
-	auth "github.com/abbot/go-http-auth"
-	"github.com/stretchr/testify/assert"
-	check "gopkg.in/check.v1"
-	"gopkg.in/mgo.v2/bson"
-)
-
-func WorkerTestRequest(worker_id bson.ObjectId, method, url string, vargs ...interface{}) (*httptest.ResponseRecorder, *auth.AuthenticatedRequest) {
-	return WorkerTestRequestWithBody(worker_id, nil, method, url, vargs...)
-}
-
-func WorkerTestRequestWithBody(worker_id bson.ObjectId, body io.Reader, method, url string, vargs ...interface{}) (*httptest.ResponseRecorder, *auth.AuthenticatedRequest) {
-	resp_rec := httptest.NewRecorder()
-	if resp_rec == nil {
-		panic("WorkerTestRequest: resp_rec is nil")
-	}
-
-	request, err := http.NewRequest(method, fmt.Sprintf(url, vargs...), body)
-	if err != nil {
-		panic(err)
-	}
-	if request == nil {
-		panic("WorkerTestRequest: request is nil")
-	}
-
-	ar := &auth.AuthenticatedRequest{Request: *request, Username: worker_id.Hex()}
-	if ar == nil {
-		panic("WorkerTestRequest: ar is nil")
-	}
-
-	return resp_rec, ar
-}
-
-func (s *SchedulerTestSuite) TestWorkerMayRun(t *check.C) {
-	// Store task in DB.
-	task := ConstructTestTask("aaaaaaaaaaaaaaaaaaaaaaaa", "sleeping")
-	if err := s.db.C("flamenco_tasks").Insert(task); err != nil {
-		t.Fatal("Unable to insert test task", err)
-	}
-
-	// Make sure the scheduler gives us this task.
-	resp_rec, ar := WorkerTestRequest(s.worker_lnx.ID, "GET", "/task")
-	s.sched.ScheduleTask(resp_rec, ar)
-
-	// Right after obtaining the task, we should be allowed to keep running it.
-	resp_rec, ar = WorkerTestRequest(s.worker_lnx.ID, "GET", "/may-i-run/%s", task.ID.Hex())
-	WorkerMayRunTask(resp_rec, ar, s.db, task.ID)
-
-	resp := MayKeepRunningResponse{}
-	parseJson(t, resp_rec, 200, &resp)
-	assert.Equal(t, "", resp.Reason)
-	assert.Equal(t, true, resp.MayKeepRunning)
-
-	// If we now change the task status to "cancel-requested", the worker should be denied.
-	assert.Nil(t, s.db.C("flamenco_tasks").UpdateId(task.ID,
-		bson.M{"$set": bson.M{"status": "cancel-requested"}}))
-	resp_rec, ar = WorkerTestRequest(s.worker_lnx.ID, "GET", "/may-i-run/%s", task.ID.Hex())
-	WorkerMayRunTask(resp_rec, ar, s.db, task.ID)
-
-	resp = MayKeepRunningResponse{}
-	parseJson(t, resp_rec, 200, &resp)
-	assert.Equal(t, false, resp.MayKeepRunning)
-
-	// Changing status back to "active", but assigning to another worker
-	assert.Nil(t, s.db.C("flamenco_tasks").UpdateId(task.ID, bson.M{"$set": bson.M{
-		"status":    "active",
-		"worker_id": s.worker_win.ID,
-	}}))
-	resp_rec, ar = WorkerTestRequest(s.worker_lnx.ID, "GET", "/may-i-run/%s", task.ID.Hex())
-	WorkerMayRunTask(resp_rec, ar, s.db, task.ID)
-
-	resp = MayKeepRunningResponse{}
-	parseJson(t, resp_rec, 200, &resp)
-	assert.Equal(t, false, resp.MayKeepRunning)
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/main.go b/packages/flamenco-manager-go/src/flamenco-manager/main.go
deleted file mode 100644
index 47a4fdf008d547cbdbbd7270b7e7a2e1ef3c7181..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/main.go
+++ /dev/null
@@ -1,264 +0,0 @@
-package main
-
-import (
-	"context"
-	"flag"
-	"fmt"
-	"net/http"
-	"os"
-	"os/signal"
-	"strings"
-	"syscall"
-	"time"
-
-	"gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
-
-	log "github.com/Sirupsen/logrus"
-	auth "github.com/abbot/go-http-auth"
-
-	"flamenco-manager/flamenco"
-
-	"github.com/gorilla/mux"
-)
-
-const FLAMENCO_VERSION = "2.0-beta10"
-
-// MongoDB session
-var session *mgo.Session
-var config flamenco.Conf
-var upstream *flamenco.UpstreamConnection
-var task_scheduler *flamenco.TaskScheduler
-var task_update_pusher *flamenco.TaskUpdatePusher
-var task_timeout_checker *flamenco.TaskTimeoutChecker
-var httpServer *http.Server
-var shutdownComplete chan struct{}
-
-func http_status(w http.ResponseWriter, r *http.Request) {
-	flamenco.SendStatusReport(w, r, session, FLAMENCO_VERSION)
-}
-
-func http_register_worker(w http.ResponseWriter, r *http.Request) {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-	flamenco.RegisterWorker(w, r, mongo_sess.DB(""))
-}
-
-func http_schedule_task(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
-	task_scheduler.ScheduleTask(w, r)
-}
-
-func http_kick(w http.ResponseWriter, r *http.Request) {
-	upstream.KickDownloader(false)
-	fmt.Fprintln(w, "Kicked task downloader")
-}
-
-func http_timeout(w http.ResponseWriter, r *http.Request) {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-	task_timeout_checker.Check(mongo_sess.DB(""))
-
-	fmt.Fprintln(w, "Kicked task timeouter")
-}
-
-func http_task_update(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-
-	vars := mux.Vars(&r.Request)
-	task_id := vars["task-id"]
-
-	if !bson.IsObjectIdHex(task_id) {
-		w.WriteHeader(http.StatusNotFound)
-		fmt.Fprintf(w, "Invalid ObjectID passed as task ID: %s\n", task_id)
-		return
-	}
-
-	flamenco.QueueTaskUpdateFromWorker(w, r, mongo_sess.DB(""), bson.ObjectIdHex(task_id))
-}
-
-/**
- * Called by a worker, to check whether it is allowed to keep running this task.
- */
-func http_worker_may_run_task(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-
-	vars := mux.Vars(&r.Request)
-	task_id := vars["task-id"]
-
-	if !bson.IsObjectIdHex(task_id) {
-		w.WriteHeader(http.StatusNotFound)
-		fmt.Fprintf(w, "Invalid ObjectID passed as task ID: %s\n", task_id)
-		return
-	}
-
-	flamenco.WorkerMayRunTask(w, r, mongo_sess.DB(""), bson.ObjectIdHex(task_id))
-}
-
-func http_worker_sign_off(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-
-	flamenco.WorkerSignOff(w, r, mongo_sess.DB(""))
-}
-
-func worker_secret(user, realm string) string {
-	mongo_sess := session.Copy()
-	defer mongo_sess.Close()
-
-	return flamenco.WorkerSecret(user, mongo_sess.DB(""))
-}
-
-func shutdown(signum os.Signal) {
-	// Always shut down after 2 seconds.
-	timeout := flamenco.TimeoutAfter(2 * time.Second)
-
-	go func() {
-		log.Infof("Signal '%s' received, shutting down.", signum)
-
-		if httpServer != nil {
-			log.Info("Shutting down HTTP server")
-			httpServer.Shutdown(context.Background())
-		} else {
-			log.Warning("HTTP server was not even started yet")
-		}
-
-		task_timeout_checker.Close()
-		task_update_pusher.Close()
-		upstream.Close()
-		session.Close()
-		timeout <- false
-	}()
-
-	if <-timeout {
-		log.Error("Shutdown forced, stopping process.")
-		os.Exit(-2)
-	}
-
-	log.Warning("Shutdown complete, stopping process.")
-	close(shutdownComplete)
-}
-
-var cliArgs struct {
-	verbose    bool
-	debug      bool
-	jsonLog    bool
-	cleanSlate bool
-	version    bool
-}
-
-func parseCliArgs() {
-	flag.BoolVar(&cliArgs.verbose, "verbose", false, "Enable info-level logging")
-	flag.BoolVar(&cliArgs.debug, "debug", false, "Enable debug-level logging")
-	flag.BoolVar(&cliArgs.jsonLog, "json", false, "Log in JSON format")
-	flag.BoolVar(&cliArgs.cleanSlate, "cleanslate", false, "Start with a clean slate; erases all tasks from the local MongoDB")
-	flag.BoolVar(&cliArgs.version, "version", false, "Show the version of Flamenco Manager")
-	flag.Parse()
-}
-
-func configLogging() {
-	if cliArgs.jsonLog {
-		log.SetFormatter(&log.JSONFormatter{})
-	} else {
-		log.SetFormatter(&log.TextFormatter{
-			FullTimestamp: true,
-		})
-	}
-
-	// Only log the warning severity or above.
-	level := log.WarnLevel
-	if cliArgs.debug {
-		level = log.DebugLevel
-	} else if cliArgs.verbose {
-		level = log.InfoLevel
-	}
-	log.SetLevel(level)
-}
-
-func main() {
-	parseCliArgs()
-	if cliArgs.version {
-		fmt.Println(FLAMENCO_VERSION)
-		return
-	}
-
-	configLogging()
-	log.Infof("Starting Flamenco Manager version %s", FLAMENCO_VERSION)
-
-	defer func() {
-		// If there was a panic, make sure we log it before quitting.
-		if r := recover(); r != nil {
-			log.Panic(r)
-		}
-	}()
-
-	config = flamenco.GetConf()
-	has_tls := config.TLSCert != "" && config.TLSKey != ""
-	if has_tls {
-		config.OwnUrl = strings.Replace(config.OwnUrl, "http://", "https://", 1)
-	} else {
-		config.OwnUrl = strings.Replace(config.OwnUrl, "https://", "http://", 1)
-		log.Warning("WARNING: TLS not enabled!")
-	}
-
-	log.Info("MongoDB database server :", config.DatabaseUrl)
-	log.Info("Upstream Flamenco server:", config.Flamenco)
-	log.Info("My URL is               :", config.OwnUrl)
-	log.Info("Listening at            :", config.Listen)
-
-	session = flamenco.MongoSession(&config)
-
-	if cliArgs.cleanSlate {
-		flamenco.CleanSlate(session.DB(""))
-		log.Warning("Shutting down after performing clean slate")
-		return
-	}
-
-	upstream = flamenco.ConnectUpstream(&config, session)
-	task_scheduler = flamenco.CreateTaskScheduler(&config, upstream, session)
-	task_update_pusher = flamenco.CreateTaskUpdatePusher(&config, upstream, session)
-	task_timeout_checker = flamenco.CreateTaskTimeoutChecker(&config, session)
-
-	// Set up our own HTTP server
-	worker_authenticator := auth.NewBasicAuthenticator("Flamenco Manager", worker_secret)
-	router := mux.NewRouter().StrictSlash(true)
-	router.HandleFunc("/", http_status).Methods("GET")
-	router.HandleFunc("/register-worker", http_register_worker).Methods("POST")
-	router.HandleFunc("/task", worker_authenticator.Wrap(http_schedule_task)).Methods("POST")
-	router.HandleFunc("/tasks/{task-id}/update", worker_authenticator.Wrap(http_task_update)).Methods("POST")
-	router.HandleFunc("/may-i-run/{task-id}", worker_authenticator.Wrap(http_worker_may_run_task)).Methods("GET")
-	router.HandleFunc("/sign-off", worker_authenticator.Wrap(http_worker_sign_off)).Methods("POST")
-	router.HandleFunc("/kick", http_kick)
-	router.HandleFunc("/timeout", http_timeout)
-
-	upstream.SendStartupNotification()
-	go task_update_pusher.Go()
-	go task_timeout_checker.Go()
-
-	// Create the HTTP server before allowing the shutdown signal Handler
-	// to exist. This prevents a race condition when Ctrl+C is pressed after
-	// the http.Server is created, but before it is assigned to httpServer.
-	httpServer = &http.Server{Addr: config.Listen, Handler: router}
-	shutdownComplete = make(chan struct{})
-
-	// Handle Ctrl+C
-	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt)
-	signal.Notify(c, syscall.SIGTERM)
-	go func() {
-		for signum := range c {
-			// Run the shutdown sequence in a goroutine, so that multiple Ctrl+C presses can be handled in parallel.
-			go shutdown(signum)
-		}
-	}()
-
-	// Fall back to insecure server if TLS certificate/key is not defined.
-	if !has_tls {
-		log.Warning(httpServer.ListenAndServe())
-	} else {
-		log.Warning(httpServer.ListenAndServeTLS(config.TLSCert, config.TLSKey))
-	}
-
-	<-shutdownComplete
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/main_test.go b/packages/flamenco-manager-go/src/flamenco-manager/main_test.go
deleted file mode 100644
index 1d7985c909de039f1864af3f26569d950fe4c1f3..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/main_test.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package main
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestCanary(t *testing.T) {
-	assert.True(t, true, "This is good. Canary test passing")
-}
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/tls/cert.pem b/packages/flamenco-manager-go/src/flamenco-manager/tls/cert.pem
deleted file mode 100644
index 45b515c02b785a5318cd805b3077d9cf44c8a49f..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/tls/cert.pem
+++ /dev/null
@@ -1,23 +0,0 @@
-Signature ok
-subject=/C=NL/ST=Noord Holland/L=Amsterdam/O=Blender Institute/CN=localhost
-Getting Private key
------BEGIN CERTIFICATE-----
-MIIDTjCCAjYCCQDRSJyrq+KmTzANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJO
-TDEWMBQGA1UECAwNTm9vcmQgSG9sbGFuZDESMBAGA1UEBwwJQW1zdGVyZGFtMRow
-GAYDVQQKDBFCbGVuZGVyIEluc3RpdHV0ZTESMBAGA1UEAwwJbG9jYWxob3N0MB4X
-DTE2MTIxNjE0MDQyNFoXDTE3MDExNTE0MDQyNFowaTELMAkGA1UEBhMCTkwxFjAU
-BgNVBAgMDU5vb3JkIEhvbGxhbmQxEjAQBgNVBAcMCUFtc3RlcmRhbTEaMBgGA1UE
-CgwRQmxlbmRlciBJbnN0aXR1dGUxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOUo4MMPw+ab12S4DCpusw39tAN3cZ5d
-a2PvljgZguv+oJfFEW2Z7ndjSyvrmPqkwtZG9N1nZz3rIRzuoSoBG1c86hC2sdFJ
-fcPGf1Mcd5uyJNMfRxIdSGB1JUgzoMsGKZiOHfwaRVLmC/k9WPYIBgV3DWJVH5ds
-OcM0A3qtHc1c7a1kMSrXsRrSn9J2MgMwAT7POwE47djy85k2bYnO7apHoBqGpEtP
-CNHGOmnMiBePUu/PGYMSrqvg4tyAqStdtNeMQFv4BpSOm7cYyMZ3NKY9Zzoulb1/
-D5MFIYnrpsyW1y7l93gZPuL3ETlTdXBKuVKHUuyLgkMdK0D9eOCoE+MCAwEAATAN
-BgkqhkiG9w0BAQsFAAOCAQEAKpdTclBuPYwuYUl7B6fgEzeWO269CgZrMGBxy8kq
-ZhBfbtdCQUEygERRZ/eA1xS3PT6TVCBoHcHTEJqiPjW7Ag91HceYDGIrdN4HUQJ5
-0dkaLefC+539gobd82JIKOAaiSRFMAIe0UBncmzBevTH13A0uv7jHMaToccsQi8v
-DbKbEawNolsjQHPZ+xqIFD0sXnoUE3cVXtLlMkeVEnhwEB8b+LxuemJZ5z36RIxb
-C4H4szW/bkR8mjOAu5e2qKXgDc/5rJ6Tkast7U62HbihpDzdpwUEul0wEXLVSd8F
-ofT1q2FacrHPiysxhYQZ4X98YyDqx77AFMc0UKhXnkEt5w==
------END CERTIFICATE-----
diff --git a/packages/flamenco-manager-go/src/flamenco-manager/tls/privkey.pem b/packages/flamenco-manager-go/src/flamenco-manager/tls/privkey.pem
deleted file mode 100644
index 9e524cb488e3082034c78b644079e848cf19ac17..0000000000000000000000000000000000000000
--- a/packages/flamenco-manager-go/src/flamenco-manager/tls/privkey.pem
+++ /dev/null
@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDlKODDD8Pmm9dk
-uAwqbrMN/bQDd3GeXWtj75Y4GYLr/qCXxRFtme53Y0sr65j6pMLWRvTdZ2c96yEc
-7qEqARtXPOoQtrHRSX3Dxn9THHebsiTTH0cSHUhgdSVIM6DLBimYjh38GkVS5gv5
-PVj2CAYFdw1iVR+XbDnDNAN6rR3NXO2tZDEq17Ea0p/SdjIDMAE+zzsBOO3Y8vOZ
-Nm2Jzu2qR6AahqRLTwjRxjppzIgXj1LvzxmDEq6r4OLcgKkrXbTXjEBb+AaUjpu3
-GMjGdzSmPWc6LpW9fw+TBSGJ66bMltcu5fd4GT7i9xE5U3VwSrlSh1Lsi4JDHStA
-/XjgqBPjAgMBAAECggEBAL6aJ4hW3ow65wbBBm1sscVbVZTkjj44WZA/wORcY8bC
-fPR/VyWgOPZYQjf/t7gRvnTXg+d7kCWyIlKcMLRtQz5mThEkw/XdeJuTyGdqcBmy
-LGrlwwlQDdkc1qudNYpoT8SxwELl3u86pI7j9dB9j/SPtzQotSQPQmQYKSSqRPV/
-WDUG3vBAoMQaUXHZqN9+ryeWYP4CYZZKF1NxxomkFg4Y+M6s6G+7NIeYmTTTrQWB
-xxYJnTIDFaK0S9uEn7qsELhCsSMENbEEm6+wmi9uFemYhsQeXsVrOuGw1rTtbeHB
-QANfL5zUCuOT+tVoy0sT/6u6UOD9jeMlc13uBl7H+wECgYEA/8mLrlbgz68gLzXq
-rkqGCCuHChFsJU1A+APMv+myoUTd4gXupBdfLS9k72CbKfBwUniWJgplyRU0gZT5
-YqCT+cLjBfYkzmKEZUMOSYlpSEtej3ma19Bbmxzh4pJWQtV5hLkujs2Sir4SN/i+
-8ncYtnDOTD0V0UDlB88Q0gmcM0ECgYEA5Vmp4q9yg0hsDXXqrb+irl0q8Hjov2AM
-bXRTh7gMvtPR/Ra8lJY+Th542K59+deDe5/mNrdLsVQDX4ro74yyGfcHlNLGYFM0
-UTPXDaubJYyOYfHwsEeU3KHj+XFjbTFc+l8aN1g4DMkVvHAoAMV7aYlf2SlxDoKr
-JonEIUCSkiMCgYEAtD7sRVBHX1KDFYGi/GrbhEpYAIpCcQ69Z4gV8m7WR7pluO6B
-OfSWRxsMv3qOHMGoBRWgiPHuxAJDW8UE77FEVU41+G95hE38Cfd0y/Ee1aj225fP
-u6DBzM5Phv+j9bjExvhPjKXkTAygffy1Ydr2+SkI1sR86VYXjqclrTzEa4ECgYEA
-kRvm8ebhxBB5VRbrMZ1TF5EZDubhE9x4YHQ+OVuIrOAmN0RAcp6QsypyeV4FlKL3
-rKshpDLasEqgi72+3XmeYfE7Gb02CFH8gvgSs7KEygAhQfUqvM29cM75B6TnLHoU
-AtFTK/skE2rS1tP7a2mHSOHDBApFXtHr6ck2j3dkhRMCgYBP6iQT6SoEZKT1P4Te
-bcVkCgSl0D1GvALds8BcEWfUL4X7x54QWeU4CgiNLnwHnf+R4pIcXiQs5NAXwZiG
-eMqPYUCOG6KjkLIxMPP4ghMbI2ZCjPE0oLquwsyMurD8ClZ5vP+WQjxu8gv+ak63
-qqjUgar6faW8Yomhz6v0md+pXw==
------END PRIVATE KEY-----
diff --git a/packages/flamenco-worker-python/README.md b/packages/flamenco-worker-python/README.md
deleted file mode 100644
index 63fd37a90f4b9a44526b2521e9cd4e0f8c14203c..0000000000000000000000000000000000000000
--- a/packages/flamenco-worker-python/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Flamenco Worker
-
-This is the Flamenco Worker implemented in Python 3.
-
-
-## Configuration
-
-Configuration is read from three locations:
-
-- A hard-coded default in the Python source code.
-- `flamenco-worker.cfg` in the current working directory.
-- `$HOME/.flamenco-worker.cfg`.
-
-When those files do not exist, they are skipped (i.e. this is not an error). They
-should be in INI format, as specified by the
-[configparser documentation](https://docs.python.org/3/library/configparser.html)
-
-### Configuration contents:
-
-All configuration keys should be placed in the `[flamenco-worker]` section of the
-config files.
-
-- `manager_url`: Flamenco Manager URL.
-- `worker_id`: ID of the worker, handed out by the Manager upon registration (see
-  Registration below) and used for authentication with the Manager.
-- `worker_secret`: Secret key of the worker, given to the Manager upon registration
-  and authentication.
-- `job_types`: Space-separated list of job types this worker may execute.
-- `task_update_queue_db`: filename of the SQLite3 database holding the queue of task
-  updates to be sent to the Master.
-
-### TODO
-
-- Certain settings are currently only settable by editing constants in the Python source code.
-  It might be nice to read them from the config file too, at some point.
-- Update worker address in MongoDB when communicating with it.
-
-## Invocation
-
-Install using `pip install -e .` for development, or `setup.py install` for production.
-This creates a command `flamenco-worker`, which can be run with `--help` to obtain
-a list of possible CLI arguments.
-
-## Registration
-
-If the configuration file does not contain both a `worker_id` and `worker_secret`, at startup
-the worker will attempt to register itself at the Master.
-Once registered via a POST to the manager's `/register-worker` endpoint, the `worker_id` and
-`worker_secret` will be written to `$HOME/.flamenco-worker.cfg`
-
-## Task fetch & execution
-
-1. A task is obtained by the FlamencoWorker from the manager via a POST to its `/task` endpoint.
-   If this fails (for example due to a connection error), the worker will retry every few seconds
-   until a task fetch is succesful.
-2. The task is given to a TaskRunner object.
-3. The TaskRunner object iterates over the commands and executes them.
-4. At any time, the FlamencoWorker can be called upon to register activities and log lines,
-   and forward them to the Manager. These updates are queued in a SQLite3 database, such that
-   task execution isn't interrupted when the Manager cannot be reached.
-5. A separate coroutine of TaskUpdateQueue fetches updates from the queue, and forwards them to
-   the Master, using a POST to its `/tasks/{task-id}/update` endpoint.
-   **TODO:** the response to this endpoint may indicate a request to abort the currently running
-   task. This should be implemented.
-
-
-## Shutdown
-
-Pressing [CTRL]+[C] will cause a clean shutdown of the worker.
-If there is a task currently running, it will be aborted without changing its status. Any pending task updates are sent to the Manager, and then the Manager's `/sign-off` URL is
-POSTed to, to indicate a clean shutdown of the worker. Any active task that is still
-assigned to the worker is given status "claimed-by-manager" so that it can be re-activated
-by another worker.
-
-
-## Systemd integration
-
-To run Flamenco Worker as a systemd-managed service, copy `flamenco-worker.service` to
-`/etc/systemd/system/flamenco-worker.service`, then run `systemctl daemon-reload`.
-
-After installation of this service, `systemctl {start,stop,status,restart} flamenco-worker`
-commands can be used to manage it. To ensure that the Flamenco Worker starts at system boot,
-use `systemctl enable flamenco-worker`.
-
-
-## Signals
-
-Flamenco Worker responds to the following POSIX signals:
-
-- `SIGINT`, `SIGTERM`: performs a clean shutdown, as described in the Shutdown section above.
-- `SIGUSR1`: logs the currently scheduled asyncio tasks.
diff --git a/packages/flamenco/.gitignore b/packages/flamenco/.gitignore
deleted file mode 100644
index 0736a17702b1a53e59d15ff95c91fffba6de2ada..0000000000000000000000000000000000000000
--- a/packages/flamenco/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-.DS_Store
-.project
-.coverage
-*.pyc
-__pycache__
-
-/build
-/.cache
-/*.egg-info/
-/.eggs/
-/node_modules/
-/flamenco/templates/
-/flamenco/static/assets/css/
-/flamenco/static/assets/js/generated/
diff --git a/packages/flamenco/LICENSE.txt b/packages/flamenco/LICENSE.txt
deleted file mode 100644
index 41fbe44f271a07c79cb466553e352bfd81a1ad8e..0000000000000000000000000000000000000000
--- a/packages/flamenco/LICENSE.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/packages/flamenco/README.md b/packages/flamenco/README.md
deleted file mode 100644
index cce5a2c29d356fe8ad1e5a005c898d7687d4ec28..0000000000000000000000000000000000000000
--- a/packages/flamenco/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Flamenco Server
-
-This is the Flamenco Server component, implemented as a Pillar extension.
-
-## Development Setup
-
-In order to get Flamenco up and running, we need to follow these steps:
-
-- add Flamenco as Pillar extension to our project
-- create a Manager doc
-- give a user 'admin' rights for Flamenco (this is temporary)
-- give setup a project to use Flamenco
-
-Add Flamenco to your Pillar application as an extension (docs will be available in the Pillar 
-documentaiton). At this point we can proceed with the setup of our first manager.
-
-```
-python manage.py flamenco create_manager flm-manager@example.com local-manager 'Local manager'
-```
-
-The required params are: 
-- `flm-manager@example.com` is a new Pillar service account that gets associated with the
-new manager created
-- `local-manager` is the name of the manager
-- `'Local manager` is a description of the manager
-
-Once the manager doc is created, we note down the following info:
-
-- `_id` in the new manager doc
-- the *Access Token*
-
-We will use these values in the `flamenco-manager.yaml` config file for the Manager.
-
-Next, we allow a user to interact with a Flamenco project:
-
-```
-python manage.py make_admin user@example.com
-```
-
-where `user@example.com` is an existing user.
-
-Finally, we set up a project to be used with Flamenco:
-
-```
-python manage.py setup_for_flamenco project-url
-```
-
-At this point we can run our server and access Flamenco on the `/flamenco` endpoint.
-
-## TODO
-
-- When a certain percentage of a job's tasks have failed, cancel the remaining
-  tasks and only then mark the job as failed.
-- Handle parent relations between tasks (scheduling, canceling, failing etc.)
diff --git a/packages/flamenco/deploy.sh b/packages/flamenco/deploy.sh
deleted file mode 100755
index e4783f76777e1180dfa106b7d16b7ec6ba994996..0000000000000000000000000000000000000000
--- a/packages/flamenco/deploy.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-echo
-echo "==========================================================================="
-echo "Dummy deploy script for people with a 'git pp' alias to push to production."
-echo "Run deploy script on your server project."
-echo "When done, press [ENTER] to stop this script."
-read dummy
diff --git a/packages/flamenco/flamenco/__init__.py b/packages/flamenco/flamenco/__init__.py
deleted file mode 100644
index 70a65c65cbb23d913bc8c9669167f3d85dd76b03..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/__init__.py
+++ /dev/null
@@ -1,273 +0,0 @@
-import logging
-import os.path
-
-import flask
-from werkzeug.local import LocalProxy
-from pillar.extension import PillarExtension
-
-EXTENSION_NAME = 'flamenco'
-
-# Roles required to view job, manager or task details.
-ROLES_REQUIRED_TO_VIEW_ITEMS = {u'demo', u'subscriber', u'admin', u'flamenco-admin'}
-ROLES_REQUIRED_TO_VIEW_LOGS = {u'admin', u'flamenco-admin'}
-
-
-class FlamencoExtension(PillarExtension):
-    def __init__(self):
-        self._log = logging.getLogger('%s.FlamencoExtension' % __name__)
-
-        import flamenco.jobs
-        import flamenco.tasks
-        import flamenco.managers
-
-        self.job_manager = flamenco.jobs.JobManager()
-        self.task_manager = flamenco.tasks.TaskManager()
-        self.manager_manager = flamenco.managers.ManagerManager()
-
-    @property
-    def name(self):
-        return EXTENSION_NAME
-
-    def flask_config(self):
-        """Returns extension-specific defaults for the Flask configuration.
-
-        Use this to set sensible default values for configuration settings
-        introduced by the extension.
-
-        :rtype: dict
-        """
-
-        # Just so that it registers the management commands.
-        from . import cli
-
-        return {}
-
-    def eve_settings(self):
-        """Returns extensions to the Eve settings.
-
-        Currently only the DOMAIN key is used to insert new resources into
-        Eve's configuration.
-
-        :rtype: dict
-        """
-        from eve_settings import DOMAIN
-        return {'DOMAIN': DOMAIN}
-
-    def blueprints(self):
-        """Returns the list of top-level blueprints for the extension.
-
-        These blueprints will be mounted at the url prefix given to
-        app.load_extension().
-
-        :rtype: list of flask.Blueprint objects.
-        """
-
-        from . import routes
-        import flamenco.jobs.routes
-        import flamenco.tasks.routes
-
-        return [
-            routes.blueprint,
-            flamenco.jobs.routes.perproject_blueprint,
-            flamenco.jobs.routes.blueprint,
-            flamenco.tasks.routes.perjob_blueprint,
-            flamenco.tasks.routes.perproject_blueprint,
-        ]
-
-    @property
-    def template_path(self):
-        return os.path.join(os.path.dirname(__file__), 'templates')
-
-    @property
-    def static_path(self):
-        return os.path.join(os.path.dirname(__file__), 'static')
-
-    def setup_app(self, app):
-        """Connects Blinker signals and sets up other app-dependent stuff in
-        submodules.
-        """
-
-        # Create the flamenco_task_logs collection with a compressing storage engine.
-        # If the zlib compression is too CPU-intensive, switch to Snappy instead.
-        with app.app_context():
-            self._create_collections(app.db())
-
-        from . import managers, jobs, tasks
-
-        managers.setup_app(app)
-        jobs.setup_app(app)
-        tasks.setup_app(app)
-
-    def _create_collections(self, db):
-        import pymongo
-
-        # flamenco_task_logs
-        if 'flamenco_task_logs' not in db.collection_names(include_system_collections=False):
-            self._log.info('Creating flamenco_task_logs collection.')
-            db.create_collection('flamenco_task_logs',
-                                 storageEngine={
-                                     'wiredTiger': {'configString': 'block_compressor=zlib'}
-                                 })
-        else:
-            self._log.debug('Not creating flamenco_task_logs collection, already exists.')
-
-        self._log.info('Creating index on flamenco_task_logs collection')
-        db.flamenco_task_logs.create_index(
-            [('task_id', pymongo.ASCENDING),
-             ('received_on_manager', pymongo.ASCENDING)],
-            background=True,
-            unique=False,
-            sparse=False,
-        )
-
-        # flamenco_tasks
-        if 'flamenco_tasks' not in db.collection_names(include_system_collections=False):
-            self._log.info('Creating flamenco_tasks collection.')
-            db.create_collection('flamenco_tasks',
-                                 storageEngine={
-                                     'wiredTiger': {'configString': 'block_compressor=zlib'}
-                                 })
-        else:
-            self._log.debug('Not creating flamenco_tasks collection, already exists.')
-
-        self._log.info('Creating index on flamenco_tasks collection')
-        db.flamenco_tasks.create_index(
-            [('manager', pymongo.ASCENDING)],
-            background=False,
-            unique=False,
-            sparse=False,
-        )
-        db.flamenco_tasks.create_index(
-            [('_updated', pymongo.DESCENDING)],
-            background=False,
-            unique=False,
-            sparse=False,
-        )
-
-    def flamenco_projects(self):
-        """Returns projects set up for Flamenco.
-
-        :returns: {'_items': [proj, proj, ...], '_meta': Eve metadata}
-        """
-
-        import pillarsdk
-        from pillar.web.system_util import pillar_api
-
-        api = pillar_api()
-
-        # Find projects that are set up for Flamenco.
-        projects = pillarsdk.Project.all({
-            'where': {
-                'extension_props.flamenco': {'$exists': 1},
-            }}, api=api)
-
-        return projects
-
-    def is_flamenco_project(self, project, test_extension_props=True):
-        """Returns whether the project is set up for Flamenco.
-
-        Requires Flamenco extension properties.
-        """
-
-        if not test_extension_props:
-            return True
-
-        if not project.extension_props:
-            return False
-
-        try:
-            pprops = project.extension_props[EXTENSION_NAME]
-        except AttributeError:
-            self._log.warning("is_flamenco_project: Project url=%r doesn't have"
-                              " any extension properties.", project['url'])
-            if self._log.isEnabledFor(logging.DEBUG):
-                import pprint
-                self._log.debug('Project: %s', pprint.pformat(project.to_dict()))
-            return False
-        except KeyError:
-            return False
-
-        if pprops is None:
-            self._log.warning("is_flamenco_project: Project url=%r doesn't have"
-                              " Flamenco extension properties.", project['url'])
-            return False
-        return True
-
-    def current_user_is_flamenco_admin(self):
-        """Returns True iff the user is a Flamenco admin or regular admin."""
-
-        from pillar.api.utils.authorization import user_matches_roles
-
-        return user_matches_roles({u'admin', u'flamenco-admin'})
-
-    def sidebar_links(self, project):
-
-        if not self.is_flamenco_project(project):
-            return ''
-
-        # Temporarily disabled until Flamenco is nicer to look at.
-        return ''
-        # return flask.render_template('flamenco/sidebar.html',
-        #                              project=project)
-
-    def db(self, collection_name):
-        """Returns a Flamenco-specific MongoDB collection."""
-        return flask.current_app.db()['flamenco_%s' % collection_name]
-
-    def update_status(self, collection_name, document_id, new_status):
-        """Updates a document's status, avoiding Eve.
-
-        Doesn't use Eve patch_internal to avoid Eve's authorisation. For
-        example, Eve doesn't know certain PATCH operations are allowed by
-        Flamenco managers.
-
-        :rtype: pymongo.results.UpdateResult
-        """
-
-        return self.update_status_q(collection_name, {'_id': document_id}, new_status)
-
-    def update_status_q(self, collection_name, query, new_status):
-        """Updates the status for the queried objects.
-
-        :returns: the result of the collection.update_many() call
-        :rtype: pymongo.results.UpdateResult
-        """
-        from flamenco import eve_settings, current_flamenco
-        import datetime
-        import uuid
-        from bson import tz_util
-
-        singular_name = collection_name.rstrip('s')  # jobs -> job
-        schema = eve_settings.DOMAIN['flamenco_%s' % collection_name]['schema']
-        valid_statuses = schema['status']['allowed']
-
-        if new_status not in valid_statuses:
-            raise ValueError('Invalid %s status %s' % (singular_name, new_status))
-
-        # Generate random ETag since we can't compute it from the entire document.
-        # This means that a subsequent PUT will change the etag even when the document doesn't
-        # change; this is unavoidable without fetching the entire document.
-        etag = uuid.uuid4().hex
-
-        collection = current_flamenco.db(collection_name)
-        result = collection.update_many(
-            query,
-            {'$set': {'status': new_status,
-                      '_updated': datetime.datetime.now(tz=tz_util.utc),
-                      '_etag': etag}}
-        )
-
-        self._log.debug('Updated status of %i %s %s to %s',
-                        result.modified_count, singular_name, query, new_status)
-
-        return result
-
-
-def _get_current_flamenco():
-    """Returns the Flamenco extension of the current application."""
-
-    return flask.current_app.pillar_extensions[EXTENSION_NAME]
-
-
-current_flamenco = LocalProxy(_get_current_flamenco)
-"""Flamenco extension of the current app."""
diff --git a/packages/flamenco/flamenco/cli.py b/packages/flamenco/flamenco/cli.py
deleted file mode 100644
index dd96de92516eebfc645a34f837a67a4cd24ccacf..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/cli.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""Commandline interface for Flamenco."""
-
-import logging
-
-from flask import current_app
-from flask_script import Manager
-
-from pillar.cli import manager, create_service_account
-from pillar.api.utils import authentication
-
-import flamenco
-import flamenco.setup
-
-log = logging.getLogger(__name__)
-
-manager_flamenco = Manager(current_app, usage="Perform Flamenco operations")
-
-
-@manager_flamenco.command
-@manager_flamenco.option('-r', '--replace', dest='replace', action='store_true',
-                         default=False)
-def setup_for_flamenco(project_url, replace=False):
-    """Adds Flamenco node types to the project.
-
-    Use --replace to replace pre-existing Flamenco node types
-    (by default already existing Flamenco node types are skipped).
-    """
-
-    authentication.force_cli_user()
-    flamenco.setup.setup_for_flamenco(project_url, replace=replace)
-
-
-@manager_flamenco.command
-def create_manager(email, name, description):
-    """Creates a Flamenco manager."""
-
-    from pillar.api.utils import dumps
-
-    authentication.force_cli_user()
-    mngr_doc, account, token = flamenco.setup.create_manager(email, name, description)
-
-    print('Created a new manager:')
-    print(dumps(mngr_doc, indent=4))
-
-
-@manager_flamenco.command
-def create_test_job(manager_id, user_email, project_url):
-    """Creates a test job for a given manager."""
-
-    from pillar.api.utils import dumps, str2id
-
-    manager_id = str2id(manager_id)
-    authentication.force_cli_user()
-
-    # Find user
-    users_coll = current_app.db()['users']
-    user = users_coll.find_one({'email': user_email}, projection={'_id': 1})
-    if not user:
-        raise ValueError('User with email %r not found' % user_email)
-
-    # Find project
-    projs_coll = current_app.db()['projects']
-    proj = projs_coll.find_one({'url': project_url},
-                               projection={'_id': 1})
-    if not proj:
-        log.error('Unable to find project url=%s', project_url)
-        return 1
-
-    # Create the job
-    job = flamenco.current_flamenco.job_manager.api_create_job(
-        u'CLI test job',
-        u'Test job created from the server CLI',
-        u'sleep',
-        {
-            'frames': '1-30, 40-44',
-            'chunk_size': 13,
-            'time_in_seconds': 3,
-        },
-        proj['_id'], user['_id'], manager_id)
-
-    log.info('Job created:\n%s', dumps(job, indent=4))
-
-
-@manager_flamenco.command
-def make_admin(user_email):
-    """Grants the user flamenco-admin role."""
-
-    from pillar.api.service import do_badger
-
-    _, status = do_badger('grant', user_email, u'flamenco-admin')
-    if status != 204:
-        log.error('Unable to find user %s', user_email)
-        return 1
-
-    log.info('Done.')
-    return 0
-
-
-@manager_flamenco.command
-def revoke_admin(user_email):
-    """Revokes the user's flamenco-admin role."""
-
-    from pillar.api.service import do_badger
-
-    _, status = do_badger('revoke', user_email, u'flamenco-admin')
-    if status != 204:
-        log.error('Unable to find user %s', user_email)
-        return 1
-
-    log.info('Done.')
-    return 0
-
-manager.add_command("flamenco", manager_flamenco)
diff --git a/packages/flamenco/flamenco/eve_settings.py b/packages/flamenco/flamenco/eve_settings.py
deleted file mode 100644
index 0a457fb3046017744b4d52e8b9a9d1f4300fce35..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/eve_settings.py
+++ /dev/null
@@ -1,344 +0,0 @@
-from eve import ID_FIELD
-
-
-managers_schema = {
-    'name': {
-        'type': 'string',
-        'required': True,
-    },
-    # Short description of the manager
-    'description': {
-        'type': 'string',
-    },
-    # Used in the interface, should be a web address for a picture or logo
-    # representing the manager
-    'picture': {
-        'type': 'string',
-    },
-    # Full web address of the host. Use for internal queries about status of
-    # workers or other operations.
-    'url': {
-        'type': 'string',
-    },
-    # The jobs supported by the manager. This means that the manager has a task
-    # compiler capable of handling the tasks provided by the server so that
-    # the workers can understand them. Both server and manager need to agree
-    # on how a job type looks like (in terms of tasks).
-    'job_types': {
-        'type': 'dict',
-        # TODO: will be renamed to 'keyschema' in Cerberus 1.0
-        'propertyschema': {  # name of the job type
-            'type': 'string',
-        },
-        'valueschema': {  # configuration of the job type
-            'type': 'dict',
-            'schema': {
-                'vars': {
-                    'type': 'dict',
-                    # TODO: will be renamed to 'keyschema' in Cerberus 1.0
-                    'propertyschema': {  # name of the variable
-                        'type': 'string',
-                    },
-                    'valueschema': {  # variable values for different platforms.
-                        'type': 'dict',
-                        'schema': {
-                            'linux': {'type': 'string'},
-                            'darwin': {'type': 'string'},
-                            'win': {'type': 'string'},
-                        }
-                    }
-                },
-                # This is used to dynamically generate the interface form for
-                # submitting a new job.
-                'settings_schema': {
-                    'type': 'dict',
-                }
-            }
-        }
-    },
-    # Project IDs this manager is associated with.
-    'projects': {
-        'type': 'list',
-        'schema': {
-            'type': 'objectid',
-            'data_relation': {
-                'resource': 'projects',
-                'field': '_id',
-            }
-        },
-    },
-    # The service account of this manager.
-    'service_account': {
-        'type': 'objectid',
-        'required': True,
-        'data_relation': {
-            'resource': 'users',
-            'field': '_id',
-        },
-    },
-
-    # Received from the manager itself at startup.
-    'variables': {
-        'type': 'dict',
-        'allow_unknown': True,
-    },
-    'stats': {
-        'type': 'dict',
-        'schema': {
-            # TODO: determine which statistics should be stored here.
-            'nr_of_workers': {
-                'type': 'integer',
-            }
-        }
-    }
-
-}
-
-jobs_schema = {
-    'name': {
-        'type': 'string',
-        'required': True,
-    },
-    # Defines how we are going to parse the settings field, in order to generate
-    # the tasks list.
-    'job_type': {
-        'type': 'string',
-        'required': True,
-    },
-    # Remarks about the settings, the author or the system
-    'description': {
-        'type': 'string',
-    },
-    'project': {
-        'type': 'objectid',
-        'required': True,
-        'data_relation': {
-            'resource': 'projects',
-            'field': '_id',
-        },
-    },
-    'user': {
-        'type': 'objectid',
-        'required': True,
-        'data_relation': {
-            'resource': 'users',
-            'field': '_id',
-        },
-    },
-    # We currently say that a job, and all its tasks, will be assigned to one
-    # manager only. If one day we want to allow multiple managers to handle a
-    # job we can convert this to a list.
-    'manager': {
-        'type': 'objectid',
-        'data_relation': {
-            'resource': 'flamenco_managers',
-            'field': '_id',
-        },
-    },
-    'status': {
-        'type': 'string',
-        'allowed': [
-            'completed',
-            'active',
-            'canceled',
-            'cancel-requested',
-            'queued',
-            'failed'],
-        'default': 'queued'
-    },
-    # This number could be also be a float between 0 and 1.
-    'priority': {
-        'type': 'integer',
-        'min': 1,
-        'max': 100,
-        'default': 50
-    },
-    # Embedded summary of the status of all tasks of a job. Used when listing
-    # all jobs via a graphical interface.
-    'tasks_status': {
-        'type': 'dict',
-        'schema': {
-            'count': {'type': 'integer'},
-            'completed': {'type': 'integer'},
-            'failed': {'type': 'integer'},
-            'canceled': {'type': 'integer'}
-        }
-    },
-    # The most important part of a job. These custom values are parsed by the
-    # job compiler in order to generate the tasks.
-    'settings': {
-        'type': 'dict',
-        # TODO: introduce dynamic validator, based on job_type/task_type
-        'allow_unknown': True,
-    },
-}
-
-tasks_schema = {
-    'job': {
-        'type': 'objectid',
-        'data_relation': {
-            'resource': 'flamenco_jobs',
-            'field': '_id',
-        },
-    },
-    'manager': {
-        'type': 'objectid',
-        'data_relation': {
-            'resource': 'flamenco_managers',
-            'field': '_id',
-        },
-    },
-    'project': {
-        'type': 'objectid',
-        'required': True,
-        'data_relation': {
-            'resource': 'projects',
-            'field': '_id',
-        },
-    },
-    'user': {
-        'type': 'objectid',
-        'required': True,
-        'data_relation': {
-            'resource': 'users',
-            'field': '_id',
-        },
-    },
-    'name': {
-        'type': 'string',
-        'required': True,
-    },
-    'status': {
-        'type': 'string',
-        'allowed': [
-            'queued',
-            'claimed-by-manager',
-            'completed',
-            'active',
-            'cancel-requested',
-            'canceled',
-            'failed'],
-        'default': 'queued'
-    },
-    'priority': {
-        'type': 'integer',
-        'default': 0
-    },
-    'job_priority': {
-        'type': 'integer',
-        'min': 1,
-        'max': 100,
-        'default': 50
-    },
-    'job_type': {
-        'type': 'string',
-        'required': True,
-    },
-    'commands': {
-        'type': 'list',
-        'schema': {
-            'type': 'dict',
-            'schema': {
-                # The parser is inferred form the command name
-                'name': {
-                    'type': 'string',
-                    'required': True,
-                },
-                # In the list of built arguments for the command, we will
-                # replace the executable, which will be defined on the fly by
-                # the manager
-                'settings': {
-                    'type': 'dict',
-                    # TODO: introduce dynamic validator, based on job_type/task_type
-                    'allow_unknown': True,
-                },
-            }
-        },
-    },
-    'log': {
-        'type': 'string',
-    },
-    'activity': {
-        'type': 'string',
-        'maxlength': 128
-    },
-    'parents': {
-        'type': 'list',
-        'schema': {
-            'type': 'objectid',
-            'data_relation': {
-                'resource': 'flamenco_tasks',
-                'field': '_id',
-            }
-        },
-    },
-    'worker': {
-        'type': 'string',
-    },
-    'task_progress_percentage': {
-        'type': 'integer',
-    },
-    'current_command_index': {
-        'type': 'integer',
-    },
-    'command_progress_percentage': {
-        'type': 'integer',
-    },
-}
-
-task_logs_schema = {
-    'task': {
-        'type': 'objectid',
-        'data_relation': {
-            'resource': 'flamenco_tasks',
-            'field': '_id',
-        },
-        'required': True,
-    },
-    'received_on_manager': {
-        'type': 'datetime',
-        'required': True,
-    },
-    'log': {
-        'type': 'string',
-        'required': True,
-    },
-}
-
-_managers = {
-    'schema': managers_schema,
-    'item_methods': ['GET', 'PUT', 'PATCH'],
-    'public_methods': [],
-    'public_item_methods': [],
-}
-
-_jobs = {
-    'schema': jobs_schema,
-    'item_methods': ['GET', 'PUT', 'DELETE'],
-    'public_methods': [],
-    'public_item_methods': [],
-}
-
-_tasks = {
-    'schema': tasks_schema,
-    'item_methods': ['GET', 'PUT', 'DELETE'],
-    'public_methods': [],
-    'public_item_methods': [],
-}
-
-_task_logs = {
-    'schema': task_logs_schema,
-    'item_methods': ['GET', 'DELETE'],
-    'public_methods': [],
-    'public_item_methods': [],
-    'embedding': False,
-    'pagination': True,
-    'extra_response_fields': (ID_FIELD, ),  # don't include _etag etc.
-}
-
-DOMAIN = {
-    'flamenco_managers': _managers,
-    'flamenco_jobs': _jobs,
-    'flamenco_tasks': _tasks,
-    'flamenco_task_logs': _task_logs,
-}
diff --git a/packages/flamenco/flamenco/exceptions.py b/packages/flamenco/flamenco/exceptions.py
deleted file mode 100644
index 9e88b11761bfc689fc03c2ae66e12fd668e63794..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/exceptions.py
+++ /dev/null
@@ -1,9 +0,0 @@
-"""Flamenco-specific exceptions."""
-
-
-class FlamencoException(Exception):
-    """Base exception for all Flamenco-specific exceptions."""
-
-
-class JobSettingError(FlamencoException):
-    """Raised when a job's settings contains errors."""
diff --git a/packages/flamenco/flamenco/job_compilers/__init__.py b/packages/flamenco/flamenco/job_compilers/__init__.py
deleted file mode 100644
index 0c2dd26379d17b5af1da3ea91bbd697d01307d46..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/__init__.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import logging
-
-log = logging.getLogger(__name__)
-
-# Mapping from job type to compiler class.
-compilers = {}
-
-
-def register_compiler(job_type):
-    """Registers the decorated class as job compiler."""
-
-    def decorator(cls):
-        compilers[job_type] = cls
-        return cls
-
-    return decorator
-
-
-# Import subpackages to register the compilers
-from . import sleep, blender_render, blender_render_progressive
-
-
-def compile_job(job):
-    """Creates tasks from the given job."""
-
-    compiler = construct_job_compiler(job)
-    compiler.compile(job)
-
-
-def validate_job(job):
-    """Validates job settings.
-
-    :raises flamenco.exceptions.JobSettingError if the settings are bad.
-    """
-
-    compiler = construct_job_compiler(job)
-    compiler.validate_job_settings(job)
-
-
-def construct_job_compiler(job):
-    from flamenco import current_flamenco
-
-    compiler_class = find_job_compiler(job)
-    compiler = compiler_class(task_manager=current_flamenco.task_manager)
-
-    return compiler
-
-
-def find_job_compiler(job):
-    from .abstract_compiler import AbstractJobCompiler
-
-    # Get the compiler class for the job type.
-    job_type = job['job_type']
-    try:
-        compiler_class = compilers[job_type]
-    except KeyError:
-        log.error('No compiler for job type %r', job_type)
-        raise KeyError('No compiler for job type %r' % job_type)
-
-    assert issubclass(compiler_class, AbstractJobCompiler)
-    return compiler_class
diff --git a/packages/flamenco/flamenco/job_compilers/abstract_compiler.py b/packages/flamenco/flamenco/job_compilers/abstract_compiler.py
deleted file mode 100644
index e8f9f9b6241191c09414e30fa2572f4753df282c..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/abstract_compiler.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import attr
-from pillar import attrs_extra
-
-
-@attr.s
-class AbstractJobCompiler(object):
-    task_manager = attr.ib(cmp=False, hash=False)
-    _log = attrs_extra.log('%s.AbstractJobType' % __name__)
-
-    REQUIRED_SETTINGS = []
-
-    def compile(self, job):
-        """Compiles the job into a list of tasks.
-
-        Calls self.task_manager.create_task(...) to create the task in the database.
-        """
-        raise NotImplementedError()
-
-    def validate_job_settings(self, job):
-        """Raises an exception if required settings are missing.
-
-        :raises: flamenco.exceptions.JobSettingError
-        """
-        from pillarsdk import Resource
-
-        job_settings = job['settings']
-        if isinstance(job_settings, Resource):
-            job_settings = job_settings.to_dict()
-
-        missing = [key for key in self.REQUIRED_SETTINGS
-                   if key not in job_settings]
-
-        if not missing:
-            return
-
-        from flamenco import exceptions
-        job_id = job.get(u'_id', u'')
-        if job_id:
-            job_id = u' ' + job_id
-        if len(missing) == 1:
-            setting = u'setting'
-        else:
-            setting = u'settings'
-
-        raise exceptions.JobSettingError(
-            u'Job%s is missing required %s: %s' % (job_id, setting, u', '.join(missing)))
diff --git a/packages/flamenco/flamenco/job_compilers/blender_render.py b/packages/flamenco/flamenco/job_compilers/blender_render.py
deleted file mode 100644
index 78149c3711b0ccd64c3d2d248f5ad6297d821e9d..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/blender_render.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from pillar import attrs_extra
-
-from .abstract_compiler import AbstractJobCompiler
-from . import commands, register_compiler
-
-
-@register_compiler('blender-render')
-class BlenderRender(AbstractJobCompiler):
-    """Basic Blender render job."""
-    _log = attrs_extra.log('%s.BlenderRender' % __name__)
-
-    REQUIRED_SETTINGS = ('blender_cmd', 'filepath', 'render_output', 'frames', 'chunk_size')
-
-    def compile(self, job):
-        self._log.info('Compiling job %s', job['_id'])
-        self.validate_job_settings(job)
-
-        move_existing_task_id = self._make_move_out_of_way_task(job)
-        task_count = 1 + self._make_render_tasks(job, move_existing_task_id)
-
-        self._log.info('Created %i tasks for job %s', task_count, job['_id'])
-
-    def _make_move_out_of_way_task(self, job):
-        """Creates a MoveOutOfWay command to back up existing frames, and wraps it in a task.
-
-        :returns: the ObjectId of the created task.
-        :rtype: bson.ObjectId
-        """
-
-        import os.path
-
-        # The render path contains a filename pattern, most likely '######' or
-        # something similar. This has to be removed, so that we end up with
-        # the directory that will contain the frames.
-        render_dest_dir = os.path.dirname(job['settings']['render_output'])
-        cmd = commands.MoveOutOfWay(src=render_dest_dir)
-
-        task_id = self.task_manager.api_create_task(
-            job, [cmd], u'move-existing-frames')
-
-        return task_id
-
-    def _make_render_tasks(self, job, parent_task_id):
-        """Creates the render tasks for this job.
-
-        :returns: the number of tasks created
-        :rtype: int
-        """
-        from flamenco.utils import iter_frame_range, frame_range_merge
-
-        job_settings = job['settings']
-
-        task_count = 0
-        for chunk_frames in iter_frame_range(job_settings['frames'], job_settings['chunk_size']):
-            frame_range = frame_range_merge(chunk_frames)
-            frame_range_bstyle = frame_range_merge(chunk_frames, blender_style=True)
-
-            task_cmds = [
-                commands.BlenderRender(
-                    blender_cmd=job_settings['blender_cmd'],
-                    filepath=job_settings['filepath'],
-                    format=job_settings.get('format'),
-                    render_output=job_settings.get('render_output'),
-                    frames=frame_range_bstyle)
-            ]
-
-            name = 'blender-render-%s' % frame_range
-            self.task_manager.api_create_task(job, task_cmds, name, parents=[parent_task_id])
-            task_count += 1
-
-        return task_count
diff --git a/packages/flamenco/flamenco/job_compilers/blender_render_progressive.py b/packages/flamenco/flamenco/job_compilers/blender_render_progressive.py
deleted file mode 100644
index a766a08dde13f3e2fb2912eaf039064cd01ca410..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/blender_render_progressive.py
+++ /dev/null
@@ -1,239 +0,0 @@
-from pillar import attrs_extra
-
-from .blender_render import BlenderRender
-from . import commands, register_compiler
-
-
-@register_compiler('blender-render-progressive')
-class BlenderRenderProgressive(BlenderRender):
-    """Progressive Blender render job.
-
-    Creates a render task for each Cycles sample chunk, and creates merge
-    tasks to merge those render outputs into progressively refining output.
-
-    Intermediary files are created in a subdirectory of the render output path.
-    """
-
-    _log = attrs_extra.log('%s.BlenderRenderProgressive' % __name__)
-
-    REQUIRED_SETTINGS = ('blender_cmd', 'filepath', 'render_output', 'frames', 'chunk_size',
-                         'format', 'cycles_sample_count', 'cycles_num_chunks')
-
-    def compile(self, job):
-        import math
-        from pathlib2 import Path
-
-        self._log.info('Compiling job %s', job['_id'])
-        self.validate_job_settings(job)
-
-        job_settings = job['settings']
-        self.intermediate_path = Path(job_settings['render_output']).with_name('_intermediate')
-
-        move_existing_task_id = self._make_move_out_of_way_task(job)
-        task_count = 1
-
-        cycles_sample_count = int(job_settings['cycles_sample_count'])
-        self.cycles_num_chunks = int(job_settings['cycles_num_chunks'])
-        sample_count_per_chunk = int(math.ceil(float(cycles_sample_count) / self.cycles_num_chunks))
-
-        next_merge_task_deps = []
-        prev_samples_to = 0
-        for cycles_chunk_idx in range(int(job_settings['cycles_num_chunks'])):
-            # Compute the Cycles sample range for this chunk (chunk_idx in base-0), in base-1.
-            cycles_samples_from = cycles_chunk_idx * sample_count_per_chunk + 1
-            cycles_samples_to = min((cycles_chunk_idx + 1) * sample_count_per_chunk,
-                                    cycles_sample_count)
-
-            # Create render tasks for each frame chunk. Only this function uses the base-0
-            # chunk/sample numbers, so we also convert to the base-1 numbers that Blender
-            # uses.
-            render_task_ids = self._make_progressive_render_tasks(
-                job,
-                u'render-smpl%i-%i-frm%%s' % (cycles_samples_from, cycles_samples_to),
-                move_existing_task_id,
-                cycles_chunk_idx + 1,
-                cycles_samples_from,
-                cycles_samples_to,
-                task_priority=-cycles_chunk_idx * 10,
-            )
-            task_count += len(render_task_ids)
-
-            # Create progressive image merge tasks, based on previous list of render tasks
-            # and the just-created list.
-            if cycles_chunk_idx == 0:
-                next_merge_task_deps = render_task_ids
-            else:
-                merge_task_ids = self._make_merge_tasks(
-                    job,
-                    u'merge-to-smpl%i-frm%%s' % cycles_samples_to,
-                    cycles_chunk_idx + 1,
-                    next_merge_task_deps,
-                    render_task_ids,
-                    cycles_samples_to1=prev_samples_to,
-                    cycles_samples_from2=cycles_samples_from,
-                    cycles_samples_to2=cycles_samples_to,
-                    task_priority=-cycles_chunk_idx * 10 - 1,
-                )
-                task_count += len(merge_task_ids)
-                next_merge_task_deps = merge_task_ids
-            prev_samples_to = cycles_samples_to
-
-        self._log.info('Created %i tasks for job %s', task_count, job['_id'])
-
-    def validate_job_settings(self, job):
-        """Ensure that the job uses format=EXR."""
-        super(BlenderRenderProgressive, self).validate_job_settings(job)
-
-        from flamenco import exceptions
-
-        render_format = job['settings']['format']
-        if render_format.upper() != u'EXR':
-            raise exceptions.JobSettingError(
-                u'Job %s must use format="EXR", not %r' % (job[u'_id'], render_format))
-
-        # This is quite a limitation, but makes our code to predict the
-        # filename that Blender will use a lot simpler.
-        render_output = job['settings']['render_output']
-        if not render_output.endswith(u'######') or render_output.endswith(u'#######'):
-            raise exceptions.JobSettingError(
-                u'Setting "render_output" must end in exactly 6 "#" marks.')
-
-    def _make_progressive_render_tasks(self,
-                                       job, name_fmt, parents,
-                                       cycles_chunk_idx,
-                                       cycles_samples_from, cycles_samples_to,
-                                       task_priority):
-        """Creates the render tasks for this job.
-
-        :param parents: either a list of parents, one for each task, or a
-            single parent used for all tasks.
-        :param cycles_chunk_idx: base-1 sample chunk index
-
-        :returns: created task IDs, one render task per frame chunk.
-        :rtype: list
-        """
-
-        from bson import ObjectId
-        from flamenco.utils import iter_frame_range, frame_range_merge
-
-        job_settings = job['settings']
-
-        task_ids = []
-        frame_chunk_iter = iter_frame_range(job_settings['frames'], job_settings['chunk_size'])
-        for chunk_idx, chunk_frames in enumerate(frame_chunk_iter):
-            frame_range = frame_range_merge(chunk_frames)
-            frame_range_bstyle = frame_range_merge(chunk_frames, blender_style=True)
-
-            name = name_fmt % frame_range
-
-            render_output = self._render_output(cycles_samples_from, cycles_samples_to)
-
-            task_cmds = [
-                commands.BlenderRenderProgressive(
-                    blender_cmd=job_settings['blender_cmd'],
-                    filepath=job_settings['filepath'],
-                    format=job_settings.get('format'),
-                    # Don't render to actual render output, but to an intermediate file.
-                    render_output=unicode(render_output),
-                    frames=frame_range_bstyle,
-                    cycles_num_chunks=self.cycles_num_chunks,
-                    cycles_chunk=cycles_chunk_idx,
-                    cycles_samples_from=cycles_samples_from,
-                    cycles_samples_to=cycles_samples_to,
-                )
-            ]
-
-            if isinstance(parents, list):
-                parent_task_id = parents[chunk_idx]
-            else:
-                parent_task_id = parents
-
-            if not isinstance(parent_task_id, ObjectId):
-                raise TypeError('parents should be list of ObjectIds or ObjectId, not %s' % parents)
-
-            task_id = self.task_manager.api_create_task(
-                job, task_cmds, name, parents=[parent_task_id],
-                priority=task_priority)
-            task_ids.append(task_id)
-
-        return task_ids
-
-    def _render_output(self, cycles_samples_from, cycles_samples_to):
-        """Intermediate render output path, with ###### placeholder for the frame nr"""
-        render_fname = u'render-smpl-%i-%i-frm-######' % (cycles_samples_from, cycles_samples_to)
-        render_output = self.intermediate_path / render_fname
-        return render_output
-
-    def _merge_output(self, cycles_samples_to):
-        """Intermediate merge output path, with ###### placeholder for the frame nr"""
-        merge_fname = u'merge-smpl-%i-frm-######' % cycles_samples_to
-        merge_output = self.intermediate_path / merge_fname
-        return merge_output
-
-    def _make_merge_tasks(self, job, name_fmt,
-                          cycles_chunk_idx,
-                          parents1, parents2,
-                          cycles_samples_to1,
-                          cycles_samples_from2,
-                          cycles_samples_to2,
-                          task_priority):
-        """Creates merge tasks for each chunk, consisting of merges for each frame.
-
-        :param cycles_chunk_idx: base-1 sample chunk index
-
-        """
-
-        # Merging cannot happen unless we have at least two chunks
-        assert cycles_chunk_idx >= 2
-
-        from flamenco.utils import iter_frame_range, frame_range_merge
-
-        job_settings = job['settings']
-
-        task_ids = []
-
-        cycles_num_chunks = int(job_settings['cycles_num_chunks'])
-
-        weight1 = cycles_samples_to1
-        weight2 = cycles_samples_to2 - cycles_samples_from2 + 1
-
-        # Replace Blender formatting with Python formatting in render output path
-        if cycles_chunk_idx == 2:
-            # The first merge takes a render output as input1, subsequent ones take merge outputs.
-            # Merging only happens from Cycles chunk 2 (it needs two inputs, hence 2 chunks).
-            input1 = self._render_output(1, cycles_samples_to1)
-        else:
-            input1 = self._merge_output(cycles_samples_to1)
-        input2 = self._render_output(cycles_samples_from2, cycles_samples_to2)
-
-        if cycles_chunk_idx == cycles_num_chunks:
-            # At the last merge, we merge to the actual render output, not to intermediary.
-            output = job['settings']['render_output']
-        else:
-            output = self._merge_output(cycles_samples_to2)
-
-        frame_chunk_iter = iter_frame_range(job_settings['frames'], job_settings['chunk_size'])
-        for chunk_idx, chunk_frames in enumerate(frame_chunk_iter):
-            # Create a merge command for every frame in the chunk.
-            task_cmds = []
-            for framenr in chunk_frames:
-                task_cmds.append(
-                    commands.MergeProgressiveRenders(
-                        input1=unicode(input1).replace(u'######', u'%06i.exr') % framenr,
-                        input2=unicode(input2).replace(u'######', u'%06i.exr') % framenr,
-                        output=unicode(output).replace(u'######', u'%06i.exr') % framenr,
-                        weight1=weight1,
-                        weight2=weight2,
-                    ))
-
-            name = name_fmt % frame_range_merge(chunk_frames)
-
-            parent1 = parents1[chunk_idx]
-            parent2 = parents2[chunk_idx]
-
-            task_id = self.task_manager.api_create_task(
-                job, task_cmds, name, parents=[parent1, parent2],
-                priority=task_priority)
-            task_ids.append(task_id)
-
-        return task_ids
diff --git a/packages/flamenco/flamenco/job_compilers/commands.py b/packages/flamenco/flamenco/job_compilers/commands.py
deleted file mode 100644
index 6dfe66331d964f07c0f823a29ce7e45647ec0a3d..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/commands.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import attr
-
-
-@attr.s
-class AbstractCommand(object):
-    """Abstract Flamenco command.
-
-    Command settings are defined in subclasses using attr.ib().
-    """
-
-    @classmethod
-    def cmdname(cls):
-        """Returns the command name."""
-        from flamenco.utils import camel_case_to_lower_case_underscore
-
-        return camel_case_to_lower_case_underscore(unicode(cls.__name__))
-
-    def to_dict(self):
-        """Returns a dictionary representation of this command, for JSON serialisation."""
-
-        return {
-            u'name': self.cmdname(),
-            u'settings': attr.asdict(self),
-        }
-
-
-@attr.s
-class Sleep(AbstractCommand):
-    time_in_seconds = attr.ib(validator=attr.validators.instance_of(int))
-
-
-@attr.s
-class Echo(AbstractCommand):
-    message = attr.ib(validator=attr.validators.instance_of(unicode))
-
-
-@attr.s
-class BlenderRender(AbstractCommand):
-    # Blender executable to run.
-    blender_cmd = attr.ib(validator=attr.validators.instance_of(unicode))
-    # blend file path.
-    filepath = attr.ib(validator=attr.validators.instance_of(unicode))
-    # output format.
-    format = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(unicode)))
-    # output file path, defaults to the path in the blend file itself.
-    render_output = attr.ib(
-        validator=attr.validators.optional(attr.validators.instance_of(unicode)))
-
-    # list of frames to render, as frame range string.
-    frames = attr.ib(validator=attr.validators.instance_of(unicode))
-
-
-@attr.s
-class BlenderRenderProgressive(BlenderRender):
-    # Total number of Cycles sample chunks.
-    cycles_num_chunks = attr.ib(validator=attr.validators.instance_of(int))
-    # Cycle sample chunk to render in this command.
-    cycles_chunk = attr.ib(validator=attr.validators.instance_of(int))
-
-    # Cycles first sample number, base-1
-    cycles_samples_from = attr.ib(validator=attr.validators.instance_of(int))
-    # Cycles last sample number, base-1
-    cycles_samples_to = attr.ib(validator=attr.validators.instance_of(int))
-
-
-@attr.s
-class MoveOutOfWay(AbstractCommand):
-    """Moves a file or directory out of the way.
-
-    The destination is the same as the source, with the source's modification
-    timestamp appended to it.
-
-    :ivar src: source path
-    """
-
-    src = attr.ib(validator=attr.validators.instance_of(unicode))
-
-
-@attr.s
-class MergeProgressiveRenders(AbstractCommand):
-    """Merges two Cycles outputs into one by taking the weighted average.
-    """
-
-    input1 = attr.ib(validator=attr.validators.instance_of(unicode))
-    input2 = attr.ib(validator=attr.validators.instance_of(unicode))
-    output = attr.ib(validator=attr.validators.instance_of(unicode))
-
-    weight1 = attr.ib(validator=attr.validators.instance_of(int))
-    weight2 = attr.ib(validator=attr.validators.instance_of(int))
-
-    # Blender command to run in order to merge the two EXR files.
-    # This is usually determined by the Flamenco Manager configuration.
-    blender_cmd = attr.ib(validator=attr.validators.instance_of(unicode),
-                          default=u'{blender}')
diff --git a/packages/flamenco/flamenco/job_compilers/sleep.py b/packages/flamenco/flamenco/job_compilers/sleep.py
deleted file mode 100644
index a08aee4fe59cd5546233d6c31e231d3a0406b8a7..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/job_compilers/sleep.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from .abstract_compiler import AbstractJobCompiler
-from . import commands, register_compiler
-
-
-@register_compiler('sleep')
-class Sleep(AbstractJobCompiler):
-    """Sleeps for N seconds for each frame chunk."""
-
-    def compile(self, job):
-        from flamenco.utils import iter_frame_range, frame_range_merge
-
-        self._log.info('Compiling job %s', job['_id'])
-
-        job_settings = job['settings']
-        task_count = 0
-        for chunk_frames in iter_frame_range(job_settings['frames'], job_settings['chunk_size']):
-            task_cmds = [
-                commands.Echo(message=u'Preparing to sleep'),
-                commands.Sleep(time_in_seconds=job_settings['time_in_seconds']),
-            ]
-            name = 'sleep-%s' % frame_range_merge(chunk_frames)
-
-            self.task_manager.api_create_task(job, task_cmds, name)
-            task_count += 1
-
-        self._log.info('Created %i tasks for job %s', task_count, job['_id'])
diff --git a/packages/flamenco/flamenco/jobs/__init__.py b/packages/flamenco/flamenco/jobs/__init__.py
deleted file mode 100644
index 040081cdf401bf474cf7ab50ac786fd8254e1af1..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/jobs/__init__.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""Job management."""
-
-import collections
-import copy
-
-import attr
-
-import pillarsdk
-from pillar import attrs_extra
-from pillar.web.system_util import pillar_api
-
-from flamenco import current_flamenco
-
-CANCELABLE_JOB_STATES = {'active', 'queued', 'failed'}
-REQUEABLE_JOB_STATES = {'completed', 'canceled', 'failed'}
-TASK_FAIL_JOB_PERCENTAGE = 10  # integer from 0 to 100
-
-
-class ProjectSummary(object):
-    """Summary of the jobs in a project."""
-
-    def __init__(self):
-        self._counts = collections.defaultdict(int)
-        self._total = 0
-
-    def count(self, status):
-        self._counts[status] += 1
-        self._total += 1
-
-    def percentages(self):
-        """Generator, yields (status, percentage) tuples.
-
-        The percentage is on a 0-100 scale.
-        """
-
-        remaining = 100
-        last_index = len(self._counts) - 1
-
-        for idx, status in enumerate(sorted(self._counts.keys())):
-            if idx == last_index:
-                yield (status, remaining)
-                continue
-
-            perc = float(self._counts[status]) / self._total
-            whole_perc = int(round(perc * 100))
-            remaining -= whole_perc
-
-            yield (status, whole_perc)
-
-
-@attr.s
-class JobManager(object):
-    _log = attrs_extra.log('%s.JobManager' % __name__)
-
-    def api_create_job(self, job_name, job_desc, job_type, job_settings,
-                       project_id, user_id, manager_id, priority=50):
-        """Creates a job, returning a dict with its generated fields."""
-
-        from eve.methods.post import post_internal
-
-        job = {
-            'name': job_name,
-            'description': job_desc,
-            'job_type': job_type,
-            'project': project_id,
-            'user': user_id,
-            'manager': manager_id,
-            'status': 'queued',
-            'priority': int(priority),
-            'settings': copy.deepcopy(job_settings),
-        }
-
-        self._log.info('Creating job %r for user %s and manager %s',
-                       job_name, user_id, manager_id)
-
-        r, _, _, status = post_internal('flamenco_jobs', job)
-        if status != 201:
-            self._log.error('Status should be 201, not %i: %s' % (status, r))
-            raise ValueError('Unable to create Flamenco job, status code %i' % status)
-
-        job.update(r)
-        return job
-
-    def jobs_for_project(self, project_id):
-        """Returns the jobs for the given project.
-
-        :returns: {'_items': [job, job, ...], '_meta': {Eve metadata}}
-        """
-        from .sdk import Job
-
-        api = pillar_api()
-        try:
-            j = Job.all({
-                'where': {'project': project_id},
-                'sort': [('_updated', -1), ('_created', -1)],
-            }, api=api)
-        except pillarsdk.ResourceNotFound:
-            return {'_items': [], '_meta': {'total': 0}}
-        return j
-
-    def job_status_summary(self, project_id):
-        """Returns number of shots per shot status for the given project.
-
-        :rtype: ProjectSummary
-        """
-        from .sdk import Job
-
-        api = pillar_api()
-
-        # TODO: turn this into an aggregation call to do the counting on
-        # MongoDB.
-        try:
-            jobs = Job.all({
-                'where': {
-                    'project': project_id,
-                },
-                'projection': {
-                    'status': 1,
-                },
-                'order': [
-                    ('status', 1),
-                ],
-            }, api=api)
-        except pillarsdk.ResourceNotFound:
-            return ProjectSummary()
-
-        # FIXME: this breaks when we hit the pagination limit.
-        summary = ProjectSummary()
-        for job in jobs['_items']:
-            summary.count(job['status'])
-
-        return summary
-
-    def update_job_after_task_status_change(self, job_id, task_id, new_task_status):
-        """Updates the job status based on the status of this task and other tasks in the job.
-        """
-
-        def __job_active_if_queued():
-            """Set job to active if it was queued."""
-
-            jobs_coll = current_flamenco.db('jobs')
-            job = jobs_coll.find_one(job_id, projection={'status': 1})
-            if job['status'] == 'queued':
-                self._log.info('Job %s became active because one of its tasks %s changed '
-                               'status to %s', job_id, task_id, new_task_status)
-                self.api_set_job_status(job_id, 'active')
-
-        if new_task_status == {'queued', 'cancel-requested', 'claimed-by-manager'}:
-            # Ignore; for now re-queueing a task doesn't change the job status.
-            # Also, canceling a single task has no influence on the job itself.
-            # A task being claimed by the manager also doesn't change job status.
-            return
-
-        if new_task_status == 'canceled':
-            # This could be the last cancel-requested task to go to 'canceled.
-            tasks_coll = current_flamenco.db('tasks')
-            statuses = tasks_coll.distinct('status', {'job': job_id})
-            if 'cancel-requested' not in statuses:
-                self._log.info('Last task %s of job %s went from cancel-requested to canceld.',
-                               task_id, job_id)
-                self.api_set_job_status(job_id, 'canceled')
-            return
-
-        if new_task_status == 'failed':
-            # Count the number of failed tasks. If it is more than 10, fail the job.
-            tasks_coll = current_flamenco.db('tasks')
-            total_count = tasks_coll.find({'job': job_id}).count()
-            fail_count = tasks_coll.find({'job': job_id, 'status': 'failed'}).count()
-            fail_perc = fail_count / float(total_count) * 100
-            if fail_perc >= TASK_FAIL_JOB_PERCENTAGE:
-                self._log.warning('Failing job %s because %i of its %i tasks (%i%%) failed',
-                                  job_id, fail_count, total_count, fail_perc)
-                self.api_set_job_status(job_id, 'failed')
-            else:
-                self._log.warning('Task %s of job %s failed; '
-                                  'only %i of its %i tasks failed (%i%%), so ignoring for now',
-                                  task_id, job_id, fail_count, total_count, fail_perc)
-                __job_active_if_queued()
-            return
-
-        if new_task_status in {'active', 'processing'}:
-            self._log.info('Job %s became active because one of its tasks %s changed status to %s',
-                           job_id, task_id, new_task_status)
-            self.api_set_job_status(job_id, 'active')
-            return
-
-        if new_task_status == 'completed':
-            # Maybe all tasks are completed, which should complete the job.
-            tasks_coll = current_flamenco.db('tasks')
-            statuses = tasks_coll.distinct('status', {'job': job_id})
-            if statuses == ['completed']:
-                self._log.info('All tasks (last one was %s) of job %s are completed, '
-                               'setting job to completed.',
-                               task_id, job_id)
-                self.api_set_job_status(job_id, 'completed')
-            else:
-                __job_active_if_queued()
-            return
-
-        self._log.warning('Task %s of job %s obtained status %s, '
-                          'which we do not know how to handle.',
-                          task_id, job_id, new_task_status)
-
-    def web_set_job_status(self, job_id, new_status):
-        """Web-level call to updates the job status."""
-        from .sdk import Job
-
-        api = pillar_api()
-        job = Job({'_id': job_id})
-        job.patch({'op': 'set-job-status',
-                   'status': new_status}, api=api)
-
-    def api_set_job_status(self, job_id, new_status):
-        """API-level call to updates the job status."""
-
-        self._log.info('Setting job %s status to "%s"', job_id, new_status)
-
-        jobs_coll = current_flamenco.db('jobs')
-        curr_job = jobs_coll.find_one({'_id': job_id}, projection={'status': 1})
-        old_status = curr_job['status']
-
-        current_flamenco.update_status('jobs', job_id, new_status)
-        self.handle_job_status_change(job_id, old_status, new_status)
-
-    def handle_job_status_change(self, job_id, old_status, new_status):
-        """Updates task statuses based on this job status transition."""
-
-        query = None
-        to_status = None
-        if new_status in {'completed', 'canceled'}:
-            # Nothing to do; this will happen as a response to all tasks receiving this status.
-            return
-        elif new_status == 'active':
-            # Nothing to do; this happens when a task gets started, which has nothing to
-            # do with other tasks in the job.
-            return
-        elif new_status in {'cancel-requested', 'failed'}:
-            # Request cancel of any task that might run on the manager.
-            cancelreq_result = current_flamenco.update_status_q(
-                'tasks',
-                {'job': job_id, 'status': {'$in': ['active', 'claimed-by-manager']}},
-                'cancel-requested')
-            # Directly cancel any task that might run in the future, but is not touched by
-            # a manager yet.
-            current_flamenco.update_status_q(
-                'tasks',
-                {'job': job_id, 'status': 'queued'},
-                'canceled')
-
-            # If the new status is cancel-requested, and no tasks were marked as cancel-requested,
-            # we can directly transition the job to 'canceled', without waiting for more task
-            # updates.
-            if new_status == 'cancel-requested' and cancelreq_result.modified_count == 0:
-                self._log.info('handle_job_status_change(%s, %s, %s): no cancel-requested tasks, '
-                               'so transitioning directly to canceled',
-                               job_id, old_status, new_status)
-                self.api_set_job_status(job_id, 'canceled')
-            return
-        elif new_status == 'queued':
-            if old_status == 'completed':
-                # Re-queue all tasks except cancel-requested; those should remain
-                # untouched; changing their status is only allowed by managers, to avoid
-                # race conditions.
-                query = {'status': {'$ne': 'cancel-requested'}}
-            else:
-                # Re-queue any non-completed task. Cancel-requested tasks should also be
-                # untouched; changing their status is only allowed by managers, to avoid
-                # race conditions.
-                query = {'status': {'$nin': ['completed', 'cancel-requested']}}
-            to_status = 'queued'
-
-        if query is None:
-            self._log.debug('Job %s status change from %s to %s has no effect on tasks.',
-                            job_id, old_status, new_status)
-            return
-        if to_status is None:
-            self._log.error('Job %s status change from %s to %s has to_status=None, aborting.',
-                            job_id, old_status, new_status)
-            return
-
-        # Update the tasks.
-        query['job'] = job_id
-
-        current_flamenco.update_status_q('tasks', query, to_status)
-
-
-def setup_app(app):
-    from . import eve_hooks, patch
-
-    eve_hooks.setup_app(app)
-    patch.setup_app(app)
diff --git a/packages/flamenco/flamenco/jobs/eve_hooks.py b/packages/flamenco/flamenco/jobs/eve_hooks.py
deleted file mode 100644
index 69836844a86888e17fa27283ed46b11ca6abb553..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/jobs/eve_hooks.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-import logging
-
-import werkzeug.exceptions as wz_exceptions
-from pillar.api.utils.authorization import user_matches_roles
-
-from flamenco import current_flamenco, ROLES_REQUIRED_TO_VIEW_ITEMS
-
-log = logging.getLogger(__name__)
-
-
-def before_inserting_jobs(jobs):
-    from flamenco import job_compilers, exceptions
-
-    for job in jobs:
-        try:
-            job_compilers.validate_job(job)
-        except exceptions.JobSettingError as ex:
-            # We generally only submit one job at a time anyway.
-            raise wz_exceptions.BadRequest('Invalid job: %s' % ex)
-
-
-def after_inserting_jobs(jobs):
-    from flamenco import job_compilers
-
-    for job in jobs:
-        # Prepare storage dir for the job files?
-        # Generate tasks
-        log.info('Generating tasks for job {}'.format(job['_id']))
-        job_compilers.compile_job(job)
-
-
-def check_job_permission_fetch(job_doc):
-
-    if current_flamenco.current_user_is_flamenco_admin():
-        return
-
-    if not current_flamenco.manager_manager.user_is_manager():
-        # Subscribers can read Flamenco jobs.
-        if user_matches_roles(ROLES_REQUIRED_TO_VIEW_ITEMS):
-            return
-        raise wz_exceptions.Forbidden()
-
-    mngr_doc_id = job_doc.get('manager')
-    if not current_flamenco.manager_manager.user_manages(mngr_doc_id=mngr_doc_id):
-        raise wz_exceptions.Forbidden()
-
-
-def check_job_permission_fetch_resource(response):
-    from pylru import lrudecorator
-
-    if current_flamenco.current_user_is_flamenco_admin():
-        return
-
-    if not current_flamenco.manager_manager.user_is_manager():
-        # Subscribers can read Flamenco jobs.
-        if user_matches_roles(ROLES_REQUIRED_TO_VIEW_ITEMS):
-            return
-        raise wz_exceptions.Forbidden()
-
-    @lrudecorator(32)
-    def user_managers(mngr_doc_id):
-        return current_flamenco.manager_manager.user_manages(mngr_doc_id=mngr_doc_id)
-
-    items = response['_items']
-    to_remove = []
-    for idx, job_doc in enumerate(items):
-        if not user_managers(job_doc.get('manager')):
-            to_remove.append(idx)
-
-    for idx in reversed(to_remove):
-        del items[idx]
-
-    response['_meta']['total'] -= len(items)
-
-
-def check_job_permissions_modify(job_doc, original_doc=None):
-    """For now, only admins are allowed to create, edit, and delete jobs."""
-
-    if not current_flamenco.current_user_is_flamenco_admin():
-        raise wz_exceptions.Forbidden()
-
-    # FIXME: check user access to the project.
-
-    handle_job_status_update(job_doc, original_doc)
-
-
-def handle_job_status_update(job_doc, original_doc):
-    """Calls upon the JobManager to handle a job status update, if there is any."""
-
-    if original_doc is None:
-        return
-
-    job_id = job_doc.get('_id')
-    if not job_id:
-        log.warning('handle_job_status_update: No _id in new job document, rejecting')
-        raise wz_exceptions.UnprocessableEntity('missing _id')
-
-    try:
-        old_status = original_doc['status']
-    except KeyError:
-        log.info('handle_job_status_update: No status in old job document %s, ignoring', job_id)
-        return
-
-    try:
-        new_status = job_doc['status']
-    except KeyError:
-        log.warning('handle_job_status_update: No status in new job document %s, rejecting', job_id)
-        raise wz_exceptions.UnprocessableEntity('missing status field')
-
-    if old_status == new_status:
-        # No change, so nothing to handle.
-        return
-
-    from flamenco import current_flamenco
-    current_flamenco.job_manager.handle_job_status_change(job_id, old_status, new_status)
-
-
-def setup_app(app):
-    app.on_insert_flamenco_jobs += before_inserting_jobs
-    app.on_inserted_flamenco_jobs += after_inserting_jobs
-    app.on_fetched_item_flamenco_jobs += check_job_permission_fetch
-    app.on_fetched_resource_flamenco_jobs += check_job_permission_fetch_resource
-
-    app.on_insert_flamenco_jobs += check_job_permissions_modify
-    app.on_update_flamenco_jobs += check_job_permissions_modify
-    app.on_replace_flamenco_jobs += check_job_permissions_modify
-    app.on_delete_flamenco_jobs += check_job_permissions_modify
diff --git a/packages/flamenco/flamenco/jobs/patch.py b/packages/flamenco/flamenco/jobs/patch.py
deleted file mode 100644
index d741cf0418dd389eb9c066f12610d77fda9e27e9..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/jobs/patch.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""Job patching support.
-
-TODO Sybren: merge identical code in jobs/patch.py and tasks/patch.py into
-something more generic/reusable.
-"""
-
-import logging
-
-import werkzeug.exceptions as wz_exceptions
-from flask import Blueprint, request
-from pillar.api.utils import authorization, authentication, str2id
-
-log = logging.getLogger(__name__)
-patch_api_blueprint = Blueprint('flamenco.jobs.patch', __name__)
-
-patch_handlers = {}
-
-
-def patch_handler(operation):
-    """Decorator, marks the decorated function as PATCH handler."""
-
-    def decorator(func):
-        patch_handlers[operation] = func
-        return func
-
-    return decorator
-
-
-@patch_api_blueprint.route('/<job_id>', methods=['PATCH'])
-@authorization.require_login()
-def patch_job(job_id):
-    # Parse the request
-    job_id = str2id(job_id)
-    patch = request.get_json()
-    if not patch:
-        raise wz_exceptions.BadRequest('Patch must contain JSON')
-
-    try:
-        patch_op = patch['op']
-    except KeyError:
-        raise wz_exceptions.BadRequest("PATCH should contain 'op' key to denote operation.")
-
-    log.debug('User %s wants to PATCH "%s" job %s',
-              authentication.current_user_id(), patch_op, job_id)
-
-    # Find the PATCH handler for the operation.
-    try:
-        handler = patch_handlers[patch_op]
-    except KeyError:
-        log.warning('No PATCH handler for operation %r', patch_op)
-        raise wz_exceptions.BadRequest('Operation %r not supported' % patch_op)
-
-    # Let the PATCH handler do its thing.
-    return handler(job_id, patch)
-
-
-@patch_handler(u'set-job-status')
-@authorization.require_login(require_roles={u'flamenco-admin'})
-def patch_set_job_status(job_id, patch):
-    """Updates a job's status in the database."""
-
-    from flamenco import current_flamenco
-    from pillar.api.utils import str2id
-    from pillar.api.utils.authentication import current_user_id
-
-    new_status = patch['status']
-    job_id = str2id(job_id)
-
-    log.info('User %s uses PATCH to set job %s status to "%s"',
-             current_user_id(), job_id, new_status)
-    try:
-        current_flamenco.job_manager.api_set_job_status(job_id, new_status)
-    except ValueError:
-        raise wz_exceptions.UnprocessableEntity('Status %s is invalid' % new_status)
-
-    return '', 204
-
-
-def setup_app(app):
-    app.register_api_blueprint(patch_api_blueprint, url_prefix='/flamenco/jobs')
diff --git a/packages/flamenco/flamenco/jobs/routes.py b/packages/flamenco/flamenco/jobs/routes.py
deleted file mode 100644
index de4cadb7f43bb18b87c283a4cca939a6e292ce3d..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/jobs/routes.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-import logging
-
-from flask import Blueprint, render_template, request
-import flask_login
-import werkzeug.exceptions as wz_exceptions
-
-from pillar.web.system_util import pillar_api
-
-from flamenco.routes import flamenco_project_view
-from flamenco import current_flamenco, ROLES_REQUIRED_TO_VIEW_ITEMS
-
-blueprint = Blueprint('flamenco.jobs', __name__, url_prefix='/jobs')
-perproject_blueprint = Blueprint('flamenco.jobs.perproject', __name__,
-                                 url_prefix='/<project_url>/jobs')
-log = logging.getLogger(__name__)
-
-# The job statuses that can be set from the web-interface.
-ALLOWED_JOB_STATUSES_FROM_WEB = {'cancel-requested', 'queued'}
-
-
-@perproject_blueprint.route('/', endpoint='index')
-@flamenco_project_view(extension_props=False)
-def for_project(project, job_id=None, task_id=None):
-    jobs = current_flamenco.job_manager.jobs_for_project(project['_id'])
-    return render_template('flamenco/jobs/list_for_project.html',
-                           stats={'nr_of_jobs': u'∞', 'nr_of_tasks': u'∞'},
-                           jobs=jobs['_items'],
-                           open_job_id=job_id,
-                           open_task_id=task_id,
-                           project=project)
-
-
-@perproject_blueprint.route('/with-task/<task_id>')
-@flamenco_project_view()
-def for_project_with_task(project, task_id):
-    from flamenco.tasks.sdk import Task
-
-    api = pillar_api()
-    task = Task.find(task_id, {'projection': {'job': 1}}, api=api)
-    return for_project(project, job_id=task['job'], task_id=task_id)
-
-
-@perproject_blueprint.route('/<job_id>')
-@flamenco_project_view(extension_props=True)
-def view_job(project, flamenco_props, job_id):
-    if not request.is_xhr:
-        return for_project(project, job_id=job_id)
-
-    # Job list is public, job details are not.
-    if not flask_login.current_user.has_role(*ROLES_REQUIRED_TO_VIEW_ITEMS):
-        raise wz_exceptions.Forbidden()
-
-    from .sdk import Job
-
-    api = pillar_api()
-    job = Job.find(job_id, api=api)
-
-    from . import CANCELABLE_JOB_STATES, REQUEABLE_JOB_STATES
-
-    write_access = current_flamenco.current_user_is_flamenco_admin()
-
-    return render_template('flamenco/jobs/view_job_embed.html',
-                           job=job,
-                           project=project,
-                           flamenco_props=flamenco_props.to_dict(),
-                           flamenco_context=request.args.get('context'),
-                           can_cancel_job=write_access and job['status'] in CANCELABLE_JOB_STATES,
-                           can_requeue_job=write_access and job['status'] in REQUEABLE_JOB_STATES)
-
-
-@perproject_blueprint.route('/<job_id>/depsgraph')
-@flamenco_project_view(extension_props=False)
-def view_job_depsgraph(project, job_id):
-
-    # Job list is public, job details are not.
-    if not flask_login.current_user.has_role(*ROLES_REQUIRED_TO_VIEW_ITEMS):
-        raise wz_exceptions.Forbidden()
-
-    if request.is_xhr:
-        from flask import jsonify
-        from flamenco.tasks import COLOR_FOR_TASK_STATUS
-
-        # Return the vis.js nodes and edges as JSON
-        tasks = current_flamenco.task_manager.tasks_for_job(job_id)
-        nodes = []
-        edges = []
-
-        # Make a mapping from database ID to task index
-        tid_to_idx = {task['_id']: tidx
-                      for tidx, task in enumerate(tasks._items)}
-
-        for task in sorted(tasks._items, key=lambda task: task['priority']):
-            task_id = tid_to_idx[task['_id']]
-            nodes.append({
-                'id': task_id,
-                'label': task['name'],
-                'shape': 'box',
-                'color': COLOR_FOR_TASK_STATUS[task['status']],
-            })
-            if task.parents:
-                for parent in task.parents:
-                    edges.append({
-                        'from': task_id,
-                        'to': tid_to_idx[parent],
-                        'arrows': 'to',
-                    })
-        return jsonify(nodes=nodes, edges=edges)
-
-    return render_template('flamenco/jobs/depsgraph.html',
-                           job_id=job_id,
-                           project=project)
-
-
-@blueprint.route('/<job_id>/set-status', methods=['POST'])
-def set_job_status(job_id):
-    from flask_login import current_user
-
-    new_status = request.form['status']
-    if new_status not in ALLOWED_JOB_STATUSES_FROM_WEB:
-        log.warning('User %s tried to set status of job %s to disallowed status "%s"; denied.',
-                    current_user.objectid, job_id, new_status)
-        raise wz_exceptions.UnprocessableEntity('Status "%s" not allowed' % new_status)
-
-    log.info('User %s set status of job %s to "%s"', current_user.objectid, job_id, new_status)
-    current_flamenco.job_manager.web_set_job_status(job_id, new_status)
-
-    return '', 204
-
-
-@blueprint.route('/<job_id>/redir')
-def redir_job_id(job_id):
-    """Redirects to the job view.
-
-    This saves the client from performing another request to find the project URL;
-    we do it for them.
-    """
-
-    from flask import redirect, url_for
-    from .sdk import Job
-    from pillarsdk import Project
-
-    api = pillar_api()
-    j = Job.find(job_id, {'projection': {'project': 1}}, api=api)
-    p = Project.find(j.project, {'projection': {'url': 1}}, api=api)
-
-    return redirect(url_for('flamenco.jobs.perproject.view_job',
-                            project_url=p.url,
-                            job_id=job_id))
diff --git a/packages/flamenco/flamenco/jobs/sdk.py b/packages/flamenco/flamenco/jobs/sdk.py
deleted file mode 100644
index b025e55982a196d263223cd493b2b79568d18942..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/jobs/sdk.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-from pillarsdk.resource import List
-from pillarsdk.resource import Find
-from pillarsdk.resource import Patch
-
-
-class Job(List, Find, Patch):
-    """Job class wrapping the REST nodes endpoint
-    """
-    path = 'flamenco/jobs'
-    ensure_query_projections = {'project': 1}
diff --git a/packages/flamenco/flamenco/managers/__init__.py b/packages/flamenco/flamenco/managers/__init__.py
deleted file mode 100644
index 09f8cbf50f3dfedfcb2a6f5542791f35de78a4e6..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/managers/__init__.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""Manager management."""
-
-import attr
-
-from pillar import attrs_extra
-
-from pillarsdk.resource import List
-from pillarsdk.resource import Find
-from pillarsdk.resource import Create
-from pillarsdk.resource import Post
-from pillarsdk.resource import Update
-from pillarsdk.resource import Delete
-from pillarsdk.resource import Replace
-
-
-class Manager(List, Find, Create, Post, Update, Delete, Replace):
-    """Manager class wrapping the REST nodes endpoint"""
-    path = 'flamenco/managers'
-
-
-@attr.s
-class ManagerManager(object):
-    _log = attrs_extra.log('%s.ManagerManager' % __name__)
-
-    def create_manager(self, service_account_id, name, description, url=None):
-        """Creates a new Flamenco manager.
-
-        Returns the MongoDB document.
-        """
-
-        from eve.methods.post import post_internal
-        from pillar.api.utils import str2id
-
-        mngr_doc = {
-            'name': name,
-            'description': description,
-            'job_types': {
-                'sleep': {
-                    'vars': {}
-                }
-            },
-            'service_account': str2id(service_account_id),
-        }
-        if url:
-            mngr_doc['url'] = url
-            self._log.info('Creating manager %r at %s', name, url)
-        else:
-            self._log.info('Creating manager %r', name)
-
-        r, _, _, status = post_internal('flamenco_managers', mngr_doc)
-        if status != 201:
-            self._log.error('Status should be 201, not %i: %s' % (status, r))
-            raise ValueError('Unable to create Flamenco manager, status code %i' % status)
-
-        mngr_doc.update(r)
-        return mngr_doc
-
-    def user_is_manager(self):
-        """Returns True iff the current user is a Flamenco manager service account."""
-
-        from pillar.api.utils.authorization import user_matches_roles
-
-        return user_matches_roles(require_roles={u'service', u'flamenco_manager'},
-                                  require_all=True)
-
-    def user_manages(self, mngr_doc_id=None, mngr_doc=None):
-        """
-        Returns True iff the current user is the Flamenco manager service account for this doc.
-        """
-
-        assert (mngr_doc_id is None) != (mngr_doc is None), \
-            'Either one or the other parameter must be given.'
-
-        from pillar.api.utils.authentication import current_user_id
-        from flamenco import current_flamenco
-
-        if not self.user_is_manager():
-            self._log.debug('user_manages(...): user is not a Flamenco manager service account')
-            return False
-
-        if mngr_doc is None:
-            mngr_coll = current_flamenco.db('managers')
-            mngr_doc = mngr_coll.find_one({'_id': mngr_doc_id},
-                                          {'service_account': 1})
-            if not mngr_doc:
-                self._log.debug('user_manages(%s): no such document', mngr_doc_id)
-                return False
-        else:
-            mngr_doc_id = mngr_doc['_id']
-
-        service_account = mngr_doc.get('service_account')
-        user_id = current_user_id()
-        if service_account != user_id:
-            self._log.debug('user_manages(%s): current user %s is not manager %s',
-                            mngr_doc_id, user_id, service_account)
-            return False
-
-        return True
-
-
-def setup_app(app):
-    from . import eve_hooks, api
-
-    eve_hooks.setup_app(app)
-    api.setup_app(app)
diff --git a/packages/flamenco/flamenco/managers/api.py b/packages/flamenco/flamenco/managers/api.py
deleted file mode 100644
index 03fb15497a05805e6e52961ba8cf9eb333774965..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/managers/api.py
+++ /dev/null
@@ -1,314 +0,0 @@
-import logging
-
-from flask import Blueprint, request
-import werkzeug.exceptions as wz_exceptions
-
-from pillar.api.utils import authorization, authentication
-
-api_blueprint = Blueprint('flamenco.managers', __name__)
-log = logging.getLogger(__name__)
-
-# Task statuses that are acceptable after a task has been set to 'cancel-requested'
-# TODO: maybe move allowed task transition handling to a different bit of code.
-ACCEPTED_AFTER_CANCEL_REQUESTED = {'canceled', 'failed', 'completed'}
-
-DEPSGRAPH_RUNNABLE_JOB_STATUSES = [u'queued', u'active', u'cancel-requested']
-DEPSGRAPH_CLEAN_SLATE_TASK_STATUSES = [u'queued', u'claimed-by-manager',
-                                       u'active', u'cancel-requested']
-DEPSGRAPH_MODIFIED_SINCE_TASK_STATUSES = [u'queued', u'claimed-by-manager']
-
-
-def manager_api_call(wrapped):
-    """Decorator, performs some standard stuff for Manager API endpoints."""
-    import functools
-
-    @authorization.require_login(require_roles={u'service', u'flamenco_manager'}, require_all=True)
-    @functools.wraps(wrapped)
-    def wrapper(manager_id, *args, **kwargs):
-        from flamenco import current_flamenco
-        from pillar.api.utils import str2id, mongo
-
-        manager_id = str2id(manager_id)
-        manager = mongo.find_one_or_404('flamenco_managers', manager_id)
-        if not current_flamenco.manager_manager.user_manages(mngr_doc=manager):
-            user_id = authentication.current_user_id()
-            log.warning('Service account %s sent startup notification for manager %s of another '
-                        'service account', user_id, manager_id)
-            raise wz_exceptions.Unauthorized()
-
-        return wrapped(manager_id, request.json, *args, **kwargs)
-
-    return wrapper
-
-
-@api_blueprint.route('/<manager_id>/startup', methods=['POST'])
-@manager_api_call
-def startup(manager_id, notification):
-    from flamenco import current_flamenco
-
-    log.info('Received startup notification from manager %s %s', manager_id, notification)
-
-    mngr_coll = current_flamenco.db('managers')
-    update_res = mngr_coll.update_one(
-        {'_id': manager_id},
-        {'$set': {
-            'url': notification['manager_url'],
-            'variables': notification['variables'],
-            'stats.nr_of_workers': notification['nr_of_workers'],
-        }}
-    )
-    if update_res.matched_count != 1:
-        log.warning('Updating manager %s matched %i documents.',
-                    manager_id, update_res.matched_count)
-        raise wz_exceptions.InternalServerError('Unable to update manager in database.')
-
-    return '', 204
-
-
-@api_blueprint.route('/<manager_id>/task-update-batch', methods=['POST'])
-@manager_api_call
-def task_update_batch(manager_id, task_updates):
-    from pillar.api.utils import jsonify
-
-    total_modif_count, handled_update_ids = handle_task_update_batch(manager_id, task_updates)
-
-    # Check which tasks are in state 'cancel-requested', as those need to be sent back.
-    # This MUST be done after we run the task update batch, as just-changed task statuses
-    # should be taken into account.
-    tasks_to_cancel = tasks_cancel_requested(manager_id)
-
-    response = {'modified_count': total_modif_count,
-                'handled_update_ids': handled_update_ids}
-    if tasks_to_cancel:
-        response['cancel_task_ids'] = list(tasks_to_cancel)
-
-    return jsonify(response)
-
-
-def handle_task_update_batch(manager_id, task_updates):
-    """Performs task updates.
-
-    Task status changes are generally always accepted. The only exception is when the
-    task ID is contained in 'tasks_to_cancel'; in that case only a transition to either
-    'canceled', 'completed' or 'failed' is accepted.
-
-    :returns: tuple (total nr of modified tasks, handled update IDs)
-    """
-
-    if not task_updates:
-        return 0, []
-
-    import dateutil.parser
-    from pillar.api.utils import str2id
-
-    from flamenco import current_flamenco, eve_settings
-
-    log.info('Received %i task updates from manager %s', len(task_updates), manager_id)
-
-    tasks_coll = current_flamenco.db('tasks')
-    logs_coll = current_flamenco.db('task_logs')
-
-    valid_statuses = set(eve_settings.tasks_schema['status']['allowed'])
-    handled_update_ids = []
-    total_modif_count = 0
-
-    for task_update in task_updates:
-        # Check that this task actually belongs to this manager, before we accept any updates.
-        update_id = str2id(task_update['_id'])
-        task_id = str2id(task_update['task_id'])
-        task_info = tasks_coll.find_one({'_id': task_id},
-                                        projection={'manager': 1, 'status': 1, 'job': 1})
-
-        # For now, we just ignore updates to non-existing tasks. Someone might have just deleted
-        # one, for example. This is not a reason to reject the entire batch.
-        if task_info is None:
-            log.warning('Manager %s sent update for non-existing task %s; ignoring',
-                        manager_id, task_id)
-            continue
-
-        if task_info['manager'] != manager_id:
-            log.warning('Manager %s sent update for task %s which belongs to other manager %s',
-                        manager_id, task_id, task_info['manager'])
-            continue
-
-        # Store the log for this task, allowing for duplicate log reports.
-        task_log = task_update.get('log')
-        if task_log:
-            received_on_manager = dateutil.parser.parse(task_update['received_on_manager'])
-            log_doc = {
-                '_id': update_id,
-                'task': task_id,
-                'received_on_manager': received_on_manager,
-                'log': task_log
-            }
-            logs_coll.replace_one({'_id': update_id}, log_doc, upsert=True)
-
-        # Modify the task, and append the log to the logs collection.
-        updates = {
-            'task_progress_percentage': task_update.get('task_progress_percentage', 0),
-            'current_command_index': task_update.get('current_command_index', 0),
-            'command_progress_percentage': task_update.get('command_progress_percentage', 0),
-        }
-
-        new_status = determine_new_task_status(manager_id, task_id, task_info,
-                                               task_update.get('task_status'), valid_statuses)
-        if new_status:
-            updates['status'] = new_status
-
-        new_activity = task_update.get('activity')
-        if new_activity:
-            updates['activity'] = new_activity
-        worker = task_update.get('worker')
-        if worker:
-            updates['worker'] = worker
-
-        result = tasks_coll.update_one({'_id': task_id}, {'$set': updates})
-        total_modif_count += result.modified_count
-
-        handled_update_ids.append(update_id)
-
-        # Update the task's job after updating the task itself.
-        if new_status:
-            current_flamenco.job_manager.update_job_after_task_status_change(
-                task_info['job'], task_id, new_status)
-
-    return total_modif_count, handled_update_ids
-
-
-def determine_new_task_status(manager_id, task_id, current_task_info, new_status, valid_statuses):
-    """Returns the new task status, or None if the task should not get a new status."""
-
-    if not new_status:
-        return None
-
-    current_status = current_task_info['status']
-    if new_status == current_status:
-        return None
-
-    if current_status == 'cancel-requested':
-        if new_status not in ACCEPTED_AFTER_CANCEL_REQUESTED:
-            log.warning('Manager %s wants to set task %s to status %r, but that is not allowed '
-                        'because the task is in status %s',
-                        manager_id, task_id, new_status, current_status)
-            return None
-
-    if new_status not in valid_statuses:
-        # We have to accept the invalid status, because we're too late in the update
-        # pipeline to do anything about it. The alternative is to drop the update or
-        # reject the entire batch of updates, which is more damaging to the workflow.
-        log.warning('Manager %s sent update for task %s with invalid status %r',
-                    manager_id, task_id, new_status)
-        return None
-
-    return new_status
-
-
-def tasks_cancel_requested(manager_id):
-    """Returns a set of tasks of status cancel-requested."""
-
-    from flamenco import current_flamenco, eve_settings
-
-    tasks_coll = current_flamenco.db('tasks')
-
-    task_ids = {
-        task['_id']
-        for task in tasks_coll.find({'manager': manager_id, 'status': 'cancel-requested'},
-                                    projection={'_id': 1})
-        }
-
-    log.debug('Returning %i tasks to be canceled by manager %s', len(task_ids), manager_id)
-    return task_ids
-
-
-@api_blueprint.route('/<manager_id>/depsgraph')
-@manager_api_call
-def get_depsgraph(manager_id, request_json):
-    """Returns the dependency graph of all tasks assigned to the given Manager.
-
-    Use the HTTP header X-Flamenco-If-Updated-Since to limit the dependency
-    graph to tasks that have been modified since that timestamp.
-    """
-
-    import dateutil.parser
-    from pillar.api.utils import jsonify, bsonify
-    from flamenco import current_flamenco
-    from flamenco.utils import report_duration
-
-    modified_since = request.headers.get('X-Flamenco-If-Updated-Since')
-
-    with report_duration(log, 'depsgraph query'):
-        tasks_coll = current_flamenco.db('tasks')
-
-        task_query = {
-            'manager': manager_id,
-            'status': {'$nin': ['active']},
-        }
-
-        if modified_since is None:
-            # "Clean slate" query, get runnable jobs first.
-            jobs_coll = current_flamenco.db('jobs')
-            jobs = jobs_coll.find({
-                'manager': manager_id,
-                'status': {'$in': DEPSGRAPH_RUNNABLE_JOB_STATUSES}},
-                projection={'_id': 1},
-            )
-            job_ids = [job['_id'] for job in jobs]
-            if not job_ids:
-                log.debug('Returning empty depsgraph')
-                return '', 204  # empty response
-
-            log.debug('Requiring jobs to be in %s', job_ids)
-            task_query['job'] = {'$in': job_ids}
-            task_query['status'] = {'$in': DEPSGRAPH_CLEAN_SLATE_TASK_STATUSES}
-        else:
-            # Not clean slate, just give all updated tasks assigned to this manager.
-            log.debug('Modified-since header: %s', modified_since)
-            modified_since = dateutil.parser.parse(modified_since)
-            task_query['_updated'] = {'$gt': modified_since}
-            task_query['status'] = {'$in': DEPSGRAPH_MODIFIED_SINCE_TASK_STATUSES}
-            log.debug('Querying all tasks changed since %s', modified_since)
-
-        cursor = tasks_coll.find(task_query)
-        depsgraph = list(cursor)
-
-    if len(depsgraph) == 0:
-        log.debug('Returning empty depsgraph')
-        if modified_since is not None:
-            return '', 304  # Not Modified
-    else:
-        log.info('Returning depsgraph of %i tasks', len(depsgraph))
-
-    # Update the task status in the database to move queued tasks to claimed-by-manager.
-    task_query['status'] = u'queued'
-    tasks_coll.update_many(task_query,
-                           {u'$set': {u'status': u'claimed-by-manager'}})
-
-    # Update the returned task statuses. Unfortunately Mongo doesn't support
-    # find_and_modify() on multiple documents.
-    for task in depsgraph:
-        if task['status'] == u'queued':
-            task['status'] = u'claimed-by-manager'
-
-    # Must be a dict to convert to BSON.
-    respdoc = {
-        'depsgraph': depsgraph,
-    }
-    if request.accept_mimetypes.best == 'application/bson':
-        resp = bsonify(respdoc)
-    else:
-        resp = jsonify(respdoc)
-
-    if depsgraph:
-        last_modification = max(task['_updated'] for task in depsgraph)
-        log.debug('Last modification was %s', last_modification)
-        # We need a format that can handle sub-second precision, which is not provided by the
-        # HTTP date format (RFC 1123). This means that we can't use the Last-Modified header, as
-        # it may be incorrectly interpreted and rewritten by HaProxy, Apache or other software
-        # in the path between client & server.
-        resp.headers['X-Flamenco-Last-Updated'] = last_modification.isoformat()
-        resp.headers['X-Flamenco-Last-Updated-Format'] = 'ISO-8601'
-    return resp
-
-
-def setup_app(app):
-    app.register_api_blueprint(api_blueprint, url_prefix='/flamenco/managers')
diff --git a/packages/flamenco/flamenco/managers/eve_hooks.py b/packages/flamenco/flamenco/managers/eve_hooks.py
deleted file mode 100644
index adc593e2195605ff356007c6a05d59e9e1ee7a04..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/managers/eve_hooks.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-import logging
-import werkzeug.exceptions as wz_exceptions
-
-log = logging.getLogger(__name__)
-
-
-def check_manager_permissions(mngr_doc):
-    from flamenco import current_flamenco
-
-    if current_flamenco.current_user_is_flamenco_admin():
-        return
-
-    if not current_flamenco.manager_manager.user_manages(mngr_doc=mngr_doc):
-        raise wz_exceptions.Forbidden()
-
-    log.debug('Allowing manager access to own document.')
-
-
-def check_manager_permissions_modify(mngr_doc, original_doc=None):
-    """For now, only admins are allowed to create, edit, and delete managers."""
-
-    from flamenco import current_flamenco
-
-    if not current_flamenco.current_user_is_flamenco_admin():
-        raise wz_exceptions.Forbidden()
-
-
-def setup_app(app):
-    app.on_fetched_item_flamenco_managers += check_manager_permissions
-    app.on_insert_flamenco_managers += check_manager_permissions_modify
-    app.on_update_flamenco_managers += check_manager_permissions_modify
-    app.on_replace_flamenco_managers += check_manager_permissions_modify
-    app.on_delete_flamenco_managers += check_manager_permissions_modify
diff --git a/packages/flamenco/flamenco/routes.py b/packages/flamenco/flamenco/routes.py
deleted file mode 100644
index a6259f30132c44e49e8fd8d32fc79cdea1b3b432..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/routes.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import functools
-import logging
-
-from flask import Blueprint, render_template, redirect, url_for
-
-import flask_login
-
-from pillar.web.utils import attach_project_pictures
-import pillar.web.subquery
-from pillar.web.system_util import pillar_api
-import pillarsdk
-
-from flamenco import current_flamenco
-
-
-blueprint = Blueprint('flamenco', __name__)
-log = logging.getLogger(__name__)
-
-
-@blueprint.route('/')
-def index():
-    api = pillar_api()
-
-    # TODO: add projections.
-    projects = current_flamenco.flamenco_projects()
-
-    for project in projects['_items']:
-        attach_project_pictures(project, api)
-
-    projs_with_summaries = [
-        (proj, current_flamenco.job_manager.job_status_summary(proj['_id']))
-        for proj in projects['_items']
-        ]
-
-    return render_template('flamenco/index.html',
-                           projs_with_summaries=projs_with_summaries)
-
-
-def error_project_not_setup_for_flamenco():
-    return render_template('flamenco/errors/project_not_setup.html')
-
-
-def flamenco_project_view(extra_project_projections=None, extension_props=False):
-    """Decorator, replaces the first parameter project_url with the actual project.
-
-    Assumes the first parameter to the decorated function is 'project_url'. It then
-    looks up that project, checks that it's set up for Flamenco, and passes it to the
-    decorated function.
-
-    If not set up for flamenco, uses error_project_not_setup_for_flamenco() to render
-    the response.
-
-    :param extra_project_projections: extra projections to use on top of the ones already
-        used by this decorator.
-    :type extra_project_projections: dict
-    :param extension_props: whether extension properties should be included. Includes them
-        in the projections, and verifies that they are there.
-    :type extension_props: bool
-    """
-
-    from . import EXTENSION_NAME
-
-    if callable(extra_project_projections):
-        raise TypeError('Use with @flamenco_project_view() <-- note the parentheses')
-
-    projections = {
-        '_id': 1,
-        'name': 1,
-        # We don't need this here, but this way the wrapped function has access
-        # to the orignal URL passed to it.
-        'url': 1,
-    }
-    if extra_project_projections:
-        projections.update(extra_project_projections)
-    if extension_props:
-        projections['extension_props.%s' % EXTENSION_NAME] = 1
-
-    def decorator(wrapped):
-        @functools.wraps(wrapped)
-        def wrapper(project_url, *args, **kwargs):
-            if isinstance(project_url, pillarsdk.Resource):
-                # This is already a resource, so this call probably is from one
-                # view to another. Assume the caller knows what he's doing and
-                # just pass everything along.
-                return wrapped(project_url, *args, **kwargs)
-
-            api = pillar_api()
-
-            project = pillarsdk.Project.find_by_url(
-                project_url,
-                {'projection': projections},
-                api=api)
-
-            is_flamenco = current_flamenco.is_flamenco_project(
-                project, test_extension_props=extension_props)
-            if not is_flamenco:
-                return error_project_not_setup_for_flamenco()
-
-            if extension_props:
-                pprops = project.extension_props.flamenco
-                return wrapped(project, pprops, *args, **kwargs)
-            return wrapped(project, *args, **kwargs)
-
-        return wrapper
-
-    return decorator
-
-
-@blueprint.route('/<project_url>')
-@flamenco_project_view(extension_props=False)
-def project_index(project):
-    return redirect(url_for('flamenco.jobs.perproject.index', project_url=project.url))
-
-
-@blueprint.route('/<project_url>/help')
-@flamenco_project_view(extension_props=False)
-def help(project):
-    return render_template('flamenco/help.html', statuses=[])
diff --git a/packages/flamenco/flamenco/setup.py b/packages/flamenco/flamenco/setup.py
deleted file mode 100644
index 469f768216d21710413ff6ca74d3d185ffe726e5..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/setup.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""Setting up projects for Flamenco.
-
-This is intended to be used by the CLI and unittests only, not tested
-for live/production situations.
-"""
-
-from __future__ import print_function, division
-
-import logging
-
-from bson import ObjectId
-from eve.methods.put import put_internal
-from flask import current_app
-
-from . import EXTENSION_NAME
-
-log = logging.getLogger(__name__)
-
-
-def _get_project(project_url):
-    """Find a project in the database, or SystemExit()s.
-
-    :param project_url: UUID of the project
-    :type: str
-    :return: the project
-    :rtype: dict
-    """
-
-    projects_collection = current_app.data.driver.db['projects']
-
-    # Find the project in the database.
-    project = projects_collection.find_one({'url': project_url})
-    if not project:
-        raise RuntimeError('Project %s does not exist.' % project_url)
-
-    return project
-
-
-def _update_project(project):
-    """Updates a project in the database, or SystemExit()s.
-
-    :param project: the project data, should be the entire project document
-    :type: dict
-    :return: the project
-    :rtype: dict
-    """
-
-    from pillar.api.utils import remove_private_keys
-
-    project_id = ObjectId(project['_id'])
-    project = remove_private_keys(project)
-    result, _, _, status_code = put_internal('projects', project, _id=project_id)
-
-    if status_code != 200:
-        raise RuntimeError("Can't update project %s, issues: %s", project_id, result)
-
-
-def setup_for_flamenco(project_url, replace=False):
-    """Adds Flamenco node types to the project.
-
-    Use --replace to replace pre-existing Flamenco node types
-    (by default already existing Flamenco node types are skipped).
-
-    Returns the updated project.
-    """
-
-    # Copy permissions from the project, then give everyone with PUT
-    # access also DELETE access.
-    project = _get_project(project_url)
-
-    # Set default extension properties. Be careful not to overwrite any
-    # properties that are already there.
-    eprops = project.setdefault('extension_props', {})
-    eprops.setdefault(EXTENSION_NAME, {
-        'managers': [],  # List of Flamenco manager IDs that have access to this project.
-    })
-
-    _update_project(project)
-
-    log.info('Project %s was updated for Flamenco.', project_url)
-
-    return project
-
-
-def create_manager(email, name, description, url=None):
-    """Creates a Flamenco manager with service account.
-
-    :returns: tuple (mngr_doc, account, token)
-    """
-
-    from pillar.cli import create_service_account
-    from flamenco import current_flamenco
-
-    def update_existing(service):
-        pass
-    account, token = create_service_account(email,
-                                            [u'flamenco_manager'],
-                                            {u'flamenco_manager': {}},
-                                            update_existing=update_existing)
-
-    mngr_doc = current_flamenco.manager_manager.create_manager(
-        account['_id'], name, description, url)
-
-    return mngr_doc, account, token
diff --git a/packages/flamenco/flamenco/static/assets/css/vendor/vis.min.css b/packages/flamenco/flamenco/static/assets/css/vendor/vis.min.css
deleted file mode 100644
index 3925eb8c77bca884adc3f0f31a891a081dbbf0f7..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/static/assets/css/vendor/vis.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3876c2', endColorstr='#385380', GradientType=0 );box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#9d9d9d', endColorstr='#c8c8c8', GradientType=0 )}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:#fff solid 1px;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}div.vis-color-picker{position:absolute;top:0;left:30px;margin-top:-140px;margin-left:30px;width:310px;height:444px;z-index:1;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow::after,div.vis-color-picker div.vis-arrow::before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313', GradientType=0 )}div.vis-color-picker div.vis-initial-color,div.vis-color-picker div.vis-new-color{width:140px;height:20px;top:380px;font-size:10px;color:rgba(0,0,0,.4);line-height:20px;vertical-align:middle;position:absolute}div.vis-color-picker div.vis-new-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:159px;text-align:right;padding-right:2px}div.vis-color-picker div.vis-initial-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:10px;text-align:left;padding-left:2px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px}div.vis-network div.vis-manipulation{border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fcfcfc', GradientType=0 );padding-top:4px;position:absolute;left:0;top:0;width:100%;height:28px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:5px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{float:left;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;background-repeat:no-repeat;height:24px;margin-left:10px;cursor:pointer;padding:0 8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{float:left;display:inline-block;width:1px;height:21px;background-color:#bdbdbd;margin:0 7px 0 15px}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px}.vis-current-time{background-color:#FF7F6E;width:2px;z-index:1;pointer-events:none}.vis-rolling-mode-btn{height:40px;width:40px;position:absolute;top:7px;right:20px;border-radius:50%;font-size:28px;cursor:pointer;opacity:.8;color:#fff;font-weight:700;text-align:center;background:#3876c2}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-custom-time{background-color:#6E94FF;width:2px;cursor:move;z-index:1}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-item{position:absolute;color:#1A1A1A;border-color:#97B0F8;border-width:1px;background-color:#D5DDF6;display:inline-block}.vis-item.vis-point.vis-selected,.vis-item.vis-selected{background-color:#FFF785}.vis-item.vis-selected{border-color:#FFC200;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-onUpdateTime-tooltip{position:absolute;background:#4f81bd;color:#fff;width:200px;text-align:center;white-space:nowrap;padding:5px;border-radius:1px}.vis-item .vis-delete,.vis-item .vis-delete-rtl{position:absolute;top:0;width:24px;height:24px;box-sizing:border-box;padding:0 5px;cursor:pointer;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{content:"\00D7";color:red;font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{position:absolute;width:100%;height:100%;top:0;left:0;cursor:move}.vis-item.vis-range .vis-drag-left,.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0}.vis-item.vis-range .vis-drag-left{left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{right:-4px;cursor:e-resize}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-labelset .vis-label.draggable,.vis-nesting-group{cursor:pointer}.vis-itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nested-group{background:#f5f5f5}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed-rtl:before{content:"\25C0"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-labelset,.vis-labelset .vis-label{position:relative;box-sizing:border-box}.vis-labelset{overflow:hidden}.vis-labelset .vis-label{left:0;top:0;width:100%;color:#4d4d4d;border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-panel{position:absolute;padding:0;margin:0;box-sizing:border-box}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-background,.vis-time-axis,.vis-timeline{overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content,.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-time-axis{position:relative}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-vertical-rtl{position:absolute;border-right:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-timeline{position:relative;border:1px solid #bfbfbf;padding:0;margin:0;box-sizing:border-box}
\ No newline at end of file
diff --git a/packages/flamenco/flamenco/static/assets/img/favicon.png b/packages/flamenco/flamenco/static/assets/img/favicon.png
deleted file mode 100644
index 79b0bc660c5457b76b98e219ddaef82dbba4aa3c..0000000000000000000000000000000000000000
Binary files a/packages/flamenco/flamenco/static/assets/img/favicon.png and /dev/null differ
diff --git a/packages/flamenco/flamenco/static/assets/img/placeholder.jpg b/packages/flamenco/flamenco/static/assets/img/placeholder.jpg
deleted file mode 100644
index 0c47f5838820230176dfe221b42424d1940968d9..0000000000000000000000000000000000000000
Binary files a/packages/flamenco/flamenco/static/assets/img/placeholder.jpg and /dev/null differ
diff --git a/packages/flamenco/flamenco/static/assets/js/vendor/clipboard.min.js b/packages/flamenco/flamenco/static/assets/js/vendor/clipboard.min.js
deleted file mode 100644
index 580433f1d89c0fc01c75c7e9ae2131deaacfdfcf..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/static/assets/js/vendor/clipboard.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * clipboard.js v1.5.12
- * https://zenorocha.github.io/clipboard.js
- *
- * Licensed MIT © Zeno Rocha
- */
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(r)return r(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n?n:t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a<o.length;a++)i(o[a]);return i}({1:[function(t,e,n){var o=t("matches-selector");e.exports=function(t,e,n){for(var i=n?t:t.parentNode;i&&i!==document;){if(o(i,e))return i;i=i.parentNode}}},{"matches-selector":5}],2:[function(t,e,n){function o(t,e,n,o,r){var a=i.apply(this,arguments);return t.addEventListener(n,a,r),{destroy:function(){t.removeEventListener(n,a,r)}}}function i(t,e,n,o){return function(n){n.delegateTarget=r(n.target,e,!0),n.delegateTarget&&o.call(t,n)}}var r=t("closest");e.exports=o},{closest:1}],3:[function(t,e,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){var e=Object.prototype.toString.call(t);return"[object Function]"===e}},{}],4:[function(t,e,n){function o(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!c.string(e))throw new TypeError("Second argument must be a String");if(!c.fn(n))throw new TypeError("Third argument must be a Function");if(c.node(t))return i(t,e,n);if(c.nodeList(t))return r(t,e,n);if(c.string(t))return a(t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function i(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}function r(t,e,n){return Array.prototype.forEach.call(t,function(t){t.addEventListener(e,n)}),{destroy:function(){Array.prototype.forEach.call(t,function(t){t.removeEventListener(e,n)})}}}function a(t,e,n){return s(document.body,t,e,n)}var c=t("./is"),s=t("delegate");e.exports=o},{"./is":3,delegate:2}],5:[function(t,e,n){function o(t,e){if(r)return r.call(t,e);for(var n=t.parentNode.querySelectorAll(e),o=0;o<n.length;++o)if(n[o]==t)return!0;return!1}var i=Element.prototype,r=i.matchesSelector||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector;e.exports=o},{}],6:[function(t,e,n){function o(t){var e;if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName)t.focus(),t.setSelectionRange(0,t.value.length),e=t.value;else{t.hasAttribute("contenteditable")&&t.focus();var n=window.getSelection(),o=document.createRange();o.selectNodeContents(t),n.removeAllRanges(),n.addRange(o),e=n.toString()}return e}e.exports=o},{}],7:[function(t,e,n){function o(){}o.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){function o(){i.off(t,o),e.apply(n,arguments)}var i=this;return o._=e,this.on(t,o,n)},emit:function(t){var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,i=n.length;for(o;i>o;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],i=[];if(o&&e)for(var r=0,a=o.length;a>r;r++)o[r].fn!==e&&o[r].fn._!==e&&i.push(o[r]);return i.length?n[t]=i:delete n[t],this}},e.exports=o},{}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","select"],r);else if("undefined"!=typeof o)r(n,e("select"));else{var a={exports:{}};r(a,i.select),i.clipboardAction=a.exports}}(this,function(t,e){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i=n(e),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},a=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),c=function(){function t(e){o(this,t),this.resolveOptions(e),this.initSelection()}return t.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action=e.action,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""},t.prototype.initSelection=function t(){this.text?this.selectFake():this.target&&this.selectTarget()},t.prototype.selectFake=function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px",this.fakeElem.style.top=(window.pageYOffset||document.documentElement.scrollTop)+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()},t.prototype.removeFake=function t(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)},t.prototype.selectTarget=function t(){this.selectedText=(0,i.default)(this.target),this.copyText()},t.prototype.copyText=function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(n){e=!1}this.handleResult(e)},t.prototype.handleResult=function t(e){e?this.emitter.emit("success",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)}):this.emitter.emit("error",{action:this.action,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})},t.prototype.clearSelection=function t(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()},t.prototype.destroy=function t(){this.removeFake()},a(t,[{key:"action",set:function t(){var e=arguments.length<=0||void 0===arguments[0]?"copy":arguments[0];if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==("undefined"==typeof e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:6}],9:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{"default":t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var l=i(e),u=i(n),f=i(o),d=function(t){function e(n,o){r(this,e);var i=a(this,t.call(this));return i.resolveOptions(o),i.listenClick(n),i}return c(e,t),e.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText},e.prototype.listenClick=function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})},e.prototype.onClick=function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new l.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})},e.prototype.defaultAction=function t(e){return s("action",e)},e.prototype.defaultTarget=function t(e){var n=s("target",e);return n?document.querySelector(n):void 0},e.prototype.defaultText=function t(e){return s("text",e)},e.prototype.destroy=function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)},e}(u.default);t.exports=d})},{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)});
\ No newline at end of file
diff --git a/packages/flamenco/flamenco/static/assets/js/vendor/jquery-resizable.min.js b/packages/flamenco/flamenco/static/assets/js/vendor/jquery-resizable.min.js
deleted file mode 100644
index 36b5124f35abf547ded2a453ebbc6f510a33de6a..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/static/assets/js/vendor/jquery-resizable.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(n,t){function e(t,e){return">"===t.trim()[0]?(t=t.trim().replace(/^>\s*/,""),e.find(t)):t?n(t):e}n.fn.resizable||(n.fn.resizable=function(t){var o={handleSelector:null,resizeWidth:!0,resizeHeight:!0,resizeWidthFrom:"right",resizeHeightFrom:"bottom",onDragStart:null,onDragEnd:null,onDrag:null,touchActionNone:!0};return"object"==typeof t&&(o=n.extend(o,t)),this.each(function(){function t(n){n.stopPropagation(),n.preventDefault()}function i(e){c=s(e),c.width=parseInt(d.width(),10),c.height=parseInt(d.height(),10),a=d.css("transition"),d.css("transition","none"),o.onDragStart&&o.onDragStart(e,d,o)===!1||(o.dragFunc=r,n(document).bind("mousemove.rsz",o.dragFunc),n(document).bind("mouseup.rsz",u),(window.Touch||navigator.maxTouchPoints)&&(n(document).bind("touchmove.rsz",o.dragFunc),n(document).bind("touchend.rsz",u)),n(document).bind("selectstart.rsz",t))}function r(n){var t,e,i=s(n);t="left"===o.resizeWidthFrom?c.width-i.x+c.x:c.width+i.x-c.x,e="top"===o.resizeHeightFrom?c.height-i.y+c.y:c.height+i.y-c.y,o.onDrag&&o.onDrag(n,d,t,e,o)===!1||(o.resizeHeight&&d.height(e),o.resizeWidth&&d.width(t))}function u(e){return e.stopPropagation(),e.preventDefault(),n(document).unbind("mousemove.rsz",o.dragFunc),n(document).unbind("mouseup.rsz",u),(window.Touch||navigator.maxTouchPoints)&&(n(document).unbind("touchmove.rsz",o.dragFunc),n(document).unbind("touchend.rsz",u)),n(document).unbind("selectstart.rsz",t),d.css("transition",a),o.onDragEnd&&o.onDragEnd(e,d,o),!1}function s(n){var t={x:0,y:0,width:0,height:0};if("number"==typeof n.clientX)t.x=n.clientX,t.y=n.clientY;else{if(!n.originalEvent.touches)return null;t.x=n.originalEvent.touches[0].clientX,t.y=n.originalEvent.touches[0].clientY}return t}var c,a,d=n(this),h=e(o.handleSelector,d);o.touchActionNone&&h.css("touch-action","none"),d.addClass("resizable"),h.bind("mousedown.rsz touchstart.rsz",i)})})}(jQuery,void 0);
-//# sourceMappingURL=jquery-resizable.min.js.map
diff --git a/packages/flamenco/flamenco/static/assets/js/vendor/vis.min.js b/packages/flamenco/flamenco/static/assets/js/vendor/vis.min.js
deleted file mode 100644
index 010c88a557e0e77f09b6156711bdf0f67a9d24c1..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/static/assets/js/vendor/vis.min.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * vis.js
- * https://github.com/almende/vis
- *
- * A dynamic, browser-based visualization library.
- *
- * @version 4.18.0
- * @date    2017-01-15
- *
- * @license
- * Copyright (C) 2011-2016 Almende B.V, http://almende.com
- *
- * Vis.js is dual licensed under both
- *
- * * The Apache 2.0 License
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * and
- *
- * * The MIT License
- *   http://opensource.org/licenses/MIT
- *
- * Vis.js may be distributed under either license.
- */
-"use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.vis=e():t.vis=e()}(this,function(){return function(t){function e(o){if(i[o])return i[o].exports;var n=i[o]={exports:{},id:o,loaded:!1};return t[o].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){var o=i(1);o.extend(e,i(89)),o.extend(e,i(112)),o.extend(e,i(154))},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}var n=i(2),s=o(n),r=i(55),a=o(r),h=i(58),d=o(h),l=i(62),u=o(l),c=i(82),p=o(c),f=i(84),m=i(88);e.isNumber=function(t){return t instanceof Number||"number"==typeof t},e.elementsCensor=function(t){if(t){var e=function(t,e){return e instanceof Element?"DOM Element":e};return JSON.parse((0,p.default)(t,e))}},e.recursiveDOMDelete=function(t){if(t)for(;t.hasChildNodes()===!0;)e.recursiveDOMDelete(t.firstChild),t.removeChild(t.firstChild)},e.giveRange=function(t,e,i,o){if(e==t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)},e.isString=function(t){return t instanceof String||"string"==typeof t},e.isDate=function(t){if(t instanceof Date)return!0;if(e.isString(t)){var i=v.exec(t);if(i)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},e.randomUUID=function(){return m.v4()},e.assignAllKeys=function(t,e){for(var i in t)t.hasOwnProperty(i)&&"object"!==(0,u.default)(t[i])&&(t[i]=e)},e.fillIfDefined=function(t,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2];for(var n in t)void 0!==i[n]&&("object"!==(0,u.default)(i[n])?void 0!==i[n]&&null!==i[n]||void 0===t[n]||o!==!0?t[n]=i[n]:delete t[n]:"object"===(0,u.default)(t[n])&&e.fillIfDefined(t[n],i[n],o))},e.protoExtend=function(t,e){for(var i=1;i<arguments.length;i++){var o=arguments[i];for(var n in o)t[n]=o[n]}return t},e.extend=function(t,e){for(var i=1;i<arguments.length;i++){var o=arguments[i];for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])}return t},e.selectiveExtend=function(t,e,i){if(!Array.isArray(t))throw new Error("Array with property names expected as first argument");for(var o=2;o<arguments.length;o++)for(var n=arguments[o],s=0;s<t.length;s++){var r=t[s];n.hasOwnProperty(r)&&(e[r]=n[r])}return e},e.selectiveDeepExtend=function(t,i,o){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(Array.isArray(o))throw new TypeError("Arrays are not supported by deepExtend");for(var s=2;s<arguments.length;s++)for(var r=arguments[s],a=0;a<t.length;a++){var h=t[a];if(r.hasOwnProperty(h))if(o[h]&&o[h].constructor===Object)void 0===i[h]&&(i[h]={}),i[h].constructor===Object?e.deepExtend(i[h],o[h],!1,n):null===o[h]&&void 0!==i[h]&&n===!0?delete i[h]:i[h]=o[h];else{if(Array.isArray(o[h]))throw new TypeError("Arrays are not supported by deepExtend");null===o[h]&&void 0!==i[h]&&n===!0?delete i[h]:i[h]=o[h]}}return i},e.selectiveNotDeepExtend=function(t,i,o){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(Array.isArray(o))throw new TypeError("Arrays are not supported by deepExtend");for(var s in o)if(o.hasOwnProperty(s)&&t.indexOf(s)==-1)if(o[s]&&o[s].constructor===Object)void 0===i[s]&&(i[s]={}),i[s].constructor===Object?e.deepExtend(i[s],o[s]):null===o[s]&&void 0!==i[s]&&n===!0?delete i[s]:i[s]=o[s];else if(Array.isArray(o[s])){i[s]=[];for(var r=0;r<o[s].length;r++)i[s].push(o[s][r])}else null===o[s]&&void 0!==i[s]&&n===!0?delete i[s]:i[s]=o[s];return i},e.deepExtend=function(t,i,o,n){for(var s in i)if(i.hasOwnProperty(s)||o===!0)if(i[s]&&i[s].constructor===Object)void 0===t[s]&&(t[s]={}),t[s].constructor===Object?e.deepExtend(t[s],i[s],o):null===i[s]&&void 0!==t[s]&&n===!0?delete t[s]:t[s]=i[s];else if(Array.isArray(i[s])){t[s]=[];for(var r=0;r<i[s].length;r++)t[s].push(i[s][r])}else null===i[s]&&void 0!==t[s]&&n===!0?delete t[s]:t[s]=i[s];return t},e.equalArray=function(t,e){if(t.length!=e.length)return!1;for(var i=0,o=t.length;i<o;i++)if(t[i]!=e[i])return!1;return!0},e.convert=function(t,i){var o;if(void 0!==t){if(null===t)return null;if(!i)return t;if("string"!=typeof i&&!(i instanceof String))throw new Error("Type must be a string");switch(i){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return e.isString(t)&&!isNaN(Date.parse(t))?f(t).valueOf():Number(t.valueOf());case"string":case"String":return String(t);case"Date":if(e.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(f.isMoment(t))return new Date(t.valueOf());if(e.isString(t))return o=v.exec(t),o?new Date(Number(o[1])):f(new Date(t)).toDate();throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"Moment":if(e.isNumber(t))return f(t);if(t instanceof Date)return f(t.valueOf());if(f.isMoment(t))return f(t);if(e.isString(t))return o=v.exec(t),f(o?Number(o[1]):t);throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"ISODate":if(e.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(f.isMoment(t))return t.toDate().toISOString();if(e.isString(t))return o=v.exec(t),o?new Date(Number(o[1])).toISOString():f(t).format();throw new Error("Cannot convert object of type "+e.getType(t)+" to type ISODate");case"ASPDate":if(e.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(e.isString(t)){o=v.exec(t);var n;return n=o?new Date(Number(o[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw new Error("Cannot convert object of type "+e.getType(t)+" to type ASPDate");default:throw new Error('Unknown type "'+i+'"')}}};var v=/^\/?Date\((\-?\d+)/i;e.getType=function(t){var e="undefined"==typeof t?"undefined":(0,u.default)(t);return"object"==e?null===t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":Array.isArray(t)?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":void 0===e?"undefined":e},e.copyAndExtendArray=function(t,e){for(var i=[],o=0;o<t.length;o++)i.push(t[o]);return i.push(e),i},e.copyArray=function(t){for(var e=[],i=0;i<t.length;i++)e.push(t[i]);return e},e.getAbsoluteLeft=function(t){return t.getBoundingClientRect().left},e.getAbsoluteRight=function(t){return t.getBoundingClientRect().right},e.getAbsoluteTop=function(t){return t.getBoundingClientRect().top},e.addClassName=function(t,e){var i=t.className.split(" ");i.indexOf(e)==-1&&(i.push(e),t.className=i.join(" "))},e.removeClassName=function(t,e){var i=t.className.split(" "),o=i.indexOf(e);o!=-1&&(i.splice(o,1),t.className=i.join(" "))},e.forEach=function(t,e){var i,o;if(Array.isArray(t))for(i=0,o=t.length;i<o;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},e.toArray=function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(t[i]);return e},e.updateProperty=function(t,e,i){return t[e]!==i&&(t[e]=i,!0)},e.throttle=function(t){var e=!1;return function(){e||(e=!0,requestAnimationFrame(function(){e=!1,t()}))}},e.addEventListener=function(t,e,i,o){t.addEventListener?(void 0===o&&(o=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,o)):t.attachEvent("on"+e,i)},e.removeEventListener=function(t,e,i,o){t.removeEventListener?(void 0===o&&(o=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,o)):t.detachEvent("on"+e,i)},e.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},e.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},e.hasParent=function(t,e){for(var i=t;i;){if(i===e)return!0;i=i.parentNode}return!1},e.option={},e.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},e.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},e.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},e.option.asSize=function(t,i){return"function"==typeof t&&(t=t()),e.isString(t)?t:e.isNumber(t)?t+"px":i||null},e.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},e.hexToRGB=function(t){var e=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(e,function(t,e,i,o){return e+e+i+i+o+o});var i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:null},e.overrideOpacity=function(t,i){if(t.indexOf("rgba")!=-1)return t;if(t.indexOf("rgb")!=-1){var o=t.substr(t.indexOf("(")+1).replace(")","").split(",");return"rgba("+o[0]+","+o[1]+","+o[2]+","+i+")"}var o=e.hexToRGB(t);return null==o?t:"rgba("+o.r+","+o.g+","+o.b+","+i+")"},e.RGBToHex=function(t,e,i){return"#"+((1<<24)+(t<<16)+(e<<8)+i).toString(16).slice(1)},e.parseColor=function(t){var i;if(e.isString(t)===!0){if(e.isValidRGB(t)===!0){var o=t.substr(4).substr(0,t.length-5).split(",").map(function(t){return parseInt(t)});t=e.RGBToHex(o[0],o[1],o[2])}if(e.isValidHex(t)===!0){var n=e.hexToHSV(t),s={h:n.h,s:.8*n.s,v:Math.min(1,1.02*n.v)},r={h:n.h,s:Math.min(1,1.25*n.s),v:.8*n.v},a=e.HSVToHex(r.h,r.s,r.v),h=e.HSVToHex(s.h,s.s,s.v);i={background:t,border:a,highlight:{background:h,border:a},hover:{background:h,border:a}}}else i={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else i={},i.background=t.background||void 0,i.border=t.border||void 0,e.isString(t.highlight)?i.highlight={border:t.highlight,background:t.highlight}:(i.highlight={},i.highlight.background=t.highlight&&t.highlight.background||void 0,i.highlight.border=t.highlight&&t.highlight.border||void 0),e.isString(t.hover)?i.hover={border:t.hover,background:t.hover}:(i.hover={},i.hover.background=t.hover&&t.hover.background||void 0,i.hover.border=t.hover&&t.hover.border||void 0);return i},e.RGBToHSV=function(t,e,i){t/=255,e/=255,i/=255;var o=Math.min(t,Math.min(e,i)),n=Math.max(t,Math.max(e,i));if(o==n)return{h:0,s:0,v:o};var s=t==o?e-i:i==o?t-e:i-t,r=t==o?3:i==o?1:5,a=60*(r-s/(n-o))/360,h=(n-o)/n,d=n;return{h:a,s:h,v:d}};var g={split:function(t){var e={};return t.split(";").forEach(function(t){if(""!=t.trim()){var i=t.split(":"),o=i[0].trim(),n=i[1].trim();e[o]=n}}),e},join:function(t){return(0,d.default)(t).map(function(e){return e+": "+t[e]}).join("; ")}};e.addCssText=function(t,i){var o=g.split(t.style.cssText),n=g.split(i),s=e.extend(o,n);t.style.cssText=g.join(s)},e.removeCssText=function(t,e){var i=g.split(t.style.cssText),o=g.split(e);for(var n in o)o.hasOwnProperty(n)&&delete i[n];t.style.cssText=g.join(i)},e.HSVToRGB=function(t,e,i){var o,n,s,r=Math.floor(6*t),a=6*t-r,h=i*(1-e),d=i*(1-a*e),l=i*(1-(1-a)*e);switch(r%6){case 0:o=i,n=l,s=h;break;case 1:o=d,n=i,s=h;break;case 2:o=h,n=i,s=l;break;case 3:o=h,n=d,s=i;break;case 4:o=l,n=h,s=i;break;case 5:o=i,n=h,s=d}return{r:Math.floor(255*o),g:Math.floor(255*n),b:Math.floor(255*s)}},e.HSVToHex=function(t,i,o){var n=e.HSVToRGB(t,i,o);return e.RGBToHex(n.r,n.g,n.b)},e.hexToHSV=function(t){var i=e.hexToRGB(t);return e.RGBToHSV(i.r,i.g,i.b)},e.isValidHex=function(t){var e=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t);return e},e.isValidRGB=function(t){t=t.replace(" ","");var e=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t);return e},e.isValidRGBA=function(t){t=t.replace(" ","");var e=/rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(.{1,3})\)/i.test(t);return e},e.selectiveBridgeObject=function(t,i){if("object"==("undefined"==typeof i?"undefined":(0,u.default)(i))){for(var o=(0,a.default)(i),n=0;n<t.length;n++)i.hasOwnProperty(t[n])&&"object"==(0,u.default)(i[t[n]])&&(o[t[n]]=e.bridgeObject(i[t[n]]));return o}return null},e.bridgeObject=function(t){if("object"==("undefined"==typeof t?"undefined":(0,u.default)(t))){var i=(0,a.default)(t);for(var o in t)t.hasOwnProperty(o)&&"object"==(0,u.default)(t[o])&&(i[o]=e.bridgeObject(t[o]));return i}return null},e.insertSort=function(t,e){for(var i=0;i<t.length;i++){for(var o=t[i],n=i;n>0&&e(o,t[n-1])<0;n--)t[n]=t[n-1];t[n]=o}return t},e.mergeOptions=function(t,e,i){var o=(arguments.length>3&&void 0!==arguments[3]&&arguments[3],arguments.length>4&&void 0!==arguments[4]?arguments[4]:{});if(null===e[i])t[i]=(0,a.default)(o[i]);else if(void 0!==e[i])if("boolean"==typeof e[i])t[i].enabled=e[i];else{void 0===e[i].enabled&&(t[i].enabled=!0);for(var n in e[i])e[i].hasOwnProperty(n)&&(t[i][n]=e[i][n])}},e.binarySearchCustom=function(t,e,i,o){for(var n=1e4,s=0,r=0,a=t.length-1;r<=a&&s<n;){var h=Math.floor((r+a)/2),d=t[h],l=void 0===o?d[i]:d[i][o],u=e(l);if(0==u)return h;u==-1?r=h+1:a=h-1,s++}return-1},e.binarySearchValue=function(t,e,i,o,n){for(var s,r,a,h,d=1e4,l=0,u=0,c=t.length-1,n=void 0!=n?n:function(t,e){return t==e?0:t<e?-1:1};u<=c&&l<d;){if(h=Math.floor(.5*(c+u)),s=t[Math.max(0,h-1)][i],r=t[h][i],a=t[Math.min(t.length-1,h+1)][i],0==n(r,e))return h;if(n(s,e)<0&&n(r,e)>0)return"before"==o?Math.max(0,h-1):h;if(n(r,e)<0&&n(a,e)>0)return"before"==o?h:Math.min(t.length-1,h+1);n(r,e)<0?u=h+1:c=h-1,l++}return-1},e.easingFunctions={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:-1+(4-2*t)*t},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}},e.getScrollBarWidth=function(){var t=document.createElement("p");t.style.width="100%",t.style.height="200px";var e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.style.visibility="hidden",e.style.width="200px",e.style.height="150px",e.style.overflow="hidden",e.appendChild(t),document.body.appendChild(e);var i=t.offsetWidth;e.style.overflow="scroll";var o=t.offsetWidth;return i==o&&(o=e.clientWidth),document.body.removeChild(e),i-o},e.topMost=function(t,e){var i=void 0;Array.isArray(e)||(e=[e]);var o=!0,n=!1,r=void 0;try{for(var a,h=(0,s.default)(t);!(o=(a=h.next()).done);o=!0){var d=a.value;if(d){i=d[e[0]];for(var l=1;l<e.length;l++)i&&(i=i[e[l]]);if("undefined"!=typeof i)break}}}catch(t){n=!0,r=t}finally{try{!o&&h.return&&h.return()}finally{if(n)throw r}}return i}},function(t,e,i){t.exports={default:i(3),__esModule:!0}},function(t,e,i){i(4),i(50),t.exports=i(52)},function(t,e,i){i(5);for(var o=i(16),n=i(20),s=i(8),r=i(47)("toStringTag"),a=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],h=0;h<5;h++){var d=a[h],l=o[d],u=l&&l.prototype;u&&!u[r]&&n(u,r,d),s[d]=s.Array}},function(t,e,i){var o=i(6),n=i(7),s=i(8),r=i(9);t.exports=i(13)(Array,"Array",function(t,e){this._t=r(t),this._i=0,this._k=e},function(){var t=this._t,e=this._k,i=this._i++;return!t||i>=t.length?(this._t=void 0,n(1)):"keys"==e?n(0,i):"values"==e?n(0,t[i]):n(0,[i,t[i]])},"values"),s.Arguments=s.Array,o("keys"),o("values"),o("entries")},function(t,e){t.exports=function(){}},function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},function(t,e){t.exports={}},function(t,e,i){var o=i(10),n=i(12);t.exports=function(t){return o(n(t))}},function(t,e,i){var o=i(11);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==o(t)?t.split(""):Object(t)}},function(t,e){var i={}.toString;t.exports=function(t){return i.call(t).slice(8,-1)}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on  "+t);return t}},function(t,e,i){var o=i(14),n=i(15),s=i(30),r=i(20),a=i(31),h=i(8),d=i(32),l=i(46),u=i(48),c=i(47)("iterator"),p=!([].keys&&"next"in[].keys()),f="@@iterator",m="keys",v="values",g=function(){return this};t.exports=function(t,e,i,y,b,_,w){d(i,e,y);var x,k,O,D=function(t){if(!p&&t in T)return T[t];switch(t){case m:return function(){return new i(this,t)};case v:return function(){return new i(this,t)}}return function(){return new i(this,t)}},S=e+" Iterator",M=b==v,C=!1,T=t.prototype,E=T[c]||T[f]||b&&T[b],P=E||D(b),I=b?M?D("entries"):P:void 0,N="Array"==e?T.entries||E:E;if(N&&(O=u(N.call(new t)),O!==Object.prototype&&(l(O,S,!0),o||a(O,c)||r(O,c,g))),M&&E&&E.name!==v&&(C=!0,P=function(){return E.call(this)}),o&&!w||!p&&!C&&T[c]||r(T,c,P),h[e]=P,h[S]=g,b)if(x={values:M?P:D(v),keys:_?P:D(m),entries:I},w)for(k in x)k in T||s(T,k,x[k]);else n(n.P+n.F*(p||C),e,x);return x}},function(t,e){t.exports=!0},function(t,e,i){var o=i(16),n=i(17),s=i(18),r=i(20),a="prototype",h=function(t,e,i){var d,l,u,c=t&h.F,p=t&h.G,f=t&h.S,m=t&h.P,v=t&h.B,g=t&h.W,y=p?n:n[e]||(n[e]={}),b=y[a],_=p?o:f?o[e]:(o[e]||{})[a];p&&(i=e);for(d in i)l=!c&&_&&void 0!==_[d],l&&d in y||(u=l?_[d]:i[d],y[d]=p&&"function"!=typeof _[d]?i[d]:v&&l?s(u,o):g&&_[d]==u?function(t){var e=function(e,i,o){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(e);case 2:return new t(e,i)}return new t(e,i,o)}return t.apply(this,arguments)};return e[a]=t[a],e}(u):m&&"function"==typeof u?s(Function.call,u):u,m&&((y.virtual||(y.virtual={}))[d]=u,t&h.R&&b&&!b[d]&&r(b,d,u)))};h.F=1,h.G=2,h.S=4,h.P=8,h.B=16,h.W=32,h.U=64,h.R=128,t.exports=h},function(t,e){var i=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=i)},function(t,e){var i=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=i)},function(t,e,i){var o=i(19);t.exports=function(t,e,i){if(o(t),void 0===e)return t;switch(i){case 1:return function(i){return t.call(e,i)};case 2:return function(i,o){return t.call(e,i,o)};case 3:return function(i,o,n){return t.call(e,i,o,n)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,i){var o=i(21),n=i(29);t.exports=i(25)?function(t,e,i){return o.f(t,e,n(1,i))}:function(t,e,i){return t[e]=i,t}},function(t,e,i){var o=i(22),n=i(24),s=i(28),r=Object.defineProperty;e.f=i(25)?Object.defineProperty:function(t,e,i){if(o(t),e=s(e,!0),o(i),n)try{return r(t,e,i)}catch(t){}if("get"in i||"set"in i)throw TypeError("Accessors not supported!");return"value"in i&&(t[e]=i.value),t}},function(t,e,i){var o=i(23);t.exports=function(t){if(!o(t))throw TypeError(t+" is not an object!");return t}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,i){t.exports=!i(25)&&!i(26)(function(){return 7!=Object.defineProperty(i(27)("div"),"a",{get:function(){return 7}}).a})},function(t,e,i){t.exports=!i(26)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e,i){var o=i(23),n=i(16).document,s=o(n)&&o(n.createElement);t.exports=function(t){return s?n.createElement(t):{}}},function(t,e,i){var o=i(23);t.exports=function(t,e){if(!o(t))return t;var i,n;if(e&&"function"==typeof(i=t.toString)&&!o(n=i.call(t)))return n;if("function"==typeof(i=t.valueOf)&&!o(n=i.call(t)))return n;if(!e&&"function"==typeof(i=t.toString)&&!o(n=i.call(t)))return n;throw TypeError("Can't convert object to primitive value")}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,i){t.exports=i(20)},function(t,e){var i={}.hasOwnProperty;t.exports=function(t,e){return i.call(t,e)}},function(t,e,i){var o=i(33),n=i(29),s=i(46),r={};i(20)(r,i(47)("iterator"),function(){return this}),t.exports=function(t,e,i){t.prototype=o(r,{next:n(1,i)}),s(t,e+" Iterator")}},function(t,e,i){var o=i(22),n=i(34),s=i(44),r=i(41)("IE_PROTO"),a=function(){},h="prototype",d=function(){var t,e=i(27)("iframe"),o=s.length,n="<",r=">";for(e.style.display="none",i(45).appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write(n+"script"+r+"document.F=Object"+n+"/script"+r),t.close(),d=t.F;o--;)delete d[h][s[o]];return d()};t.exports=Object.create||function(t,e){var i;return null!==t?(a[h]=o(t),i=new a,a[h]=null,i[r]=t):i=d(),void 0===e?i:n(i,e)}},function(t,e,i){var o=i(21),n=i(22),s=i(35);t.exports=i(25)?Object.defineProperties:function(t,e){n(t);for(var i,r=s(e),a=r.length,h=0;a>h;)o.f(t,i=r[h++],e[i]);return t}},function(t,e,i){var o=i(36),n=i(44);t.exports=Object.keys||function(t){return o(t,n)}},function(t,e,i){var o=i(31),n=i(9),s=i(37)(!1),r=i(41)("IE_PROTO");t.exports=function(t,e){var i,a=n(t),h=0,d=[];for(i in a)i!=r&&o(a,i)&&d.push(i);for(;e.length>h;)o(a,i=e[h++])&&(~s(d,i)||d.push(i));return d}},function(t,e,i){var o=i(9),n=i(38),s=i(40);t.exports=function(t){return function(e,i,r){var a,h=o(e),d=n(h.length),l=s(r,d);if(t&&i!=i){for(;d>l;)if(a=h[l++],a!=a)return!0}else for(;d>l;l++)if((t||l in h)&&h[l]===i)return t||l||0;return!t&&-1}}},function(t,e,i){var o=i(39),n=Math.min;t.exports=function(t){return t>0?n(o(t),9007199254740991):0}},function(t,e){var i=Math.ceil,o=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?o:i)(t)}},function(t,e,i){var o=i(39),n=Math.max,s=Math.min;t.exports=function(t,e){return t=o(t),t<0?n(t+e,0):s(t,e)}},function(t,e,i){var o=i(42)("keys"),n=i(43);t.exports=function(t){return o[t]||(o[t]=n(t))}},function(t,e,i){var o=i(16),n="__core-js_shared__",s=o[n]||(o[n]={});t.exports=function(t){return s[t]||(s[t]={})}},function(t,e){var i=0,o=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++i+o).toString(36))}},function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e,i){t.exports=i(16).document&&document.documentElement},function(t,e,i){var o=i(21).f,n=i(31),s=i(47)("toStringTag");t.exports=function(t,e,i){t&&!n(t=i?t:t.prototype,s)&&o(t,s,{configurable:!0,value:e})}},function(t,e,i){var o=i(42)("wks"),n=i(43),s=i(16).Symbol,r="function"==typeof s,a=t.exports=function(t){return o[t]||(o[t]=r&&s[t]||(r?s:n)("Symbol."+t))};a.store=o},function(t,e,i){var o=i(31),n=i(49),s=i(41)("IE_PROTO"),r=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=n(t),o(t,s)?t[s]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?r:null}},function(t,e,i){var o=i(12);t.exports=function(t){return Object(o(t))}},function(t,e,i){var o=i(51)(!0);i(13)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,i=this._i;return i>=e.length?{value:void 0,done:!0}:(t=o(e,i),this._i+=t.length,{value:t,done:!1})})},function(t,e,i){var o=i(39),n=i(12);t.exports=function(t){return function(e,i){var s,r,a=String(n(e)),h=o(i),d=a.length;return h<0||h>=d?t?"":void 0:(s=a.charCodeAt(h),s<55296||s>56319||h+1===d||(r=a.charCodeAt(h+1))<56320||r>57343?t?a.charAt(h):s:t?a.slice(h,h+2):(s-55296<<10)+(r-56320)+65536)}}},function(t,e,i){var o=i(22),n=i(53);t.exports=i(17).getIterator=function(t){var e=n(t);if("function"!=typeof e)throw TypeError(t+" is not iterable!");return o(e.call(t))}},function(t,e,i){var o=i(54),n=i(47)("iterator"),s=i(8);t.exports=i(17).getIteratorMethod=function(t){if(void 0!=t)return t[n]||t["@@iterator"]||s[o(t)]}},function(t,e,i){var o=i(11),n=i(47)("toStringTag"),s="Arguments"==o(function(){return arguments}()),r=function(t,e){try{return t[e]}catch(t){}};t.exports=function(t){var e,i,a;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=r(e=Object(t),n))?i:s?o(e):"Object"==(a=o(e))&&"function"==typeof e.callee?"Arguments":a}},function(t,e,i){t.exports={default:i(56),__esModule:!0}},function(t,e,i){i(57);var o=i(17).Object;t.exports=function(t,e){return o.create(t,e)}},function(t,e,i){var o=i(15);o(o.S,"Object",{create:i(33)})},function(t,e,i){t.exports={default:i(59),__esModule:!0}},function(t,e,i){i(60),t.exports=i(17).Object.keys},function(t,e,i){var o=i(49),n=i(35);i(61)("keys",function(){return function(t){return n(o(t))}})},function(t,e,i){var o=i(15),n=i(17),s=i(26);t.exports=function(t,e){var i=(n.Object||{})[t]||Object[t],r={};r[t]=e(i),o(o.S+o.F*s(function(){i(1)}),"Object",r)}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(63),s=o(n),r=i(66),a=o(r),h="function"==typeof a.default&&"symbol"==typeof s.default?function(t){return typeof t}:function(t){return t&&"function"==typeof a.default&&t.constructor===a.default&&t!==a.default.prototype?"symbol":typeof t};e.default="function"==typeof a.default&&"symbol"===h(s.default)?function(t){return"undefined"==typeof t?"undefined":h(t)}:function(t){return t&&"function"==typeof a.default&&t.constructor===a.default&&t!==a.default.prototype?"symbol":"undefined"==typeof t?"undefined":h(t)}},function(t,e,i){t.exports={default:i(64),__esModule:!0}},function(t,e,i){i(50),i(4),t.exports=i(65).f("iterator")},function(t,e,i){e.f=i(47)},function(t,e,i){t.exports={default:i(67),__esModule:!0}},function(t,e,i){i(68),i(79),i(80),i(81),t.exports=i(17).Symbol},function(t,e,i){var o=i(16),n=i(31),s=i(25),r=i(15),a=i(30),h=i(69).KEY,d=i(26),l=i(42),u=i(46),c=i(43),p=i(47),f=i(65),m=i(70),v=i(71),g=i(72),y=i(75),b=i(22),_=i(9),w=i(28),x=i(29),k=i(33),O=i(76),D=i(78),S=i(21),M=i(35),C=D.f,T=S.f,E=O.f,P=o.Symbol,I=o.JSON,N=I&&I.stringify,z="prototype",R=p("_hidden"),L=p("toPrimitive"),A={}.propertyIsEnumerable,B=l("symbol-registry"),F=l("symbols"),H=l("op-symbols"),j=Object[z],W="function"==typeof P,Y=o.QObject,G=!Y||!Y[z]||!Y[z].findChild,V=s&&d(function(){return 7!=k(T({},"a",{get:function(){return T(this,"a",{value:7}).a}})).a})?function(t,e,i){var o=C(j,e);o&&delete j[e],T(t,e,i),o&&t!==j&&T(j,e,o)}:T,U=function(t){var e=F[t]=k(P[z]);return e._k=t,e},q=W&&"symbol"==typeof P.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof P},X=function(t,e,i){return t===j&&X(H,e,i),b(t),e=w(e,!0),b(i),n(F,e)?(i.enumerable?(n(t,R)&&t[R][e]&&(t[R][e]=!1),i=k(i,{enumerable:x(0,!1)})):(n(t,R)||T(t,R,x(1,{})),t[R][e]=!0),V(t,e,i)):T(t,e,i)},Z=function(t,e){b(t);for(var i,o=g(e=_(e)),n=0,s=o.length;s>n;)X(t,i=o[n++],e[i]);return t},K=function(t,e){return void 0===e?k(t):Z(k(t),e)},Q=function(t){var e=A.call(this,t=w(t,!0));return!(this===j&&n(F,t)&&!n(H,t))&&(!(e||!n(this,t)||!n(F,t)||n(this,R)&&this[R][t])||e)},J=function(t,e){if(t=_(t),e=w(e,!0),t!==j||!n(F,e)||n(H,e)){var i=C(t,e);return!i||!n(F,e)||n(t,R)&&t[R][e]||(i.enumerable=!0),i}},$=function(t){for(var e,i=E(_(t)),o=[],s=0;i.length>s;)n(F,e=i[s++])||e==R||e==h||o.push(e);return o},tt=function(t){for(var e,i=t===j,o=E(i?H:_(t)),s=[],r=0;o.length>r;)!n(F,e=o[r++])||i&&!n(j,e)||s.push(F[e]);return s};W||(P=function(){if(this instanceof P)throw TypeError("Symbol is not a constructor!");var t=c(arguments.length>0?arguments[0]:void 0),e=function(i){this===j&&e.call(H,i),n(this,R)&&n(this[R],t)&&(this[R][t]=!1),V(this,t,x(1,i))};return s&&G&&V(j,t,{configurable:!0,set:e}),U(t)},a(P[z],"toString",function(){return this._k}),D.f=J,S.f=X,i(77).f=O.f=$,i(74).f=Q,i(73).f=tt,s&&!i(14)&&a(j,"propertyIsEnumerable",Q,!0),f.f=function(t){return U(p(t))}),r(r.G+r.W+r.F*!W,{Symbol:P});for(var et="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),it=0;et.length>it;)p(et[it++]);for(var et=M(p.store),it=0;et.length>it;)m(et[it++]);r(r.S+r.F*!W,"Symbol",{for:function(t){return n(B,t+="")?B[t]:B[t]=P(t)},keyFor:function(t){if(q(t))return v(B,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){G=!0},useSimple:function(){G=!1}}),r(r.S+r.F*!W,"Object",{create:K,defineProperty:X,defineProperties:Z,getOwnPropertyDescriptor:J,getOwnPropertyNames:$,getOwnPropertySymbols:tt}),I&&r(r.S+r.F*(!W||d(function(){var t=P();return"[null]"!=N([t])||"{}"!=N({a:t})||"{}"!=N(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!q(t)){for(var e,i,o=[t],n=1;arguments.length>n;)o.push(arguments[n++]);return e=o[1],"function"==typeof e&&(i=e),!i&&y(e)||(e=function(t,e){if(i&&(e=i.call(this,t,e)),!q(e))return e}),o[1]=e,N.apply(I,o)}}}),P[z][L]||i(20)(P[z],L,P[z].valueOf),u(P,"Symbol"),u(Math,"Math",!0),u(o.JSON,"JSON",!0)},function(t,e,i){var o=i(43)("meta"),n=i(23),s=i(31),r=i(21).f,a=0,h=Object.isExtensible||function(){return!0},d=!i(26)(function(){return h(Object.preventExtensions({}))}),l=function(t){r(t,o,{value:{i:"O"+ ++a,w:{}}})},u=function(t,e){if(!n(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!s(t,o)){if(!h(t))return"F";if(!e)return"E";l(t)}return t[o].i},c=function(t,e){if(!s(t,o)){if(!h(t))return!0;if(!e)return!1;l(t)}return t[o].w},p=function(t){return d&&f.NEED&&h(t)&&!s(t,o)&&l(t),t},f=t.exports={KEY:o,NEED:!1,fastKey:u,getWeak:c,onFreeze:p}},function(t,e,i){var o=i(16),n=i(17),s=i(14),r=i(65),a=i(21).f;t.exports=function(t){var e=n.Symbol||(n.Symbol=s?{}:o.Symbol||{});"_"==t.charAt(0)||t in e||a(e,t,{value:r.f(t)})}},function(t,e,i){var o=i(35),n=i(9);t.exports=function(t,e){for(var i,s=n(t),r=o(s),a=r.length,h=0;a>h;)if(s[i=r[h++]]===e)return i}},function(t,e,i){var o=i(35),n=i(73),s=i(74);t.exports=function(t){var e=o(t),i=n.f;if(i)for(var r,a=i(t),h=s.f,d=0;a.length>d;)h.call(t,r=a[d++])&&e.push(r);return e}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e){e.f={}.propertyIsEnumerable},function(t,e,i){var o=i(11);t.exports=Array.isArray||function(t){return"Array"==o(t)}},function(t,e,i){var o=i(9),n=i(77).f,s={}.toString,r="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],a=function(t){try{return n(t)}catch(t){return r.slice()}};t.exports.f=function(t){return r&&"[object Window]"==s.call(t)?a(t):n(o(t))}},function(t,e,i){var o=i(36),n=i(44).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return o(t,n)}},function(t,e,i){var o=i(74),n=i(29),s=i(9),r=i(28),a=i(31),h=i(24),d=Object.getOwnPropertyDescriptor;e.f=i(25)?d:function(t,e){if(t=s(t),e=r(e,!0),h)try{return d(t,e)}catch(t){}if(a(t,e))return n(!o.f.call(t,e),t[e])}},function(t,e){},function(t,e,i){i(70)("asyncIterator")},function(t,e,i){i(70)("observable")},function(t,e,i){t.exports={default:i(83),__esModule:!0}},function(t,e,i){var o=i(17),n=o.JSON||(o.JSON={stringify:JSON.stringify});t.exports=function(t){return n.stringify.apply(n,arguments)}},function(t,e,i){t.exports="undefined"!=typeof window&&window.moment||i(85)},function(t,e,i){(function(t){!function(e,i){t.exports=i()}(this,function(){function e(){return vo.apply(null,arguments)}function i(t){vo=t}function o(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function n(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function s(t){var e;for(e in t)return!1;return!0}function r(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function a(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function h(t,e){var i,o=[];for(i=0;i<t.length;++i)o.push(e(t[i],i));return o}function d(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function l(t,e){for(var i in e)d(e,i)&&(t[i]=e[i]);return d(e,"toString")&&(t.toString=e.toString),d(e,"valueOf")&&(t.valueOf=e.valueOf),t}function u(t,e,i,o){return ye(t,e,i,o,!0).utc()}function c(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function p(t){return null==t._pf&&(t._pf=c()),t._pf}function f(t){if(null==t._isValid){var e=p(t),i=yo.call(e.parsedDateParts,function(t){return null!=t}),o=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&i);if(t._strict&&(o=o&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return o;
-t._isValid=o}return t._isValid}function m(t){var e=u(NaN);return null!=t?l(p(e),t):p(e).userInvalidated=!0,e}function v(t){return void 0===t}function g(t,e){var i,o,n;if(v(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),v(e._i)||(t._i=e._i),v(e._f)||(t._f=e._f),v(e._l)||(t._l=e._l),v(e._strict)||(t._strict=e._strict),v(e._tzm)||(t._tzm=e._tzm),v(e._isUTC)||(t._isUTC=e._isUTC),v(e._offset)||(t._offset=e._offset),v(e._pf)||(t._pf=p(e)),v(e._locale)||(t._locale=e._locale),bo.length>0)for(i in bo)o=bo[i],n=e[o],v(n)||(t[o]=n);return t}function y(t){g(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),_o===!1&&(_o=!0,e.updateOffset(this),_o=!1)}function b(t){return t instanceof y||null!=t&&null!=t._isAMomentObject}function _(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function w(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=_(e)),i}function x(t,e,i){var o,n=Math.min(t.length,e.length),s=Math.abs(t.length-e.length),r=0;for(o=0;o<n;o++)(i&&t[o]!==e[o]||!i&&w(t[o])!==w(e[o]))&&r++;return r+s}function k(t){e.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function O(t,i){var o=!0;return l(function(){if(null!=e.deprecationHandler&&e.deprecationHandler(null,t),o){for(var n,s=[],r=0;r<arguments.length;r++){if(n="","object"==typeof arguments[r]){n+="\n["+r+"] ";for(var a in arguments[0])n+=a+": "+arguments[0][a]+", ";n=n.slice(0,-2)}else n=arguments[r];s.push(n)}k(t+"\nArguments: "+Array.prototype.slice.call(s).join("")+"\n"+(new Error).stack),o=!1}return i.apply(this,arguments)},i)}function D(t,i){null!=e.deprecationHandler&&e.deprecationHandler(t,i),wo[t]||(k(i),wo[t]=!0)}function S(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function M(t){var e,i;for(i in t)e=t[i],S(e)?this[i]=e:this["_"+i]=e;this._config=t,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function C(t,e){var i,o=l({},t);for(i in e)d(e,i)&&(n(t[i])&&n(e[i])?(o[i]={},l(o[i],t[i]),l(o[i],e[i])):null!=e[i]?o[i]=e[i]:delete o[i]);for(i in t)d(t,i)&&!d(e,i)&&n(t[i])&&(o[i]=l({},o[i]));return o}function T(t){null!=t&&this.set(t)}function E(t,e,i){var o=this._calendar[t]||this._calendar.sameElse;return S(o)?o.call(e,i):o}function P(t){var e=this._longDateFormat[t],i=this._longDateFormat[t.toUpperCase()];return e||!i?e:(this._longDateFormat[t]=i.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])}function I(){return this._invalidDate}function N(t){return this._ordinal.replace("%d",t)}function z(t,e,i,o){var n=this._relativeTime[i];return S(n)?n(t,e,i,o):n.replace(/%d/i,t)}function R(t,e){var i=this._relativeTime[t>0?"future":"past"];return S(i)?i(e):i.replace(/%s/i,e)}function L(t,e){var i=t.toLowerCase();Po[i]=Po[i+"s"]=Po[e]=t}function A(t){return"string"==typeof t?Po[t]||Po[t.toLowerCase()]:void 0}function B(t){var e,i,o={};for(i in t)d(t,i)&&(e=A(i),e&&(o[e]=t[i]));return o}function F(t,e){Io[t]=e}function H(t){var e=[];for(var i in t)e.push({unit:i,priority:Io[i]});return e.sort(function(t,e){return t.priority-e.priority}),e}function j(t,i){return function(o){return null!=o?(Y(this,t,o),e.updateOffset(this,i),this):W(this,t)}}function W(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function Y(t,e,i){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](i)}function G(t){return t=A(t),S(this[t])?this[t]():this}function V(t,e){if("object"==typeof t){t=B(t);for(var i=H(t),o=0;o<i.length;o++)this[i[o].unit](t[i[o].unit])}else if(t=A(t),S(this[t]))return this[t](e);return this}function U(t,e,i){var o=""+Math.abs(t),n=e-o.length,s=t>=0;return(s?i?"+":"":"-")+Math.pow(10,Math.max(0,n)).toString().substr(1)+o}function q(t,e,i,o){var n=o;"string"==typeof o&&(n=function(){return this[o]()}),t&&(Lo[t]=n),e&&(Lo[e[0]]=function(){return U(n.apply(this,arguments),e[1],e[2])}),i&&(Lo[i]=function(){return this.localeData().ordinal(n.apply(this,arguments),t)})}function X(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function Z(t){var e,i,o=t.match(No);for(e=0,i=o.length;e<i;e++)Lo[o[e]]?o[e]=Lo[o[e]]:o[e]=X(o[e]);return function(e){var n,s="";for(n=0;n<i;n++)s+=o[n]instanceof Function?o[n].call(e,t):o[n];return s}}function K(t,e){return t.isValid()?(e=Q(e,t.localeData()),Ro[e]=Ro[e]||Z(e),Ro[e](t)):t.localeData().invalidDate()}function Q(t,e){function i(t){return e.longDateFormat(t)||t}var o=5;for(zo.lastIndex=0;o>=0&&zo.test(t);)t=t.replace(zo,i),zo.lastIndex=0,o-=1;return t}function J(t,e,i){tn[t]=S(e)?e:function(t,o){return t&&i?i:e}}function $(t,e){return d(tn,t)?tn[t](e._strict,e._locale):new RegExp(tt(t))}function tt(t){return et(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,o,n){return e||i||o||n}))}function et(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function it(t,e){var i,o=e;for("string"==typeof t&&(t=[t]),r(e)&&(o=function(t,i){i[e]=w(t)}),i=0;i<t.length;i++)en[t[i]]=o}function ot(t,e){it(t,function(t,i,o,n){o._w=o._w||{},e(t,o._w,o,n)})}function nt(t,e,i){null!=e&&d(en,t)&&en[t](e,i._a,i,t)}function st(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function rt(t,e){return t?o(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||pn).test(e)?"format":"standalone"][t.month()]:this._months}function at(t,e){return t?o(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[pn.test(e)?"format":"standalone"][t.month()]:this._monthsShort}function ht(t,e,i){var o,n,s,r=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],o=0;o<12;++o)s=u([2e3,o]),this._shortMonthsParse[o]=this.monthsShort(s,"").toLocaleLowerCase(),this._longMonthsParse[o]=this.months(s,"").toLocaleLowerCase();return i?"MMM"===e?(n=cn.call(this._shortMonthsParse,r),n!==-1?n:null):(n=cn.call(this._longMonthsParse,r),n!==-1?n:null):"MMM"===e?(n=cn.call(this._shortMonthsParse,r),n!==-1?n:(n=cn.call(this._longMonthsParse,r),n!==-1?n:null)):(n=cn.call(this._longMonthsParse,r),n!==-1?n:(n=cn.call(this._shortMonthsParse,r),n!==-1?n:null))}function dt(t,e,i){var o,n,s;if(this._monthsParseExact)return ht.call(this,t,e,i);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),o=0;o<12;o++){if(n=u([2e3,o]),i&&!this._longMonthsParse[o]&&(this._longMonthsParse[o]=new RegExp("^"+this.months(n,"").replace(".","")+"$","i"),this._shortMonthsParse[o]=new RegExp("^"+this.monthsShort(n,"").replace(".","")+"$","i")),i||this._monthsParse[o]||(s="^"+this.months(n,"")+"|^"+this.monthsShort(n,""),this._monthsParse[o]=new RegExp(s.replace(".",""),"i")),i&&"MMMM"===e&&this._longMonthsParse[o].test(t))return o;if(i&&"MMM"===e&&this._shortMonthsParse[o].test(t))return o;if(!i&&this._monthsParse[o].test(t))return o}}function lt(t,e){var i;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=w(e);else if(e=t.localeData().monthsParse(e),!r(e))return t;return i=Math.min(t.date(),st(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,i),t}function ut(t){return null!=t?(lt(this,t),e.updateOffset(this,!0),this):W(this,"Month")}function ct(){return st(this.year(),this.month())}function pt(t){return this._monthsParseExact?(d(this,"_monthsRegex")||mt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=vn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)}function ft(t){return this._monthsParseExact?(d(this,"_monthsRegex")||mt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=gn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)}function mt(){function t(t,e){return e.length-t.length}var e,i,o=[],n=[],s=[];for(e=0;e<12;e++)i=u([2e3,e]),o.push(this.monthsShort(i,"")),n.push(this.months(i,"")),s.push(this.months(i,"")),s.push(this.monthsShort(i,""));for(o.sort(t),n.sort(t),s.sort(t),e=0;e<12;e++)o[e]=et(o[e]),n[e]=et(n[e]);for(e=0;e<24;e++)s[e]=et(s[e]);this._monthsRegex=new RegExp("^("+s.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+n.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+o.join("|")+")","i")}function vt(t){return gt(t)?366:365}function gt(t){return t%4===0&&t%100!==0||t%400===0}function yt(){return gt(this.year())}function bt(t,e,i,o,n,s,r){var a=new Date(t,e,i,o,n,s,r);return t<100&&t>=0&&isFinite(a.getFullYear())&&a.setFullYear(t),a}function _t(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function wt(t,e,i){var o=7+e-i,n=(7+_t(t,0,o).getUTCDay()-e)%7;return-n+o-1}function xt(t,e,i,o,n){var s,r,a=(7+i-o)%7,h=wt(t,o,n),d=1+7*(e-1)+a+h;return d<=0?(s=t-1,r=vt(s)+d):d>vt(t)?(s=t+1,r=d-vt(t)):(s=t,r=d),{year:s,dayOfYear:r}}function kt(t,e,i){var o,n,s=wt(t.year(),e,i),r=Math.floor((t.dayOfYear()-s-1)/7)+1;return r<1?(n=t.year()-1,o=r+Ot(n,e,i)):r>Ot(t.year(),e,i)?(o=r-Ot(t.year(),e,i),n=t.year()+1):(n=t.year(),o=r),{week:o,year:n}}function Ot(t,e,i){var o=wt(t,e,i),n=wt(t+1,e,i);return(vt(t)-o+n)/7}function Dt(t){return kt(t,this._week.dow,this._week.doy).week}function St(){return this._week.dow}function Mt(){return this._week.doy}function Ct(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function Tt(t){var e=kt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function Et(t,e){return"string"!=typeof t?t:isNaN(t)?(t=e.weekdaysParse(t),"number"==typeof t?t:null):parseInt(t,10)}function Pt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function It(t,e){return t?o(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:this._weekdays}function Nt(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort}function zt(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin}function Rt(t,e,i){var o,n,s,r=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],o=0;o<7;++o)s=u([2e3,1]).day(o),this._minWeekdaysParse[o]=this.weekdaysMin(s,"").toLocaleLowerCase(),this._shortWeekdaysParse[o]=this.weekdaysShort(s,"").toLocaleLowerCase(),this._weekdaysParse[o]=this.weekdays(s,"").toLocaleLowerCase();return i?"dddd"===e?(n=cn.call(this._weekdaysParse,r),n!==-1?n:null):"ddd"===e?(n=cn.call(this._shortWeekdaysParse,r),n!==-1?n:null):(n=cn.call(this._minWeekdaysParse,r),n!==-1?n:null):"dddd"===e?(n=cn.call(this._weekdaysParse,r),n!==-1?n:(n=cn.call(this._shortWeekdaysParse,r),n!==-1?n:(n=cn.call(this._minWeekdaysParse,r),n!==-1?n:null))):"ddd"===e?(n=cn.call(this._shortWeekdaysParse,r),n!==-1?n:(n=cn.call(this._weekdaysParse,r),n!==-1?n:(n=cn.call(this._minWeekdaysParse,r),n!==-1?n:null))):(n=cn.call(this._minWeekdaysParse,r),n!==-1?n:(n=cn.call(this._weekdaysParse,r),n!==-1?n:(n=cn.call(this._shortWeekdaysParse,r),n!==-1?n:null)))}function Lt(t,e,i){var o,n,s;if(this._weekdaysParseExact)return Rt.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),o=0;o<7;o++){if(n=u([2e3,1]).day(o),i&&!this._fullWeekdaysParse[o]&&(this._fullWeekdaysParse[o]=new RegExp("^"+this.weekdays(n,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[o]=new RegExp("^"+this.weekdaysShort(n,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[o]=new RegExp("^"+this.weekdaysMin(n,"").replace(".",".?")+"$","i")),this._weekdaysParse[o]||(s="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[o]=new RegExp(s.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[o].test(t))return o;if(i&&"ddd"===e&&this._shortWeekdaysParse[o].test(t))return o;if(i&&"dd"===e&&this._minWeekdaysParse[o].test(t))return o;if(!i&&this._weekdaysParse[o].test(t))return o}}function At(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=Et(t,this.localeData()),this.add(t-e,"d")):e}function Bt(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function Ft(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=Pt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7}function Ht(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=kn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)}function jt(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=On),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Wt(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Dn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Yt(){function t(t,e){return e.length-t.length}var e,i,o,n,s,r=[],a=[],h=[],d=[];for(e=0;e<7;e++)i=u([2e3,1]).day(e),o=this.weekdaysMin(i,""),n=this.weekdaysShort(i,""),s=this.weekdays(i,""),r.push(o),a.push(n),h.push(s),d.push(o),d.push(n),d.push(s);for(r.sort(t),a.sort(t),h.sort(t),d.sort(t),e=0;e<7;e++)a[e]=et(a[e]),h[e]=et(h[e]),d[e]=et(d[e]);this._weekdaysRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Gt(){return this.hours()%12||12}function Vt(){return this.hours()||24}function Ut(t,e){q(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function qt(t,e){return e._meridiemParse}function Xt(t){return"p"===(t+"").toLowerCase().charAt(0)}function Zt(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}function Kt(t){return t?t.toLowerCase().replace("_","-"):t}function Qt(t){for(var e,i,o,n,s=0;s<t.length;){for(n=Kt(t[s]).split("-"),e=n.length,i=Kt(t[s+1]),i=i?i.split("-"):null;e>0;){if(o=Jt(n.slice(0,e).join("-")))return o;if(i&&i.length>=e&&x(n,i,!0)>=e-1)break;e--}s++}return null}function Jt(e){var i=null;if(!En[e]&&"undefined"!=typeof t&&t&&t.exports)try{i=Sn._abbr,!function(){var t=new Error('Cannot find module "./locale"');throw t.code="MODULE_NOT_FOUND",t}(),$t(i)}catch(t){}return En[e]}function $t(t,e){var i;return t&&(i=v(e)?ie(t):te(t,e),i&&(Sn=i)),Sn._abbr}function te(t,e){if(null!==e){var i=Tn;if(e.abbr=t,null!=En[t])D("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=En[t]._config;else if(null!=e.parentLocale){if(null==En[e.parentLocale])return Pn[e.parentLocale]||(Pn[e.parentLocale]=[]),Pn[e.parentLocale].push({name:t,config:e}),null;i=En[e.parentLocale]._config}return En[t]=new T(C(i,e)),Pn[t]&&Pn[t].forEach(function(t){te(t.name,t.config)}),$t(t),En[t]}return delete En[t],null}function ee(t,e){if(null!=e){var i,o=Tn;null!=En[t]&&(o=En[t]._config),e=C(o,e),i=new T(e),i.parentLocale=En[t],En[t]=i,$t(t)}else null!=En[t]&&(null!=En[t].parentLocale?En[t]=En[t].parentLocale:null!=En[t]&&delete En[t]);return En[t]}function ie(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Sn;if(!o(t)){if(e=Jt(t))return e;t=[t]}return Qt(t)}function oe(){return Oo(En)}function ne(t){var e,i=t._a;return i&&p(t).overflow===-2&&(e=i[nn]<0||i[nn]>11?nn:i[sn]<1||i[sn]>st(i[on],i[nn])?sn:i[rn]<0||i[rn]>24||24===i[rn]&&(0!==i[an]||0!==i[hn]||0!==i[dn])?rn:i[an]<0||i[an]>59?an:i[hn]<0||i[hn]>59?hn:i[dn]<0||i[dn]>999?dn:-1,p(t)._overflowDayOfYear&&(e<on||e>sn)&&(e=sn),p(t)._overflowWeeks&&e===-1&&(e=ln),p(t)._overflowWeekday&&e===-1&&(e=un),p(t).overflow=e),t}function se(t){var e,i,o,n,s,r,a=t._i,h=In.exec(a)||Nn.exec(a);if(h){for(p(t).iso=!0,e=0,i=Rn.length;e<i;e++)if(Rn[e][1].exec(h[1])){n=Rn[e][0],o=Rn[e][2]!==!1;break}if(null==n)return void(t._isValid=!1);if(h[3]){for(e=0,i=Ln.length;e<i;e++)if(Ln[e][1].exec(h[3])){s=(h[2]||" ")+Ln[e][0];break}if(null==s)return void(t._isValid=!1)}if(!o&&null!=s)return void(t._isValid=!1);if(h[4]){if(!zn.exec(h[4]))return void(t._isValid=!1);r="Z"}t._f=n+(s||"")+(r||""),ue(t)}else t._isValid=!1}function re(t){var i=An.exec(t._i);return null!==i?void(t._d=new Date(+i[1])):(se(t),void(t._isValid===!1&&(delete t._isValid,e.createFromInputFallback(t))))}function ae(t,e,i){return null!=t?t:null!=e?e:i}function he(t){var i=new Date(e.now());return t._useUTC?[i.getUTCFullYear(),i.getUTCMonth(),i.getUTCDate()]:[i.getFullYear(),i.getMonth(),i.getDate()]}function de(t){var e,i,o,n,s=[];if(!t._d){for(o=he(t),t._w&&null==t._a[sn]&&null==t._a[nn]&&le(t),t._dayOfYear&&(n=ae(t._a[on],o[on]),t._dayOfYear>vt(n)&&(p(t)._overflowDayOfYear=!0),i=_t(n,0,t._dayOfYear),t._a[nn]=i.getUTCMonth(),t._a[sn]=i.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=o[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[rn]&&0===t._a[an]&&0===t._a[hn]&&0===t._a[dn]&&(t._nextDay=!0,t._a[rn]=0),t._d=(t._useUTC?_t:bt).apply(null,s),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[rn]=24)}}function le(t){var e,i,o,n,s,r,a,h;if(e=t._w,null!=e.GG||null!=e.W||null!=e.E)s=1,r=4,i=ae(e.GG,t._a[on],kt(be(),1,4).year),o=ae(e.W,1),n=ae(e.E,1),(n<1||n>7)&&(h=!0);else{s=t._locale._week.dow,r=t._locale._week.doy;var d=kt(be(),s,r);i=ae(e.gg,t._a[on],d.year),o=ae(e.w,d.week),null!=e.d?(n=e.d,(n<0||n>6)&&(h=!0)):null!=e.e?(n=e.e+s,(e.e<0||e.e>6)&&(h=!0)):n=s}o<1||o>Ot(i,s,r)?p(t)._overflowWeeks=!0:null!=h?p(t)._overflowWeekday=!0:(a=xt(i,o,n,s,r),t._a[on]=a.year,t._dayOfYear=a.dayOfYear)}function ue(t){if(t._f===e.ISO_8601)return void se(t);t._a=[],p(t).empty=!0;var i,o,n,s,r,a=""+t._i,h=a.length,d=0;for(n=Q(t._f,t._locale).match(No)||[],i=0;i<n.length;i++)s=n[i],o=(a.match($(s,t))||[])[0],o&&(r=a.substr(0,a.indexOf(o)),r.length>0&&p(t).unusedInput.push(r),a=a.slice(a.indexOf(o)+o.length),d+=o.length),Lo[s]?(o?p(t).empty=!1:p(t).unusedTokens.push(s),nt(s,o,t)):t._strict&&!o&&p(t).unusedTokens.push(s);p(t).charsLeftOver=h-d,a.length>0&&p(t).unusedInput.push(a),t._a[rn]<=12&&p(t).bigHour===!0&&t._a[rn]>0&&(p(t).bigHour=void 0),p(t).parsedDateParts=t._a.slice(0),p(t).meridiem=t._meridiem,t._a[rn]=ce(t._locale,t._a[rn],t._meridiem),de(t),ne(t)}function ce(t,e,i){var o;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?(o=t.isPM(i),o&&e<12&&(e+=12),o||12!==e||(e=0),e):e}function pe(t){var e,i,o,n,s;if(0===t._f.length)return p(t).invalidFormat=!0,void(t._d=new Date(NaN));for(n=0;n<t._f.length;n++)s=0,e=g({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[n],ue(e),f(e)&&(s+=p(e).charsLeftOver,s+=10*p(e).unusedTokens.length,p(e).score=s,(null==o||s<o)&&(o=s,i=e));l(t,i||e)}function fe(t){if(!t._d){var e=B(t._i);t._a=h([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),de(t)}}function me(t){var e=new y(ne(ve(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function ve(t){var e=t._i,i=t._f;return t._locale=t._locale||ie(t._l),null===e||void 0===i&&""===e?m({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),b(e)?new y(ne(e)):(a(e)?t._d=e:o(i)?pe(t):i?ue(t):ge(t),f(t)||(t._d=null),t))}function ge(t){var i=t._i;void 0===i?t._d=new Date(e.now()):a(i)?t._d=new Date(i.valueOf()):"string"==typeof i?re(t):o(i)?(t._a=h(i.slice(0),function(t){return parseInt(t,10)}),de(t)):"object"==typeof i?fe(t):r(i)?t._d=new Date(i):e.createFromInputFallback(t)}function ye(t,e,i,r,a){var h={};return i!==!0&&i!==!1||(r=i,i=void 0),(n(t)&&s(t)||o(t)&&0===t.length)&&(t=void 0),h._isAMomentObject=!0,h._useUTC=h._isUTC=a,h._l=i,h._i=t,h._f=e,h._strict=r,me(h)}function be(t,e,i,o){return ye(t,e,i,o,!1)}function _e(t,e){var i,n;if(1===e.length&&o(e[0])&&(e=e[0]),!e.length)return be();for(i=e[0],n=1;n<e.length;++n)e[n].isValid()&&!e[n][t](i)||(i=e[n]);return i}function we(){var t=[].slice.call(arguments,0);return _e("isBefore",t)}function xe(){var t=[].slice.call(arguments,0);return _e("isAfter",t)}function ke(t){var e=B(t),i=e.year||0,o=e.quarter||0,n=e.month||0,s=e.week||0,r=e.day||0,a=e.hour||0,h=e.minute||0,d=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*d+6e4*h+1e3*a*60*60,this._days=+r+7*s,this._months=+n+3*o+12*i,this._data={},this._locale=ie(),this._bubble()}function Oe(t){return t instanceof ke}function De(t){return t<0?Math.round(-1*t)*-1:Math.round(t)}function Se(t,e){q(t,0,0,function(){var t=this.utcOffset(),i="+";return t<0&&(t=-t,i="-"),i+U(~~(t/60),2)+e+U(~~t%60,2)})}function Me(t,e){var i=(e||"").match(t);if(null===i)return null;var o=i[i.length-1]||[],n=(o+"").match(jn)||["-",0,0],s=+(60*n[1])+w(n[2]);return 0===s?0:"+"===n[0]?s:-s}function Ce(t,i){var o,n;return i._isUTC?(o=i.clone(),n=(b(t)||a(t)?t.valueOf():be(t).valueOf())-o.valueOf(),o._d.setTime(o._d.valueOf()+n),e.updateOffset(o,!1),o):be(t).local()}function Te(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Ee(t,i){var o,n=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(t=Me(Qo,t),null===t)return this}else Math.abs(t)<16&&(t*=60);return!this._isUTC&&i&&(o=Te(this)),this._offset=t,this._isUTC=!0,null!=o&&this.add(o,"m"),n!==t&&(!i||this._changeInProgress?Ue(this,je(t-n,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?n:Te(this)}function Pe(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}function Ie(t){return this.utcOffset(0,t)}function Ne(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Te(this),"m")),this}function ze(){if(null!=this._tzm)this.utcOffset(this._tzm);else if("string"==typeof this._i){var t=Me(Ko,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this}function Re(t){return!!this.isValid()&&(t=t?be(t).utcOffset():0,(this.utcOffset()-t)%60===0)}function Le(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ae(){if(!v(this._isDSTShifted))return this._isDSTShifted;var t={};if(g(t,this),t=ve(t),t._a){var e=t._isUTC?u(t._a):be(t._a);this._isDSTShifted=this.isValid()&&x(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Be(){return!!this.isValid()&&!this._isUTC}function Fe(){return!!this.isValid()&&this._isUTC}function He(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function je(t,e){var i,o,n,s=t,a=null;return Oe(t)?s={ms:t._milliseconds,d:t._days,M:t._months}:r(t)?(s={},e?s[e]=t:s.milliseconds=t):(a=Wn.exec(t))?(i="-"===a[1]?-1:1,s={y:0,d:w(a[sn])*i,h:w(a[rn])*i,m:w(a[an])*i,s:w(a[hn])*i,ms:w(De(1e3*a[dn]))*i}):(a=Yn.exec(t))?(i="-"===a[1]?-1:1,s={y:We(a[2],i),M:We(a[3],i),w:We(a[4],i),d:We(a[5],i),h:We(a[6],i),m:We(a[7],i),s:We(a[8],i)}):null==s?s={}:"object"==typeof s&&("from"in s||"to"in s)&&(n=Ge(be(s.from),be(s.to)),s={},s.ms=n.milliseconds,s.M=n.months),o=new ke(s),Oe(t)&&d(t,"_locale")&&(o._locale=t._locale),o}function We(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function Ye(t,e){var i={milliseconds:0,months:0};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function Ge(t,e){var i;return t.isValid()&&e.isValid()?(e=Ce(e,t),t.isBefore(e)?i=Ye(t,e):(i=Ye(e,t),i.milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function Ve(t,e){return function(i,o){var n,s;return null===o||isNaN(+o)||(D(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),s=i,i=o,o=s),i="string"==typeof i?+i:i,n=je(i,o),Ue(this,n,t),this}}function Ue(t,i,o,n){var s=i._milliseconds,r=De(i._days),a=De(i._months);t.isValid()&&(n=null==n||n,s&&t._d.setTime(t._d.valueOf()+s*o),r&&Y(t,"Date",W(t,"Date")+r*o),a&&lt(t,W(t,"Month")+a*o),n&&e.updateOffset(t,r||a))}function qe(t,e){var i=t.diff(e,"days",!0);return i<-6?"sameElse":i<-1?"lastWeek":i<0?"lastDay":i<1?"sameDay":i<2?"nextDay":i<7?"nextWeek":"sameElse"}function Xe(t,i){var o=t||be(),n=Ce(o,this).startOf("day"),s=e.calendarFormat(this,n)||"sameElse",r=i&&(S(i[s])?i[s].call(this,o):i[s]);return this.format(r||this.localeData().calendar(s,this,be(o)))}function Ze(){return new y(this)}function Ke(t,e){var i=b(t)?t:be(t);return!(!this.isValid()||!i.isValid())&&(e=A(v(e)?"millisecond":e),"millisecond"===e?this.valueOf()>i.valueOf():i.valueOf()<this.clone().startOf(e).valueOf())}function Qe(t,e){var i=b(t)?t:be(t);return!(!this.isValid()||!i.isValid())&&(e=A(v(e)?"millisecond":e),"millisecond"===e?this.valueOf()<i.valueOf():this.clone().endOf(e).valueOf()<i.valueOf())}function Je(t,e,i,o){return o=o||"()",("("===o[0]?this.isAfter(t,i):!this.isBefore(t,i))&&(")"===o[1]?this.isBefore(e,i):!this.isAfter(e,i))}function $e(t,e){var i,o=b(t)?t:be(t);return!(!this.isValid()||!o.isValid())&&(e=A(e||"millisecond"),"millisecond"===e?this.valueOf()===o.valueOf():(i=o.valueOf(),this.clone().startOf(e).valueOf()<=i&&i<=this.clone().endOf(e).valueOf()))}function ti(t,e){return this.isSame(t,e)||this.isAfter(t,e)}function ei(t,e){return this.isSame(t,e)||this.isBefore(t,e)}function ii(t,e,i){var o,n,s,r;return this.isValid()?(o=Ce(t,this),o.isValid()?(n=6e4*(o.utcOffset()-this.utcOffset()),e=A(e),"year"===e||"month"===e||"quarter"===e?(r=oi(this,o),"quarter"===e?r/=3:"year"===e&&(r/=12)):(s=this-o,r="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?(s-n)/864e5:"week"===e?(s-n)/6048e5:s),i?r:_(r)):NaN):NaN}function oi(t,e){var i,o,n=12*(e.year()-t.year())+(e.month()-t.month()),s=t.clone().add(n,"months");return e-s<0?(i=t.clone().add(n-1,"months"),o=(e-s)/(s-i)):(i=t.clone().add(n+1,"months"),o=(e-s)/(i-s)),-(n+o)||0}function ni(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function si(){var t=this.clone().utc();return 0<t.year()&&t.year()<=9999?S(Date.prototype.toISOString)?this.toDate().toISOString():K(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):K(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ri(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var i="["+t+'("]',o=0<this.year()&&this.year()<=9999?"YYYY":"YYYYYY",n="-MM-DD[T]HH:mm:ss.SSS",s=e+'[")]';return this.format(i+o+n+s)}function ai(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var i=K(this,t);return this.localeData().postformat(i)}function hi(t,e){return this.isValid()&&(b(t)&&t.isValid()||be(t).isValid())?je({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function di(t){return this.from(be(),t)}function li(t,e){return this.isValid()&&(b(t)&&t.isValid()||be(t).isValid())?je({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function ui(t){return this.to(be(),t)}function ci(t){var e;return void 0===t?this._locale._abbr:(e=ie(t),null!=e&&(this._locale=e),this)}function pi(){return this._locale}function fi(t){switch(t=A(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this}function mi(t){return t=A(t),void 0===t||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))}function vi(){return this._d.valueOf()-6e4*(this._offset||0)}function gi(){return Math.floor(this.valueOf()/1e3)}function yi(){return new Date(this.valueOf())}function bi(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function _i(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function wi(){return this.isValid()?this.toISOString():null}function xi(){return f(this)}function ki(){return l({},p(this))}function Oi(){return p(this).overflow}function Di(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Si(t,e){q(0,[t,t.length],0,e)}function Mi(t){return Pi.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Ci(t){return Pi.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)}function Ti(){return Ot(this.year(),1,4)}function Ei(){var t=this.localeData()._week;return Ot(this.year(),t.dow,t.doy)}function Pi(t,e,i,o,n){var s;return null==t?kt(this,o,n).year:(s=Ot(t,o,n),e>s&&(e=s),Ii.call(this,t,e,i,o,n))}function Ii(t,e,i,o,n){var s=xt(t,e,i,o,n),r=_t(s.year,0,s.dayOfYear);return this.year(r.getUTCFullYear()),this.month(r.getUTCMonth()),this.date(r.getUTCDate()),this}function Ni(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}function zi(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}function Ri(t,e){e[dn]=w(1e3*("0."+t))}function Li(){return this._isUTC?"UTC":""}function Ai(){return this._isUTC?"Coordinated Universal Time":""}function Bi(t){return be(1e3*t)}function Fi(){return be.apply(null,arguments).parseZone()}function Hi(t){return t}function ji(t,e,i,o){var n=ie(),s=u().set(o,e);return n[i](s,t)}function Wi(t,e,i){if(r(t)&&(e=t,t=void 0),t=t||"",null!=e)return ji(t,e,i,"month");var o,n=[];for(o=0;o<12;o++)n[o]=ji(t,o,i,"month");return n}function Yi(t,e,i,o){"boolean"==typeof t?(r(e)&&(i=e,e=void 0),e=e||""):(e=t,i=e,t=!1,r(e)&&(i=e,e=void 0),e=e||"");var n=ie(),s=t?n._week.dow:0;if(null!=i)return ji(e,(i+s)%7,o,"day");var a,h=[];for(a=0;a<7;a++)h[a]=ji(e,(a+s)%7,o,"day");return h}function Gi(t,e){return Wi(t,e,"months")}function Vi(t,e){return Wi(t,e,"monthsShort")}function Ui(t,e,i){return Yi(t,e,i,"weekdays")}function qi(t,e,i){return Yi(t,e,i,"weekdaysShort")}function Xi(t,e,i){return Yi(t,e,i,"weekdaysMin")}function Zi(){var t=this._data;return this._milliseconds=ts(this._milliseconds),this._days=ts(this._days),this._months=ts(this._months),t.milliseconds=ts(t.milliseconds),t.seconds=ts(t.seconds),t.minutes=ts(t.minutes),t.hours=ts(t.hours),t.months=ts(t.months),t.years=ts(t.years),this}function Ki(t,e,i,o){var n=je(e,i);return t._milliseconds+=o*n._milliseconds,t._days+=o*n._days,t._months+=o*n._months,t._bubble()}function Qi(t,e){return Ki(this,t,e,1)}function Ji(t,e){return Ki(this,t,e,-1)}function $i(t){return t<0?Math.floor(t):Math.ceil(t)}function to(){var t,e,i,o,n,s=this._milliseconds,r=this._days,a=this._months,h=this._data;return s>=0&&r>=0&&a>=0||s<=0&&r<=0&&a<=0||(s+=864e5*$i(io(a)+r),r=0,a=0),h.milliseconds=s%1e3,t=_(s/1e3),h.seconds=t%60,e=_(t/60),h.minutes=e%60,i=_(e/60),h.hours=i%24,r+=_(i/24),n=_(eo(r)),a+=n,r-=$i(io(n)),o=_(a/12),a%=12,h.days=r,h.months=a,h.years=o,this}function eo(t){return 4800*t/146097}function io(t){return 146097*t/4800}function oo(t){var e,i,o=this._milliseconds;if(t=A(t),"month"===t||"year"===t)return e=this._days+o/864e5,i=this._months+eo(e),
-"month"===t?i:i/12;switch(e=this._days+Math.round(io(this._months)),t){case"week":return e/7+o/6048e5;case"day":return e+o/864e5;case"hour":return 24*e+o/36e5;case"minute":return 1440*e+o/6e4;case"second":return 86400*e+o/1e3;case"millisecond":return Math.floor(864e5*e)+o;default:throw new Error("Unknown unit "+t)}}function no(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*w(this._months/12)}function so(t){return function(){return this.as(t)}}function ro(t){return t=A(t),this[t+"s"]()}function ao(t){return function(){return this._data[t]}}function ho(){return _(this.days()/7)}function lo(t,e,i,o,n){return n.relativeTime(e||1,!!i,t,o)}function uo(t,e,i){var o=je(t).abs(),n=vs(o.as("s")),s=vs(o.as("m")),r=vs(o.as("h")),a=vs(o.as("d")),h=vs(o.as("M")),d=vs(o.as("y")),l=n<gs.s&&["s",n]||s<=1&&["m"]||s<gs.m&&["mm",s]||r<=1&&["h"]||r<gs.h&&["hh",r]||a<=1&&["d"]||a<gs.d&&["dd",a]||h<=1&&["M"]||h<gs.M&&["MM",h]||d<=1&&["y"]||["yy",d];return l[2]=e,l[3]=+t>0,l[4]=i,lo.apply(null,l)}function co(t){return void 0===t?vs:"function"==typeof t&&(vs=t,!0)}function po(t,e){return void 0!==gs[t]&&(void 0===e?gs[t]:(gs[t]=e,!0))}function fo(t){var e=this.localeData(),i=uo(this,!t,e);return t&&(i=e.pastFuture(+this,i)),e.postformat(i)}function mo(){var t,e,i,o=ys(this._milliseconds)/1e3,n=ys(this._days),s=ys(this._months);t=_(o/60),e=_(t/60),o%=60,t%=60,i=_(s/12),s%=12;var r=i,a=s,h=n,d=e,l=t,u=o,c=this.asSeconds();return c?(c<0?"-":"")+"P"+(r?r+"Y":"")+(a?a+"M":"")+(h?h+"D":"")+(d||l||u?"T":"")+(d?d+"H":"")+(l?l+"M":"")+(u?u+"S":""):"P0D"}var vo,go;go=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),i=e.length>>>0,o=0;o<i;o++)if(o in e&&t.call(this,e[o],o,e))return!0;return!1};var yo=go,bo=e.momentProperties=[],_o=!1,wo={};e.suppressDeprecationWarnings=!1,e.deprecationHandler=null;var xo;xo=Object.keys?Object.keys:function(t){var e,i=[];for(e in t)d(t,e)&&i.push(e);return i};var ko,Oo=xo,Do={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},So={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Mo="Invalid date",Co="%d",To=/\d{1,2}/,Eo={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Po={},Io={},No=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,zo=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ro={},Lo={},Ao=/\d/,Bo=/\d\d/,Fo=/\d{3}/,Ho=/\d{4}/,jo=/[+-]?\d{6}/,Wo=/\d\d?/,Yo=/\d\d\d\d?/,Go=/\d\d\d\d\d\d?/,Vo=/\d{1,3}/,Uo=/\d{1,4}/,qo=/[+-]?\d{1,6}/,Xo=/\d+/,Zo=/[+-]?\d+/,Ko=/Z|[+-]\d\d:?\d\d/gi,Qo=/Z|[+-]\d\d(?::?\d\d)?/gi,Jo=/[+-]?\d+(\.\d{1,3})?/,$o=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,tn={},en={},on=0,nn=1,sn=2,rn=3,an=4,hn=5,dn=6,ln=7,un=8;ko=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1};var cn=ko;q("M",["MM",2],"Mo",function(){return this.month()+1}),q("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),q("MMMM",0,0,function(t){return this.localeData().months(this,t)}),L("month","M"),F("month",8),J("M",Wo),J("MM",Wo,Bo),J("MMM",function(t,e){return e.monthsShortRegex(t)}),J("MMMM",function(t,e){return e.monthsRegex(t)}),it(["M","MM"],function(t,e){e[nn]=w(t)-1}),it(["MMM","MMMM"],function(t,e,i,o){var n=i._locale.monthsParse(t,o,i._strict);null!=n?e[nn]=n:p(i).invalidMonth=t});var pn=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,fn="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),mn="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),vn=$o,gn=$o;q("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),q(0,["YY",2],0,function(){return this.year()%100}),q(0,["YYYY",4],0,"year"),q(0,["YYYYY",5],0,"year"),q(0,["YYYYYY",6,!0],0,"year"),L("year","y"),F("year",1),J("Y",Zo),J("YY",Wo,Bo),J("YYYY",Uo,Ho),J("YYYYY",qo,jo),J("YYYYYY",qo,jo),it(["YYYYY","YYYYYY"],on),it("YYYY",function(t,i){i[on]=2===t.length?e.parseTwoDigitYear(t):w(t)}),it("YY",function(t,i){i[on]=e.parseTwoDigitYear(t)}),it("Y",function(t,e){e[on]=parseInt(t,10)}),e.parseTwoDigitYear=function(t){return w(t)+(w(t)>68?1900:2e3)};var yn=j("FullYear",!0);q("w",["ww",2],"wo","week"),q("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),F("week",5),F("isoWeek",5),J("w",Wo),J("ww",Wo,Bo),J("W",Wo),J("WW",Wo,Bo),ot(["w","ww","W","WW"],function(t,e,i,o){e[o.substr(0,1)]=w(t)});var bn={dow:0,doy:6};q("d",0,"do","day"),q("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),q("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),q("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),q("e",0,0,"weekday"),q("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),J("d",Wo),J("e",Wo),J("E",Wo),J("dd",function(t,e){return e.weekdaysMinRegex(t)}),J("ddd",function(t,e){return e.weekdaysShortRegex(t)}),J("dddd",function(t,e){return e.weekdaysRegex(t)}),ot(["dd","ddd","dddd"],function(t,e,i,o){var n=i._locale.weekdaysParse(t,o,i._strict);null!=n?e.d=n:p(i).invalidWeekday=t}),ot(["d","e","E"],function(t,e,i,o){e[o]=w(t)});var _n="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),wn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),kn=$o,On=$o,Dn=$o;q("H",["HH",2],0,"hour"),q("h",["hh",2],0,Gt),q("k",["kk",2],0,Vt),q("hmm",0,0,function(){return""+Gt.apply(this)+U(this.minutes(),2)}),q("hmmss",0,0,function(){return""+Gt.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),q("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),q("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Ut("a",!0),Ut("A",!1),L("hour","h"),F("hour",13),J("a",qt),J("A",qt),J("H",Wo),J("h",Wo),J("HH",Wo,Bo),J("hh",Wo,Bo),J("hmm",Yo),J("hmmss",Go),J("Hmm",Yo),J("Hmmss",Go),it(["H","HH"],rn),it(["a","A"],function(t,e,i){i._isPm=i._locale.isPM(t),i._meridiem=t}),it(["h","hh"],function(t,e,i){e[rn]=w(t),p(i).bigHour=!0}),it("hmm",function(t,e,i){var o=t.length-2;e[rn]=w(t.substr(0,o)),e[an]=w(t.substr(o)),p(i).bigHour=!0}),it("hmmss",function(t,e,i){var o=t.length-4,n=t.length-2;e[rn]=w(t.substr(0,o)),e[an]=w(t.substr(o,2)),e[hn]=w(t.substr(n)),p(i).bigHour=!0}),it("Hmm",function(t,e,i){var o=t.length-2;e[rn]=w(t.substr(0,o)),e[an]=w(t.substr(o))}),it("Hmmss",function(t,e,i){var o=t.length-4,n=t.length-2;e[rn]=w(t.substr(0,o)),e[an]=w(t.substr(o,2)),e[hn]=w(t.substr(n))});var Sn,Mn=/[ap]\.?m?\.?/i,Cn=j("Hours",!0),Tn={calendar:Do,longDateFormat:So,invalidDate:Mo,ordinal:Co,ordinalParse:To,relativeTime:Eo,months:fn,monthsShort:mn,week:bn,weekdays:_n,weekdaysMin:xn,weekdaysShort:wn,meridiemParse:Mn},En={},Pn={},In=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Nn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,zn=/Z|[+-]\d\d(?::?\d\d)?/,Rn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Ln=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],An=/^\/?Date\((\-?\d+)/i;e.createFromInputFallback=O("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),e.ISO_8601=function(){};var Bn=O("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=be.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:m()}),Fn=O("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=be.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:m()}),Hn=function(){return Date.now?Date.now():+new Date};Se("Z",":"),Se("ZZ",""),J("Z",Qo),J("ZZ",Qo),it(["Z","ZZ"],function(t,e,i){i._useUTC=!0,i._tzm=Me(Qo,t)});var jn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var Wn=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Yn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;je.fn=ke.prototype;var Gn=Ve(1,"add"),Vn=Ve(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Un=O("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});q(0,["gg",2],0,function(){return this.weekYear()%100}),q(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Si("gggg","weekYear"),Si("ggggg","weekYear"),Si("GGGG","isoWeekYear"),Si("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),J("G",Zo),J("g",Zo),J("GG",Wo,Bo),J("gg",Wo,Bo),J("GGGG",Uo,Ho),J("gggg",Uo,Ho),J("GGGGG",qo,jo),J("ggggg",qo,jo),ot(["gggg","ggggg","GGGG","GGGGG"],function(t,e,i,o){e[o.substr(0,2)]=w(t)}),ot(["gg","GG"],function(t,i,o,n){i[n]=e.parseTwoDigitYear(t)}),q("Q",0,"Qo","quarter"),L("quarter","Q"),F("quarter",7),J("Q",Ao),it("Q",function(t,e){e[nn]=3*(w(t)-1)}),q("D",["DD",2],"Do","date"),L("date","D"),F("date",9),J("D",Wo),J("DD",Wo,Bo),J("Do",function(t,e){return t?e._ordinalParse:e._ordinalParseLenient}),it(["D","DD"],sn),it("Do",function(t,e){e[sn]=w(t.match(Wo)[0],10)});var qn=j("Date",!0);q("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),F("dayOfYear",4),J("DDD",Vo),J("DDDD",Fo),it(["DDD","DDDD"],function(t,e,i){i._dayOfYear=w(t)}),q("m",["mm",2],0,"minute"),L("minute","m"),F("minute",14),J("m",Wo),J("mm",Wo,Bo),it(["m","mm"],an);var Xn=j("Minutes",!1);q("s",["ss",2],0,"second"),L("second","s"),F("second",15),J("s",Wo),J("ss",Wo,Bo),it(["s","ss"],hn);var Zn=j("Seconds",!1);q("S",0,0,function(){return~~(this.millisecond()/100)}),q(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),q(0,["SSS",3],0,"millisecond"),q(0,["SSSS",4],0,function(){return 10*this.millisecond()}),q(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),q(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),q(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),q(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),q(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),L("millisecond","ms"),F("millisecond",16),J("S",Vo,Ao),J("SS",Vo,Bo),J("SSS",Vo,Fo);var Kn;for(Kn="SSSS";Kn.length<=9;Kn+="S")J(Kn,Xo);for(Kn="S";Kn.length<=9;Kn+="S")it(Kn,Ri);var Qn=j("Milliseconds",!1);q("z",0,0,"zoneAbbr"),q("zz",0,0,"zoneName");var Jn=y.prototype;Jn.add=Gn,Jn.calendar=Xe,Jn.clone=Ze,Jn.diff=ii,Jn.endOf=mi,Jn.format=ai,Jn.from=hi,Jn.fromNow=di,Jn.to=li,Jn.toNow=ui,Jn.get=G,Jn.invalidAt=Oi,Jn.isAfter=Ke,Jn.isBefore=Qe,Jn.isBetween=Je,Jn.isSame=$e,Jn.isSameOrAfter=ti,Jn.isSameOrBefore=ei,Jn.isValid=xi,Jn.lang=Un,Jn.locale=ci,Jn.localeData=pi,Jn.max=Fn,Jn.min=Bn,Jn.parsingFlags=ki,Jn.set=V,Jn.startOf=fi,Jn.subtract=Vn,Jn.toArray=bi,Jn.toObject=_i,Jn.toDate=yi,Jn.toISOString=si,Jn.inspect=ri,Jn.toJSON=wi,Jn.toString=ni,Jn.unix=gi,Jn.valueOf=vi,Jn.creationData=Di,Jn.year=yn,Jn.isLeapYear=yt,Jn.weekYear=Mi,Jn.isoWeekYear=Ci,Jn.quarter=Jn.quarters=Ni,Jn.month=ut,Jn.daysInMonth=ct,Jn.week=Jn.weeks=Ct,Jn.isoWeek=Jn.isoWeeks=Tt,Jn.weeksInYear=Ei,Jn.isoWeeksInYear=Ti,Jn.date=qn,Jn.day=Jn.days=At,Jn.weekday=Bt,Jn.isoWeekday=Ft,Jn.dayOfYear=zi,Jn.hour=Jn.hours=Cn,Jn.minute=Jn.minutes=Xn,Jn.second=Jn.seconds=Zn,Jn.millisecond=Jn.milliseconds=Qn,Jn.utcOffset=Ee,Jn.utc=Ie,Jn.local=Ne,Jn.parseZone=ze,Jn.hasAlignedHourOffset=Re,Jn.isDST=Le,Jn.isLocal=Be,Jn.isUtcOffset=Fe,Jn.isUtc=He,Jn.isUTC=He,Jn.zoneAbbr=Li,Jn.zoneName=Ai,Jn.dates=O("dates accessor is deprecated. Use date instead.",qn),Jn.months=O("months accessor is deprecated. Use month instead",ut),Jn.years=O("years accessor is deprecated. Use year instead",yn),Jn.zone=O("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Pe),Jn.isDSTShifted=O("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ae);var $n=T.prototype;$n.calendar=E,$n.longDateFormat=P,$n.invalidDate=I,$n.ordinal=N,$n.preparse=Hi,$n.postformat=Hi,$n.relativeTime=z,$n.pastFuture=R,$n.set=M,$n.months=rt,$n.monthsShort=at,$n.monthsParse=dt,$n.monthsRegex=ft,$n.monthsShortRegex=pt,$n.week=Dt,$n.firstDayOfYear=Mt,$n.firstDayOfWeek=St,$n.weekdays=It,$n.weekdaysMin=zt,$n.weekdaysShort=Nt,$n.weekdaysParse=Lt,$n.weekdaysRegex=Ht,$n.weekdaysShortRegex=jt,$n.weekdaysMinRegex=Wt,$n.isPM=Xt,$n.meridiem=Zt,$t("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,i=1===w(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),e.lang=O("moment.lang is deprecated. Use moment.locale instead.",$t),e.langData=O("moment.langData is deprecated. Use moment.localeData instead.",ie);var ts=Math.abs,es=so("ms"),is=so("s"),os=so("m"),ns=so("h"),ss=so("d"),rs=so("w"),as=so("M"),hs=so("y"),ds=ao("milliseconds"),ls=ao("seconds"),us=ao("minutes"),cs=ao("hours"),ps=ao("days"),fs=ao("months"),ms=ao("years"),vs=Math.round,gs={s:45,m:45,h:22,d:26,M:11},ys=Math.abs,bs=ke.prototype;return bs.abs=Zi,bs.add=Qi,bs.subtract=Ji,bs.as=oo,bs.asMilliseconds=es,bs.asSeconds=is,bs.asMinutes=os,bs.asHours=ns,bs.asDays=ss,bs.asWeeks=rs,bs.asMonths=as,bs.asYears=hs,bs.valueOf=no,bs._bubble=to,bs.get=ro,bs.milliseconds=ds,bs.seconds=ls,bs.minutes=us,bs.hours=cs,bs.days=ps,bs.weeks=ho,bs.months=fs,bs.years=ms,bs.humanize=fo,bs.toISOString=mo,bs.toString=mo,bs.toJSON=mo,bs.locale=ci,bs.localeData=pi,bs.toIsoString=O("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",mo),bs.lang=Un,q("X",0,0,"unix"),q("x",0,0,"valueOf"),J("x",Zo),J("X",Jo),it("X",function(t,e,i){i._d=new Date(1e3*parseFloat(t,10))}),it("x",function(t,e,i){i._d=new Date(w(t))}),e.version="2.17.1",i(be),e.fn=Jn,e.min=we,e.max=xe,e.now=Hn,e.utc=u,e.unix=Bi,e.months=Gi,e.isDate=a,e.locale=$t,e.invalid=m,e.duration=je,e.isMoment=b,e.weekdays=Ui,e.parseZone=Fi,e.localeData=ie,e.isDuration=Oe,e.monthsShort=Vi,e.weekdaysMin=Xi,e.defineLocale=te,e.updateLocale=ee,e.locales=oe,e.weekdaysShort=qi,e.normalizeUnits=A,e.relativeTimeRounding=co,e.relativeTimeThreshold=po,e.calendarFormat=qe,e.prototype=Jn,e})}).call(e,i(86)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},function(t,e){function i(t){throw new Error("Cannot find module '"+t+"'.")}i.keys=function(){return[]},i.resolve=i,t.exports=i,i.id=87},function(t,e){(function(e){function i(t,e,i){var o=e&&i||0,n=0;for(e=e||[],t.toLowerCase().replace(/[0-9a-f]{2}/g,function(t){n<16&&(e[o+n++]=u[t])});n<16;)e[o+n++]=0;return e}function o(t,e){var i=e||0,o=l;return o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]}function n(t,e,i){var n=e&&i||0,s=e||[];t=t||{};var r=void 0!==t.clockseq?t.clockseq:m,a=void 0!==t.msecs?t.msecs:(new Date).getTime(),h=void 0!==t.nsecs?t.nsecs:g+1,d=a-v+(h-g)/1e4;if(d<0&&void 0===t.clockseq&&(r=r+1&16383),(d<0||a>v)&&void 0===t.nsecs&&(h=0),h>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");v=a,g=h,m=r,a+=122192928e5;var l=(1e4*(268435455&a)+h)%4294967296;s[n++]=l>>>24&255,s[n++]=l>>>16&255,s[n++]=l>>>8&255,s[n++]=255&l;var u=a/4294967296*1e4&268435455;s[n++]=u>>>8&255,s[n++]=255&u,s[n++]=u>>>24&15|16,s[n++]=u>>>16&255,s[n++]=r>>>8|128,s[n++]=255&r;for(var c=t.node||f,p=0;p<6;p++)s[n+p]=c[p];return e?e:o(s)}function s(t,e,i){var n=e&&i||0;"string"==typeof t&&(e="binary"==t?new Array(16):null,t=null),t=t||{};var s=t.random||(t.rng||r)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,e)for(var a=0;a<16;a++)e[n+a]=s[a];return e||o(s)}var r,a="undefined"!=typeof window?window:"undefined"!=typeof e?e:null;if(a&&a.crypto&&crypto.getRandomValues){var h=new Uint8Array(16);r=function(){return crypto.getRandomValues(h),h}}if(!r){var d=new Array(16);r=function(){for(var t,e=0;e<16;e++)0===(3&e)&&(t=4294967296*Math.random()),d[e]=t>>>((3&e)<<3)&255;return d}}for(var l=[],u={},c=0;c<256;c++)l[c]=(c+256).toString(16).substr(1),u[l[c]]=c;var p=r(),f=[1|p[0],p[1],p[2],p[3],p[4],p[5]],m=16383&(p[6]<<8|p[7]),v=0,g=0,y=s;y.v1=n,y.v4=s,y.parse=i,y.unparse=o,t.exports=y}).call(e,function(){return this}())},function(t,e,i){e.util=i(1),e.DOMutil=i(90),e.DataSet=i(91),e.DataView=i(93),e.Queue=i(92),e.Graph3d=i(94),e.graph3d={Camera:i(98),Filter:i(103),Point2d:i(97),Point3d:i(96),Slider:i(104),StepNumber:i(105)},e.moment=i(84),e.Hammer=i(108),e.keycharm=i(111)},function(t,e){e.prepareElements=function(t){for(var e in t)t.hasOwnProperty(e)&&(t[e].redundant=t[e].used,t[e].used=[])},e.cleanupElements=function(t){for(var e in t)if(t.hasOwnProperty(e)&&t[e].redundant){for(var i=0;i<t[e].redundant.length;i++)t[e].redundant[i].parentNode.removeChild(t[e].redundant[i]);t[e].redundant=[]}},e.resetElements=function(t){e.prepareElements(t),e.cleanupElements(t),e.prepareElements(t)},e.getSVGElement=function(t,e,i){var o;return e.hasOwnProperty(t)?e[t].redundant.length>0?(o=e[t].redundant[0],e[t].redundant.shift()):(o=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(o)):(o=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(o)),e[t].used.push(o),o},e.getDOMElement=function(t,e,i,o){var n;return e.hasOwnProperty(t)?e[t].redundant.length>0?(n=e[t].redundant[0],e[t].redundant.shift()):(n=document.createElement(t),void 0!==o?i.insertBefore(n,o):i.appendChild(n)):(n=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==o?i.insertBefore(n,o):i.appendChild(n)),e[t].used.push(n),n},e.drawPoint=function(t,i,o,n,s,r){var a;if("circle"==o.style?(a=e.getSVGElement("circle",n,s),a.setAttributeNS(null,"cx",t),a.setAttributeNS(null,"cy",i),a.setAttributeNS(null,"r",.5*o.size)):(a=e.getSVGElement("rect",n,s),a.setAttributeNS(null,"x",t-.5*o.size),a.setAttributeNS(null,"y",i-.5*o.size),a.setAttributeNS(null,"width",o.size),a.setAttributeNS(null,"height",o.size)),void 0!==o.styles&&a.setAttributeNS(null,"style",o.styles),a.setAttributeNS(null,"class",o.className+" vis-point"),r){var h=e.getSVGElement("text",n,s);r.xOffset&&(t+=r.xOffset),r.yOffset&&(i+=r.yOffset),r.content&&(h.textContent=r.content),r.className&&h.setAttributeNS(null,"class",r.className+" vis-label"),h.setAttributeNS(null,"x",t),h.setAttributeNS(null,"y",i)}return a},e.drawBar=function(t,i,o,n,s,r,a,h){if(0!=n){n<0&&(n*=-1,i-=n);var d=e.getSVGElement("rect",r,a);d.setAttributeNS(null,"x",t-.5*o),d.setAttributeNS(null,"y",i),d.setAttributeNS(null,"width",o),d.setAttributeNS(null,"height",n),d.setAttributeNS(null,"class",s),h&&d.setAttributeNS(null,"style",h)}}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){if(t&&!Array.isArray(t)&&(e=t,t=null),this._options=e||{},this._data={},this.length=0,this._fieldId=this._options.fieldId||"id",this._type={},this._options.type)for(var i=(0,l.default)(this._options.type),o=0,n=i.length;o<n;o++){var s=i[o],r=this._options.type[s];"Date"==r||"ISODate"==r||"ASPDate"==r?this._type[s]="Date":this._type[s]=r}if(this._options.convert)throw new Error('Option "convert" is deprecated. Use "type" instead.');this._subscribers={},t&&this.add(t),this.setOptions(e)}var s=i(82),r=o(s),a=i(62),h=o(a),d=i(58),l=o(d),u=i(1),c=i(92);n.prototype.setOptions=function(t){t&&void 0!==t.queue&&(t.queue===!1?this._queue&&(this._queue.destroy(),delete this._queue):(this._queue||(this._queue=c.extend(this,{replace:["add","update","remove"]})),"object"===(0,h.default)(t.queue)&&this._queue.setOptions(t.queue)))},n.prototype.on=function(t,e){var i=this._subscribers[t];i||(i=[],this._subscribers[t]=i),i.push({callback:e})},n.prototype.subscribe=function(){throw new Error("DataSet.subscribe is deprecated. Use DataSet.on instead.")},n.prototype.off=function(t,e){var i=this._subscribers[t];i&&(this._subscribers[t]=i.filter(function(t){return t.callback!=e}))},n.prototype.unsubscribe=function(){throw new Error("DataSet.unsubscribe is deprecated. Use DataSet.off instead.")},n.prototype._trigger=function(t,e,i){if("*"==t)throw new Error("Cannot trigger event *");var o=[];t in this._subscribers&&(o=o.concat(this._subscribers[t])),"*"in this._subscribers&&(o=o.concat(this._subscribers["*"]));for(var n=0,s=o.length;n<s;n++){var r=o[n];r.callback&&r.callback(t,e,i||null)}},n.prototype.add=function(t,e){var i,o=[],n=this;if(Array.isArray(t))for(var s=0,r=t.length;s<r;s++)i=n._addItem(t[s]),o.push(i);else{if(!(t instanceof Object))throw new Error("Unknown dataType");i=n._addItem(t),o.push(i)}return o.length&&this._trigger("add",{items:o},e),o},n.prototype.update=function(t,e){var i=[],o=[],n=[],s=[],r=this,a=r._fieldId,h=function(t){var e=t[a];if(r._data[e]){var h=u.extend({},r._data[e]);e=r._updateItem(t),o.push(e),s.push(t),n.push(h)}else e=r._addItem(t),i.push(e)};if(Array.isArray(t))for(var d=0,l=t.length;d<l;d++)t[d]instanceof Object?h(t[d]):console.warn("Ignoring input item, which is not an object at index "+d);else{if(!(t instanceof Object))throw new Error("Unknown dataType");h(t)}if(i.length&&this._trigger("add",{items:i},e),o.length){var c={items:o,oldData:n,data:s};this._trigger("update",c,e)}return i.concat(o)},n.prototype.get=function(t){var e,i,o,n=this,s=u.getType(arguments[0]);"String"==s||"Number"==s?(e=arguments[0],o=arguments[1]):"Array"==s?(i=arguments[0],o=arguments[1]):o=arguments[0];var r;if(o&&o.returnType){var a=["Array","Object"];r=a.indexOf(o.returnType)==-1?"Array":o.returnType}else r="Array";var h,d,c,p,f,m=o&&o.type||this._options.type,v=o&&o.filter,g=[];if(void 0!=e)h=n._getItem(e,m),h&&v&&!v(h)&&(h=null);else if(void 0!=i)for(p=0,f=i.length;p<f;p++)h=n._getItem(i[p],m),v&&!v(h)||g.push(h);else for(d=(0,l.default)(this._data),p=0,f=d.length;p<f;p++)c=d[p],h=n._getItem(c,m),v&&!v(h)||g.push(h);if(o&&o.order&&void 0==e&&this._sort(g,o.order),o&&o.fields){var y=o.fields;if(void 0!=e)h=this._filterFields(h,y);else for(p=0,f=g.length;p<f;p++)g[p]=this._filterFields(g[p],y)}if("Object"==r){var b,_={};for(p=0,f=g.length;p<f;p++)b=g[p],_[b.id]=b;return _}return void 0!=e?h:g},n.prototype.getIds=function(t){var e,i,o,n,s,r=this._data,a=t&&t.filter,h=t&&t.order,d=t&&t.type||this._options.type,u=(0,l.default)(r),c=[];if(a)if(h){for(s=[],e=0,i=u.length;e<i;e++)o=u[e],n=this._getItem(o,d),a(n)&&s.push(n);for(this._sort(s,h),e=0,i=s.length;e<i;e++)c.push(s[e][this._fieldId])}else for(e=0,i=u.length;e<i;e++)o=u[e],n=this._getItem(o,d),a(n)&&c.push(n[this._fieldId]);else if(h){for(s=[],e=0,i=u.length;e<i;e++)o=u[e],s.push(r[o]);for(this._sort(s,h),e=0,i=s.length;e<i;e++)c.push(s[e][this._fieldId])}else for(e=0,i=u.length;e<i;e++)o=u[e],n=r[o],c.push(n[this._fieldId]);return c},n.prototype.getDataSet=function(){return this},n.prototype.forEach=function(t,e){var i,o,n,s,r=e&&e.filter,a=e&&e.type||this._options.type,h=this._data,d=(0,l.default)(h);if(e&&e.order){var u=this.get(e);for(i=0,o=u.length;i<o;i++)n=u[i],s=n[this._fieldId],t(n,s)}else for(i=0,o=d.length;i<o;i++)s=d[i],n=this._getItem(s,a),r&&!r(n)||t(n,s)},n.prototype.map=function(t,e){var i,o,n,s,r=e&&e.filter,a=e&&e.type||this._options.type,h=[],d=this._data,u=(0,l.default)(d);for(i=0,o=u.length;i<o;i++)n=u[i],s=this._getItem(n,a),r&&!r(s)||h.push(t(s,n));return e&&e.order&&this._sort(h,e.order),h},n.prototype._filterFields=function(t,e){if(!t)return t;var i,o,n={},s=(0,l.default)(t),r=s.length;if(Array.isArray(e))for(i=0;i<r;i++)o=s[i],e.indexOf(o)!=-1&&(n[o]=t[o]);else for(i=0;i<r;i++)o=s[i],e.hasOwnProperty(o)&&(n[e[o]]=t[o]);return n},n.prototype._sort=function(t,e){if(u.isString(e)){var i=e;t.sort(function(t,e){var o=t[i],n=e[i];return o>n?1:o<n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},n.prototype.remove=function(t,e){var i,o,n,s,r=[],a=[],h=[];for(h=Array.isArray(t)?t:[t],i=0,o=h.length;i<o;i++)s=this._remove(h[i]),s&&(n=s[this._fieldId],void 0!=n&&(r.push(n),a.push(s)));return r.length&&this._trigger("remove",{items:r,oldData:a},e),r},n.prototype._remove=function(t){var e,i;return u.isNumber(t)||u.isString(t)?i=t:t instanceof Object&&(i=t[this._fieldId]),void 0!==i&&this._data[i]?(e=this._data[i],delete this._data[i],this.length--,e):null},n.prototype.clear=function(t){var e,i,o=(0,l.default)(this._data),n=[];for(e=0,i=o.length;e<i;e++)n.push(this._data[o[e]]);return this._data={},this.length=0,this._trigger("remove",{items:o,oldData:n},t),o},n.prototype.max=function(t){var e,i,o=this._data,n=(0,l.default)(o),s=null,r=null;for(e=0,i=n.length;e<i;e++){var a=n[e],h=o[a],d=h[t];null!=d&&(!s||d>r)&&(s=h,r=d)}return s},n.prototype.min=function(t){var e,i,o=this._data,n=(0,l.default)(o),s=null,r=null;for(e=0,i=n.length;e<i;e++){var a=n[e],h=o[a],d=h[t];null!=d&&(!s||d<r)&&(s=h,r=d)}return s},n.prototype.distinct=function(t){var e,i,o,n=this._data,s=(0,l.default)(n),r=[],a=this._options.type&&this._options.type[t]||null,h=0;for(e=0,o=s.length;e<o;e++){var d=s[e],c=n[d],p=c[t],f=!1;for(i=0;i<h;i++)if(r[i]==p){f=!0;break}f||void 0===p||(r[h]=p,h++)}if(a)for(e=0,o=r.length;e<o;e++)r[e]=u.convert(r[e],a);return r},n.prototype._addItem=function(t){var e=t[this._fieldId];if(void 0!=e){if(this._data[e])throw new Error("Cannot add item: item with id "+e+" already exists")}else e=u.randomUUID(),t[this._fieldId]=e;var i,o,n={},s=(0,l.default)(t);for(i=0,o=s.length;i<o;i++){var r=s[i],a=this._type[r];n[r]=u.convert(t[r],a)}return this._data[e]=n,this.length++,e},n.prototype._getItem=function(t,e){var i,o,n,s,r=this._data[t];if(!r)return null;var a={},h=(0,l.default)(r);if(e)for(n=0,s=h.length;n<s;n++)i=h[n],o=r[i],a[i]=u.convert(o,e[i]);else for(n=0,s=h.length;n<s;n++)i=h[n],o=r[i],a[i]=o;return a[this._fieldId]||(a[this._fieldId]=r.id),a},n.prototype._updateItem=function(t){var e=t[this._fieldId];if(void 0==e)throw new Error("Cannot update item: item has no id (item: "+(0,r.default)(t)+")");var i=this._data[e];if(!i)throw new Error("Cannot update item: no item with id "+e+" found");for(var o=(0,l.default)(t),n=0,s=o.length;n<s;n++){var a=o[n],h=this._type[a];i[a]=u.convert(t[a],h)}return e},t.exports=n},function(t,e){function i(t){this.delay=null,this.max=1/0,this._queue=[],this._timeout=null,this._extended=null,this.setOptions(t)}i.prototype.setOptions=function(t){t&&"undefined"!=typeof t.delay&&(this.delay=t.delay),t&&"undefined"!=typeof t.max&&(this.max=t.max),this._flushIfNeeded()},i.extend=function(t,e){var o=new i(e);if(void 0!==t.flush)throw new Error("Target object already has a property flush");t.flush=function(){o.flush()};var n=[{name:"flush",original:void 0}];if(e&&e.replace)for(var s=0;s<e.replace.length;s++){var r=e.replace[s];n.push({name:r,original:t[r]}),o.replace(t,r)}return o._extended={object:t,methods:n},o},i.prototype.destroy=function(){if(this.flush(),this._extended){for(var t=this._extended.object,e=this._extended.methods,i=0;i<e.length;i++){var o=e[i];o.original?t[o.name]=o.original:delete t[o.name]}this._extended=null}},i.prototype.replace=function(t,e){var i=this,o=t[e];if(!o)throw new Error("Method "+e+" undefined");t[e]=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];i.queue({args:t,fn:o,context:this})}},i.prototype.queue=function(t){"function"==typeof t?this._queue.push({fn:t}):this._queue.push(t),this._flushIfNeeded()},i.prototype._flushIfNeeded=function(){if(this._queue.length>this.max&&this.flush(),clearTimeout(this._timeout),this.queue.length>0&&"number"==typeof this.delay){var t=this;this._timeout=setTimeout(function(){t.flush()},this.delay)}},i.prototype.flush=function(){for(;this._queue.length>0;){var t=this._queue.shift();t.fn.apply(t.context||t.fn,t.args||[])}},t.exports=i},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){this._data=null,this._ids={},this.length=0,this._options=e||{},this._fieldId="id",this._subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}var s=i(58),r=o(s),a=i(1),h=i(91);n.prototype.setData=function(t){var e,i,o,n,s;if(this._data){for(this._data.off&&this._data.off("*",this.listener),e=this._data.getIds({filter:this._options&&this._options.filter}),s=[],o=0,n=e.length;o<n;o++)s.push(this._data._data[e[o]]);this._ids={},this.length=0,this._trigger("remove",{items:e,oldData:s})}if(this._data=t,this._data){for(this._fieldId=this._options.fieldId||this._data&&this._data.options&&this._data.options.fieldId||"id",e=this._data.getIds({filter:this._options&&this._options.filter}),o=0,n=e.length;o<n;o++)i=e[o],this._ids[i]=!0;this.length=e.length,this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},n.prototype.refresh=function(){var t,e,i,o=this._data.getIds({filter:this._options&&this._options.filter}),n=(0,r.default)(this._ids),s={},a=[],h=[],d=[];for(e=0,i=o.length;e<i;e++)t=o[e],s[t]=!0,this._ids[t]||(a.push(t),this._ids[t]=!0);for(e=0,i=n.length;e<i;e++)t=n[e],s[t]||(h.push(t),d.push(this._data._data[t]),delete this._ids[t]);this.length+=a.length-h.length,a.length&&this._trigger("add",{items:a}),h.length&&this._trigger("remove",{items:h,oldData:d})},n.prototype.get=function(t){var e,i,o,n=this,s=a.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(e=arguments[0],i=arguments[1],o=arguments[2]):(i=arguments[0],o=arguments[1]);var r=a.extend({},this._options,i);this._options.filter&&i&&i.filter&&(r.filter=function(t){return n._options.filter(t)&&i.filter(t)});var h=[];return void 0!=e&&h.push(e),h.push(r),h.push(o),this._data&&this._data.get.apply(this._data,h)},n.prototype.getIds=function(t){var e;if(this._data){var i,o=this._options.filter;i=t&&t.filter?o?function(e){return o(e)&&t.filter(e)}:t.filter:o,e=this._data.getIds({filter:i,order:t&&t.order})}else e=[];return e},n.prototype.map=function(t,e){var i=[];if(this._data){var o,n=this._options.filter;o=e&&e.filter?n?function(t){return n(t)&&e.filter(t)}:e.filter:n,i=this._data.map(t,{filter:o,order:e&&e.order})}else i=[];return i},n.prototype.getDataSet=function(){for(var t=this;t instanceof n;)t=t._data;return t||null},n.prototype._onEvent=function(t,e,i){var o,n,s,r,a=e&&e.items,h=[],d=[],l=[],u=[],c=[],p=[];if(a&&this._data){switch(t){case"add":for(o=0,n=a.length;o<n;o++)s=a[o],r=this.get(s),r&&(this._ids[s]=!0,h.push(s));break;case"update":for(o=0,n=a.length;o<n;o++)s=a[o],r=this.get(s),r?this._ids[s]?(d.push(s),c.push(e.data[o]),u.push(e.oldData[o])):(this._ids[s]=!0,h.push(s)):this._ids[s]&&(delete this._ids[s],l.push(s),p.push(e.oldData[o]));break;case"remove":for(o=0,n=a.length;o<n;o++)s=a[o],this._ids[s]&&(delete this._ids[s],l.push(s),p.push(e.oldData[o]))}this.length+=h.length-l.length,h.length&&this._trigger("add",{
-items:h},i),d.length&&this._trigger("update",{items:d,oldData:u,data:c},i),l.length&&this._trigger("remove",{items:l,oldData:p},i)}},n.prototype.on=h.prototype.on,n.prototype.off=h.prototype.off,n.prototype._trigger=h.prototype._trigger,n.prototype.subscribe=n.prototype.on,n.prototype.unsubscribe=n.prototype.off,t.exports=n},function(t,e,i){function o(t,e,i){if(!(this instanceof o))throw new SyntaxError("Constructor must be called with the new operator");this.containerElement=t,this.dataTable=null,this.dataPoints=null,this.create(),v.setDefaults(y,this),this.colX=void 0,this.colY=void 0,this.colZ=void 0,this.colValue=void 0,this.colFilter=void 0,this.setOptions(i),e&&this.setData(e)}function n(t){return"clientX"in t?t.clientX:t.targetTouches[0]&&t.targetTouches[0].clientX||0}function s(t){return"clientY"in t?t.clientY:t.targetTouches[0]&&t.targetTouches[0].clientY||0}var r=i(95),a=i(91),h=i(93),d=i(1),l=i(96),u=i(97),c=(i(98),i(103)),p=i(104),f=i(105),m=i(106),v=i(107);o.STYLE=v.STYLE;var g=void 0,y={width:"400px",height:"400px",filterLabel:"time",legendLabel:"value",xLabel:"x",yLabel:"y",zLabel:"z",xValueLabel:function(t){return t},yValueLabel:function(t){return t},zValueLabel:function(t){return t},showGrid:!0,showPerspective:!0,showShadow:!1,keepAspectRatio:!0,verticalRatio:.5,dotSizeRatio:.02,showAnimationControls:g,animationInterval:1e3,animationPreload:!1,animationAutoStart:g,axisColor:"#4D4D4D",gridColor:"#D3D3D3",xCenter:"55%",yCenter:"50%",style:o.STYLE.DOT,tooltip:!1,showLegend:g,backgroundColor:g,dataColor:{fill:"#7DC1FF",stroke:"#3267D2",strokeWidth:1},cameraPosition:{horizontal:1,vertical:.5,distance:1.7},xBarWidth:g,yBarWidth:g,valueMin:g,valueMax:g,xMin:g,xMax:g,xStep:g,yMin:g,yMax:g,yStep:g,zMin:g,zMax:g,zStep:g};r(o.prototype),o.prototype._setScale=function(){this.scale=new l(1/this.xRange.range(),1/this.yRange.range(),1/this.zRange.range()),this.keepAspectRatio&&(this.scale.x<this.scale.y?this.scale.y=this.scale.x:this.scale.x=this.scale.y),this.scale.z*=this.verticalRatio,void 0!==this.valueRange&&(this.scale.value=1/this.valueRange.range());var t=this.xRange.center()*this.scale.x,e=this.yRange.center()*this.scale.y,i=this.zRange.center()*this.scale.z;this.camera.setArmLocation(t,e,i)},o.prototype._convert3Dto2D=function(t){var e=this._convertPointToTranslation(t);return this._convertTranslationToScreen(e)},o.prototype._convertPointToTranslation=function(t){var e=this.camera.getCameraLocation(),i=this.camera.getCameraRotation(),o=t.x*this.scale.x,n=t.y*this.scale.y,s=t.z*this.scale.z,r=e.x,a=e.y,h=e.z,d=Math.sin(i.x),u=Math.cos(i.x),c=Math.sin(i.y),p=Math.cos(i.y),f=Math.sin(i.z),m=Math.cos(i.z),v=p*(f*(n-a)+m*(o-r))-c*(s-h),g=d*(p*(s-h)+c*(f*(n-a)+m*(o-r)))+u*(m*(n-a)-f*(o-r)),y=u*(p*(s-h)+c*(f*(n-a)+m*(o-r)))-d*(m*(n-a)-f*(o-r));return new l(v,g,y)},o.prototype._convertTranslationToScreen=function(t){var e,i,o=this.eye.x,n=this.eye.y,s=this.eye.z,r=t.x,a=t.y,h=t.z;return this.showPerspective?(e=(r-o)*(s/h),i=(a-n)*(s/h)):(e=r*-(s/this.camera.getArmLength()),i=a*-(s/this.camera.getArmLength())),new u(this.currentXCenter+e*this.frame.canvas.clientWidth,this.currentYCenter-i*this.frame.canvas.clientWidth)},o.prototype._calcTranslations=function(t,e){void 0===e&&(e=!0);for(var i=0;i<t.length;i++){var o=t[i];o.trans=this._convertPointToTranslation(o.point),o.screen=this._convertTranslationToScreen(o.trans);var n=this._convertPointToTranslation(o.bottom);o.dist=this.showPerspective?n.length():-n.z}if(e){var s=function(t,e){return e.dist-t.dist};t.sort(s)}},o.prototype.getNumberOfRows=function(t){return t.length},o.prototype.getNumberOfColumns=function(t){var e=0;for(var i in t[0])t[0].hasOwnProperty(i)&&e++;return e},o.prototype.getDistinctValues=function(t,e){for(var i=[],o=0;o<t.length;o++)i.indexOf(t[o][e])==-1&&i.push(t[o][e]);return i},o.prototype.getColumnRange=function(t,e){for(var i=new m,o=0;o<t.length;o++){var n=t[o][e];i.adjust(n)}return i},o.prototype._checkValueField=function(t){var e=this.style===o.STYLE.BARCOLOR||this.style===o.STYLE.BARSIZE||this.style===o.STYLE.DOTCOLOR||this.style===o.STYLE.DOTSIZE;if(e){if(void 0===this.colValue)throw new Error("Expected data to have  field 'style'  for graph style '"+this.style+"'");if(void 0===t[0][this.colValue])throw new Error("Expected data to have  field '"+this.colValue+"'  for graph style '"+this.style+"'")}},o.prototype._setRangeDefaults=function(t,e,i){void 0!==e&&(t.min=e),void 0!==i&&(t.max=i),t.max<=t.min&&(t.max=t.min+1)},o.prototype._dataInitialize=function(t,e){var i=this;if(this.dataSet&&this.dataSet.off("*",this._onChange),void 0!==t){Array.isArray(t)&&(t=new a(t));var n;if(!(t instanceof a||t instanceof h))throw new Error("Array, DataSet, or DataView expected");if(n=t.get(),0!=n.length){this.dataSet=t,this.dataTable=n,this._onChange=function(){i.setData(i.dataSet)},this.dataSet.on("*",this._onChange),this.colX="x",this.colY="y",this.colZ="z";var s=this.style==o.STYLE.BAR||this.style==o.STYLE.BARCOLOR||this.style==o.STYLE.BARSIZE;if(s){if(void 0!==this.defaultXBarWidth)this.xBarWidth=this.defaultXBarWidth;else{var r=this.getDistinctValues(n,this.colX);this.xBarWidth=r[1]-r[0]||1}if(void 0!==this.defaultYBarWidth)this.yBarWidth=this.defaultYBarWidth;else{var d=this.getDistinctValues(n,this.colY);this.yBarWidth=d[1]-d[0]||1}}var l=5,u=this.getColumnRange(n,this.colX);s&&u.expand(this.xBarWidth/2),this._setRangeDefaults(u,this.defaultXMin,this.defaultXMax),this.xRange=u,this.xStep=void 0!==this.defaultXStep?this.defaultXStep:u.range()/l;var p=this.getColumnRange(n,this.colY);s&&p.expand(this.yBarWidth/2),this._setRangeDefaults(p,this.defaultYMin,this.defaultYMax),this.yRange=p,this.yStep=void 0!==this.defaultYStep?this.defaultYStep:p.range()/l;var f=this.getColumnRange(n,this.colZ);if(this._setRangeDefaults(f,this.defaultZMin,this.defaultZMax),this.zRange=f,this.zStep=void 0!==this.defaultZStep?this.defaultZStep:f.range()/l,n[0].hasOwnProperty("style")){this.colValue="style";var m=this.getColumnRange(n,this.colValue);this._setRangeDefaults(m,this.defaultValueMin,this.defaultValueMax),this.valueRange=m}n[0].hasOwnProperty("filter")&&(this.colFilter="filter",void 0===this.dataFilter&&(this.dataFilter=new c(t,this.colFilter,this),this.dataFilter.setOnLoadCallback(function(){i.redraw()}))),this._setScale()}}},o.prototype._getDataPoints=function(t){var e,i,n,s,r,a,h=[];if(this.style===o.STYLE.GRID||this.style===o.STYLE.SURFACE){var d=[],u=[];for(n=0;n<this.getNumberOfRows(t);n++)e=t[n][this.colX]||0,i=t[n][this.colY]||0,d.indexOf(e)===-1&&d.push(e),u.indexOf(i)===-1&&u.push(i);var c=function(t,e){return t-e};d.sort(c),u.sort(c);var p=[];for(n=0;n<t.length;n++){e=t[n][this.colX]||0,i=t[n][this.colY]||0,s=t[n][this.colZ]||0;var f=d.indexOf(e),m=u.indexOf(i);void 0===p[f]&&(p[f]=[]);var v=new l;v.x=e,v.y=i,v.z=s,v.data=t[n],r={},r.point=v,r.trans=void 0,r.screen=void 0,r.bottom=new l(e,i,this.zRange.min),p[f][m]=r,h.push(r)}for(e=0;e<p.length;e++)for(i=0;i<p[e].length;i++)p[e][i]&&(p[e][i].pointRight=e<p.length-1?p[e+1][i]:void 0,p[e][i].pointTop=i<p[e].length-1?p[e][i+1]:void 0,p[e][i].pointCross=e<p.length-1&&i<p[e].length-1?p[e+1][i+1]:void 0)}else for(this._checkValueField(t),n=0;n<t.length;n++)a=new l,a.x=t[n][this.colX]||0,a.y=t[n][this.colY]||0,a.z=t[n][this.colZ]||0,a.data=t[n],void 0!==this.colValue&&(a.value=t[n][this.colValue]||0),r={},r.point=a,r.bottom=new l(a.x,a.y,this.zRange.min),r.trans=void 0,r.screen=void 0,this.style===o.STYLE.LINE&&n>0&&(h[n-1].pointNext=r),h.push(r);return h},o.prototype.create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);this.frame=document.createElement("div"),this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas);var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t),this.frame.filter=document.createElement("div"),this.frame.filter.style.position="absolute",this.frame.filter.style.bottom="0px",this.frame.filter.style.left="0px",this.frame.filter.style.width="100%",this.frame.appendChild(this.frame.filter);var e=this,i=function(t){e._onMouseDown(t)},o=function(t){e._onTouchStart(t)},n=function(t){e._onWheel(t)},s=function(t){e._onTooltip(t)},r=function(t){e._onClick(t)};d.addEventListener(this.frame.canvas,"keydown",onkeydown),d.addEventListener(this.frame.canvas,"mousedown",i),d.addEventListener(this.frame.canvas,"touchstart",o),d.addEventListener(this.frame.canvas,"mousewheel",n),d.addEventListener(this.frame.canvas,"mousemove",s),d.addEventListener(this.frame.canvas,"click",r),this.containerElement.appendChild(this.frame)},o.prototype._setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this._resizeCanvas()},o.prototype._resizeCanvas=function(){this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight,this.frame.filter.style.width=this.frame.canvas.clientWidth-20+"px"},o.prototype.animationStart=function(){if(!this.frame.filter||!this.frame.filter.slider)throw new Error("No animation available");this.frame.filter.slider.play()},o.prototype.animationStop=function(){this.frame.filter&&this.frame.filter.slider&&this.frame.filter.slider.stop()},o.prototype._resizeCenter=function(){"%"===this.xCenter.charAt(this.xCenter.length-1)?this.currentXCenter=parseFloat(this.xCenter)/100*this.frame.canvas.clientWidth:this.currentXCenter=parseFloat(this.xCenter),"%"===this.yCenter.charAt(this.yCenter.length-1)?this.currentYCenter=parseFloat(this.yCenter)/100*(this.frame.canvas.clientHeight-this.frame.filter.clientHeight):this.currentYCenter=parseFloat(this.yCenter)},o.prototype.getCameraPosition=function(){var t=this.camera.getArmRotation();return t.distance=this.camera.getArmLength(),t},o.prototype._readData=function(t){this._dataInitialize(t,this.style),this.dataFilter?this.dataPoints=this.dataFilter._getDataPoints():this.dataPoints=this._getDataPoints(this.dataTable),this._redrawFilter()},o.prototype.setData=function(t){this._readData(t),this.redraw(),this.animationAutoStart&&this.dataFilter&&this.animationStart()},o.prototype.setOptions=function(t){this.animationStop(),v.setOptions(t,this),this.setPointDrawingMethod(),this._setSize(this.width,this.height),this.dataTable&&this.setData(this.dataTable),this.animationAutoStart&&this.dataFilter&&this.animationStart()},o.prototype.setPointDrawingMethod=function(){var t=void 0;switch(this.style){case o.STYLE.BAR:t=o.prototype._redrawBarGraphPoint;break;case o.STYLE.BARCOLOR:t=o.prototype._redrawBarColorGraphPoint;break;case o.STYLE.BARSIZE:t=o.prototype._redrawBarSizeGraphPoint;break;case o.STYLE.DOT:t=o.prototype._redrawDotGraphPoint;break;case o.STYLE.DOTLINE:t=o.prototype._redrawDotLineGraphPoint;break;case o.STYLE.DOTCOLOR:t=o.prototype._redrawDotColorGraphPoint;break;case o.STYLE.DOTSIZE:t=o.prototype._redrawDotSizeGraphPoint;break;case o.STYLE.SURFACE:t=o.prototype._redrawSurfaceGraphPoint;break;case o.STYLE.GRID:t=o.prototype._redrawGridGraphPoint;break;case o.STYLE.LINE:t=o.prototype._redrawLineGraphPoint;break;default:throw new Error("Can not determine point drawing method for graph style '"+this.style+"'")}this._pointDrawingMethod=t},o.prototype.redraw=function(){if(void 0===this.dataPoints)throw new Error("Graph data not initialized");this._resizeCanvas(),this._resizeCenter(),this._redrawSlider(),this._redrawClear(),this._redrawAxis(),this._redrawDataGraph(),this._redrawInfo(),this._redrawLegend()},o.prototype._getContext=function(){var t=this.frame.canvas,e=t.getContext("2d");return e.lineJoin="round",e.lineCap="round",e},o.prototype._redrawClear=function(){var t=this.frame.canvas,e=t.getContext("2d");e.clearRect(0,0,t.width,t.height)},o.prototype._dotSize=function(){return this.frame.clientWidth*this.dotSizeRatio},o.prototype._getLegendWidth=function(){var t;if(this.style===o.STYLE.DOTSIZE){var e=this._dotSize();t=e/2+2*e}else t=this.style===o.STYLE.BARSIZE?this.xBarWidth:20;return t},o.prototype._redrawLegend=function(){if(this.showLegend===!0&&this.style!==o.STYLE.LINE&&this.style!==o.STYLE.BARSIZE){var t=this.style===o.STYLE.BARSIZE||this.style===o.STYLE.DOTSIZE,e=this.style===o.STYLE.DOTSIZE||this.style===o.STYLE.DOTCOLOR||this.style===o.STYLE.BARCOLOR,i=Math.max(.25*this.frame.clientHeight,100),n=this.margin,s=this._getLegendWidth(),r=this.frame.clientWidth-this.margin,a=r-s,h=n+i,d=this._getContext();if(d.lineWidth=1,d.font="14px arial",t===!1){var l,c=0,p=i;for(l=c;l<p;l++){var m=(l-c)/(p-c),v=240*m,g=this._hsv2rgb(v,1,1);d.strokeStyle=g,d.beginPath(),d.moveTo(a,n+l),d.lineTo(r,n+l),d.stroke()}d.strokeStyle=this.axisColor,d.strokeRect(a,n,s,i)}else{var y;if(this.style===o.STYLE.DOTSIZE){var b=this._dotSize();y=b/2}else this.style===o.STYLE.BARSIZE;d.strokeStyle=this.axisColor,d.fillStyle=this.dataColor.fill,d.beginPath(),d.moveTo(a,n),d.lineTo(r,n),d.lineTo(r-s+y,h),d.lineTo(a,h),d.closePath(),d.fill(),d.stroke()}var _=5,w=e?this.valueRange.min:this.zRange.min,x=e?this.valueRange.max:this.zRange.max,k=new f(w,x,(x-w)/5,!0);k.start(!0);for(var l,O,D;!k.end();)l=h-(k.getCurrent()-w)/(x-w)*i,O=new u(a-_,l),D=new u(a,l),this._line(d,O,D),d.textAlign="right",d.textBaseline="middle",d.fillStyle=this.axisColor,d.fillText(k.getCurrent(),a-2*_,l),k.next();d.textAlign="right",d.textBaseline="top";var S=this.legendLabel;d.fillText(S,r,h+this.margin)}},o.prototype._redrawFilter=function(){if(this.frame.filter.innerHTML="",this.dataFilter){var t={visible:this.showAnimationControls},e=new p(this.frame.filter,t);this.frame.filter.slider=e,this.frame.filter.style.padding="10px",e.setValues(this.dataFilter.values),e.setPlayInterval(this.animationInterval);var i=this,o=function(){var t=e.getIndex();i.dataFilter.selectValue(t),i.dataPoints=i.dataFilter._getDataPoints(),i.redraw()};e.setOnChangeCallback(o)}else this.frame.filter.slider=void 0},o.prototype._redrawSlider=function(){void 0!==this.frame.filter.slider&&this.frame.filter.slider.redraw()},o.prototype._redrawInfo=function(){if(this.dataFilter){var t=this._getContext();t.font="14px arial",t.lineStyle="gray",t.fillStyle="gray",t.textAlign="left",t.textBaseline="top";var e=this.margin,i=this.margin;t.fillText(this.dataFilter.getLabel()+": "+this.dataFilter.getSelectedValue(),e,i)}},o.prototype._line=function(t,e,i,o){void 0!==o&&(t.strokeStyle=o),t.beginPath(),t.moveTo(e.x,e.y),t.lineTo(i.x,i.y),t.stroke()},o.prototype.drawAxisLabelX=function(t,e,i,o,n){void 0===n&&(n=0);var s=this._convert3Dto2D(e);Math.cos(2*o)>0?(t.textAlign="center",t.textBaseline="top",s.y+=n):Math.sin(2*o)<0?(t.textAlign="right",t.textBaseline="middle"):(t.textAlign="left",t.textBaseline="middle"),t.fillStyle=this.axisColor,t.fillText(i,s.x,s.y)},o.prototype.drawAxisLabelY=function(t,e,i,o,n){void 0===n&&(n=0);var s=this._convert3Dto2D(e);Math.cos(2*o)<0?(t.textAlign="center",t.textBaseline="top",s.y+=n):Math.sin(2*o)>0?(t.textAlign="right",t.textBaseline="middle"):(t.textAlign="left",t.textBaseline="middle"),t.fillStyle=this.axisColor,t.fillText(i,s.x,s.y)},o.prototype.drawAxisLabelZ=function(t,e,i,o){void 0===o&&(o=0);var n=this._convert3Dto2D(e);t.textAlign="right",t.textBaseline="middle",t.fillStyle=this.axisColor,t.fillText(i,n.x-o,n.y)},o.prototype._line3d=function(t,e,i,o){var n=this._convert3Dto2D(e),s=this._convert3Dto2D(i);this._line(t,n,s,o)},o.prototype._redrawAxis=function(){var t,e,i,o,n,s,r,a,h,d,c,p=this._getContext();p.font=24/this.camera.getArmLength()+"px arial";var m=.025/this.scale.x,v=.025/this.scale.y,g=5/this.camera.getArmLength(),y=this.camera.getArmRotation().horizontal,b=new u(Math.cos(y),Math.sin(y)),_=this.xRange,w=this.yRange,x=this.zRange;for(p.lineWidth=1,o=void 0===this.defaultXStep,i=new f(_.min,_.max,this.xStep,o),i.start(!0);!i.end();){var k=i.getCurrent();this.showGrid?(t=new l(k,w.min,x.min),e=new l(k,w.max,x.min),this._line3d(p,t,e,this.gridColor)):(t=new l(k,w.min,x.min),e=new l(k,w.min+m,x.min),this._line3d(p,t,e,this.axisColor),t=new l(k,w.max,x.min),e=new l(k,w.max-m,x.min),this._line3d(p,t,e,this.axisColor)),r=b.x>0?w.min:w.max;var O=new l(k,r,x.min),D="  "+this.xValueLabel(k)+"  ";this.drawAxisLabelX(p,O,D,y,g),i.next()}for(p.lineWidth=1,o=void 0===this.defaultYStep,i=new f(w.min,w.max,this.yStep,o),i.start(!0);!i.end();){var S=i.getCurrent();this.showGrid?(t=new l(_.min,S,x.min),e=new l(_.max,S,x.min),this._line3d(p,t,e,this.gridColor)):(t=new l(_.min,S,x.min),e=new l(_.min+v,S,x.min),this._line3d(p,t,e,this.axisColor),t=new l(_.max,S,x.min),e=new l(_.max-v,S,x.min),this._line3d(p,t,e,this.axisColor)),s=b.y>0?_.min:_.max,O=new l(s,S,x.min);var D="  "+this.yValueLabel(S)+"  ";this.drawAxisLabelY(p,O,D,y,g),i.next()}for(p.lineWidth=1,o=void 0===this.defaultZStep,i=new f(x.min,x.max,this.zStep,o),i.start(!0),s=b.x>0?_.min:_.max,r=b.y<0?w.min:w.max;!i.end();){var M=i.getCurrent(),C=new l(s,r,M),T=this._convert3Dto2D(C);e=new u(T.x-g,T.y),this._line(p,T,e,this.axisColor);var D=this.zValueLabel(M)+" ";this.drawAxisLabelZ(p,C,D,5),i.next()}p.lineWidth=1,t=new l(s,r,x.min),e=new l(s,r,x.max),this._line3d(p,t,e,this.axisColor);var E,P;p.lineWidth=1,E=new l(_.min,w.min,x.min),P=new l(_.max,w.min,x.min),this._line3d(p,E,P,this.axisColor),E=new l(_.min,w.max,x.min),P=new l(_.max,w.max,x.min),this._line3d(p,E,P,this.axisColor),p.lineWidth=1,t=new l(_.min,w.min,x.min),e=new l(_.min,w.max,x.min),this._line3d(p,t,e,this.axisColor),t=new l(_.max,w.min,x.min),e=new l(_.max,w.max,x.min),this._line3d(p,t,e,this.axisColor);var I=this.xLabel;I.length>0&&(c=.1/this.scale.y,s=(_.max+3*_.min)/4,r=b.x>0?w.min-c:w.max+c,n=new l(s,r,x.min),this.drawAxisLabelX(p,n,I,y));var N=this.yLabel;N.length>0&&(d=.1/this.scale.x,s=b.y>0?_.min-d:_.max+d,r=(w.max+3*w.min)/4,n=new l(s,r,x.min),this.drawAxisLabelY(p,n,N,y));var z=this.zLabel;z.length>0&&(h=30,s=b.x>0?_.min:_.max,r=b.y<0?w.min:w.max,a=(x.max+3*x.min)/4,n=new l(s,r,a),this.drawAxisLabelZ(p,n,z,h))},o.prototype._hsv2rgb=function(t,e,i){var o,n,s,r,a,h;switch(r=i*e,a=Math.floor(t/60),h=r*(1-Math.abs(t/60%2-1)),a){case 0:o=r,n=h,s=0;break;case 1:o=h,n=r,s=0;break;case 2:o=0,n=r,s=h;break;case 3:o=0,n=h,s=r;break;case 4:o=h,n=0,s=r;break;case 5:o=r,n=0,s=h;break;default:o=0,n=0,s=0}return"RGB("+parseInt(255*o)+","+parseInt(255*n)+","+parseInt(255*s)+")"},o.prototype._getStrokeWidth=function(t){return void 0!==t?this.showPerspective?1/-t.trans.z*this.dataColor.strokeWidth:-(this.eye.z/this.camera.getArmLength())*this.dataColor.strokeWidth:this.dataColor.strokeWidth},o.prototype._redrawBar=function(t,e,i,o,n,s){var r,a,h=this,d=e.point,u=this.zRange.min,c=[{point:new l(d.x-i,d.y-o,d.z)},{point:new l(d.x+i,d.y-o,d.z)},{point:new l(d.x+i,d.y+o,d.z)},{point:new l(d.x-i,d.y+o,d.z)}],p=[{point:new l(d.x-i,d.y-o,u)},{point:new l(d.x+i,d.y-o,u)},{point:new l(d.x+i,d.y+o,u)},{point:new l(d.x-i,d.y+o,u)}];c.forEach(function(t){t.screen=h._convert3Dto2D(t.point)}),p.forEach(function(t){t.screen=h._convert3Dto2D(t.point)});var f=[{corners:c,center:l.avg(p[0].point,p[2].point)},{corners:[c[0],c[1],p[1],p[0]],center:l.avg(p[1].point,p[0].point)},{corners:[c[1],c[2],p[2],p[1]],center:l.avg(p[2].point,p[1].point)},{corners:[c[2],c[3],p[3],p[2]],center:l.avg(p[3].point,p[2].point)},{corners:[c[3],c[0],p[0],p[3]],center:l.avg(p[0].point,p[3].point)}];for(e.surfaces=f,r=0;r<f.length;r++){a=f[r];var m=this._convertPointToTranslation(a.center);a.dist=this.showPerspective?m.length():-m.z}for(f.sort(function(t,e){var i=e.dist-t.dist;return i?i:t.corners===c?1:e.corners===c?-1:0}),t.lineWidth=this._getStrokeWidth(e),t.strokeStyle=s,t.fillStyle=n,r=2;r<f.length;r++)a=f[r],this._polygon(t,a.corners)},o.prototype._polygon=function(t,e,i,o){if(!(e.length<2)){void 0!==i&&(t.fillStyle=i),void 0!==o&&(t.strokeStyle=o),t.beginPath(),t.moveTo(e[0].screen.x,e[0].screen.y);for(var n=1;n<e.length;++n){var s=e[n];t.lineTo(s.screen.x,s.screen.y)}t.closePath(),t.fill(),t.stroke()}},o.prototype._drawCircle=function(t,e,i,o,n){var s=this._calcRadius(e,n);t.lineWidth=this._getStrokeWidth(e),t.strokeStyle=o,t.fillStyle=i,t.beginPath(),t.arc(e.screen.x,e.screen.y,s,0,2*Math.PI,!0),t.fill(),t.stroke()},o.prototype._getColorsRegular=function(t){var e=240*(1-(t.point.z-this.zRange.min)*this.scale.z/this.verticalRatio),i=this._hsv2rgb(e,1,1),o=this._hsv2rgb(e,1,.8);return{fill:i,border:o}},o.prototype._getColorsColor=function(t){var e,i;if("string"==typeof t.point.value)e=t.point.value,i=t.point.value;else{var o=240*(1-(t.point.value-this.valueRange.min)*this.scale.value);e=this._hsv2rgb(o,1,1),i=this._hsv2rgb(o,1,.8)}return{fill:e,border:i}},o.prototype._getColorsSize=function(){return{fill:this.dataColor.fill,border:this.dataColor.stroke}},o.prototype._calcRadius=function(t,e){void 0===e&&(e=this._dotSize());var i;return i=this.showPerspective?e/-t.trans.z:e*-(this.eye.z/this.camera.getArmLength()),i<0&&(i=0),i},o.prototype._redrawBarGraphPoint=function(t,e){var i=this.xBarWidth/2,o=this.yBarWidth/2,n=this._getColorsRegular(e);this._redrawBar(t,e,i,o,n.fill,n.border)},o.prototype._redrawBarColorGraphPoint=function(t,e){var i=this.xBarWidth/2,o=this.yBarWidth/2,n=this._getColorsColor(e);this._redrawBar(t,e,i,o,n.fill,n.border)},o.prototype._redrawBarSizeGraphPoint=function(t,e){var i=(e.point.value-this.valueRange.min)/this.valueRange.range(),o=this.xBarWidth/2*(.8*i+.2),n=this.yBarWidth/2*(.8*i+.2),s=this._getColorsSize();this._redrawBar(t,e,o,n,s.fill,s.border)},o.prototype._redrawDotGraphPoint=function(t,e){var i=this._getColorsRegular(e);this._drawCircle(t,e,i.fill,i.border)},o.prototype._redrawDotLineGraphPoint=function(t,e){var i=this._convert3Dto2D(e.bottom);t.lineWidth=1,this._line(t,i,e.screen,this.gridColor),this._redrawDotGraphPoint(t,e)},o.prototype._redrawDotColorGraphPoint=function(t,e){var i=this._getColorsColor(e);this._drawCircle(t,e,i.fill,i.border)},o.prototype._redrawDotSizeGraphPoint=function(t,e){var i=this._dotSize(),o=(e.point.value-this.valueRange.min)/this.valueRange.range(),n=i/2+2*i*o,s=this._getColorsSize();this._drawCircle(t,e,s.fill,s.border,n)},o.prototype._redrawSurfaceGraphPoint=function(t,e){var i=e.pointRight,o=e.pointTop,n=e.pointCross;if(void 0!==e&&void 0!==i&&void 0!==o&&void 0!==n){var s,r,a=!0;if(this.showGrayBottom||this.showShadow){var h=l.subtract(n.trans,e.trans),d=l.subtract(o.trans,i.trans),u=l.crossProduct(h,d),c=u.length();a=u.z>0}if(a){var p,f=(e.point.z+i.point.z+o.point.z+n.point.z)/4,m=240*(1-(f-this.zRange.min)*this.scale.z/this.verticalRatio),v=1;this.showShadow?(p=Math.min(1+u.x/c/2,1),s=this._hsv2rgb(m,v,p),r=s):(p=1,s=this._hsv2rgb(m,v,p),r=this.axisColor)}else s="gray",r=this.axisColor;t.lineWidth=this._getStrokeWidth(e);var g=[e,i,n,o];this._polygon(t,g,s,r)}},o.prototype._drawGridLine=function(t,e,i){if(void 0!==e&&void 0!==i){var o=(e.point.z+i.point.z)/2,n=240*(1-(o-this.zRange.min)*this.scale.z/this.verticalRatio);t.lineWidth=2*this._getStrokeWidth(e),t.strokeStyle=this._hsv2rgb(n,1,1),this._line(t,e.screen,i.screen)}},o.prototype._redrawGridGraphPoint=function(t,e){this._drawGridLine(t,e,e.pointRight),this._drawGridLine(t,e,e.pointTop)},o.prototype._redrawLineGraphPoint=function(t,e){void 0!==e.pointNext&&(t.lineWidth=this._getStrokeWidth(e),t.strokeStyle=this.dataColor.stroke,this._line(t,e.screen,e.pointNext.screen))},o.prototype._redrawDataGraph=function(){var t,e=this._getContext();if(!(void 0===this.dataPoints||this.dataPoints.length<=0))for(this._calcTranslations(this.dataPoints),t=0;t<this.dataPoints.length;t++){var i=this.dataPoints[t];this._pointDrawingMethod.call(this,e,i)}},o.prototype._storeMousePosition=function(t){this.startMouseX=n(t),this.startMouseY=s(t),this._startCameraOffset=this.camera.getOffset()},o.prototype._onMouseDown=function(t){if(t=t||window.event,this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1===t.which:1===t.button,this.leftButtonDown||this.touchDown){this._storeMousePosition(t),this.startStart=new Date(this.start),this.startEnd=new Date(this.end),this.startArmRotation=this.camera.getArmRotation(),this.frame.style.cursor="move";var e=this;this.onmousemove=function(t){e._onMouseMove(t)},this.onmouseup=function(t){e._onMouseUp(t)},d.addEventListener(document,"mousemove",e.onmousemove),d.addEventListener(document,"mouseup",e.onmouseup),d.preventDefault(t)}},o.prototype._onMouseMove=function(t){this.moving=!0,t=t||window.event;var e=parseFloat(n(t))-this.startMouseX,i=parseFloat(s(t))-this.startMouseY;if(t&&t.ctrlKey===!0){var o=.5*this.frame.clientWidth,r=.5*this.frame.clientHeight,a=(this._startCameraOffset.x||0)-e/o*this.camera.armLength*.8,h=(this._startCameraOffset.y||0)+i/r*this.camera.armLength*.8;this.camera.setOffset(a,h),this._storeMousePosition(t)}else{var l=this.startArmRotation.horizontal+e/200,u=this.startArmRotation.vertical+i/200,c=4,p=Math.sin(c/360*2*Math.PI);Math.abs(Math.sin(l))<p&&(l=Math.round(l/Math.PI)*Math.PI-.001),Math.abs(Math.cos(l))<p&&(l=(Math.round(l/Math.PI-.5)+.5)*Math.PI-.001),Math.abs(Math.sin(u))<p&&(u=Math.round(u/Math.PI)*Math.PI),Math.abs(Math.cos(u))<p&&(u=(Math.round(u/Math.PI-.5)+.5)*Math.PI),this.camera.setArmRotation(l,u)}this.redraw();var f=this.getCameraPosition();this.emit("cameraPositionChange",f),d.preventDefault(t)},o.prototype._onMouseUp=function(t){this.frame.style.cursor="auto",this.leftButtonDown=!1,d.removeEventListener(document,"mousemove",this.onmousemove),d.removeEventListener(document,"mouseup",this.onmouseup),d.preventDefault(t)},o.prototype._onClick=function(t){if(this.onclick_callback){if(this.moving)this.moving=!1;else{var e=this.frame.getBoundingClientRect(),i=n(t)-e.left,o=s(t)-e.top,r=this._dataPointFromXY(i,o);r&&this.onclick_callback(r.point.data)}d.preventDefault(t)}},o.prototype._onTooltip=function(t){var e=300,i=this.frame.getBoundingClientRect(),o=n(t)-i.left,r=s(t)-i.top;if(this.showTooltip){if(this.tooltipTimeout&&clearTimeout(this.tooltipTimeout),this.leftButtonDown)return void this._hideTooltip();if(this.tooltip&&this.tooltip.dataPoint){var a=this._dataPointFromXY(o,r);a!==this.tooltip.dataPoint&&(a?this._showTooltip(a):this._hideTooltip())}else{var h=this;this.tooltipTimeout=setTimeout(function(){h.tooltipTimeout=null;var t=h._dataPointFromXY(o,r);t&&h._showTooltip(t)},e)}}},o.prototype._onTouchStart=function(t){this.touchDown=!0;var e=this;this.ontouchmove=function(t){e._onTouchMove(t)},this.ontouchend=function(t){e._onTouchEnd(t)},d.addEventListener(document,"touchmove",e.ontouchmove),d.addEventListener(document,"touchend",e.ontouchend),this._onMouseDown(t)},o.prototype._onTouchMove=function(t){this._onMouseMove(t)},o.prototype._onTouchEnd=function(t){this.touchDown=!1,d.removeEventListener(document,"touchmove",this.ontouchmove),d.removeEventListener(document,"touchend",this.ontouchend),this._onMouseUp(t)},o.prototype._onWheel=function(t){t||(t=window.event);var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){var i=this.camera.getArmLength(),o=i*(1-e/10);this.camera.setArmLength(o),this.redraw(),this._hideTooltip()}var n=this.getCameraPosition();this.emit("cameraPositionChange",n),d.preventDefault(t)},o.prototype._insideTriangle=function(t,e){function i(t){return t>0?1:t<0?-1:0}var o=e[0],n=e[1],s=e[2],r=i((n.x-o.x)*(t.y-o.y)-(n.y-o.y)*(t.x-o.x)),a=i((s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x)),h=i((o.x-s.x)*(t.y-s.y)-(o.y-s.y)*(t.x-s.x));return!(0!=r&&0!=a&&r!=a||0!=a&&0!=h&&a!=h||0!=r&&0!=h&&r!=h)},o.prototype._dataPointFromXY=function(t,e){var i,n=100,s=null,r=null,a=null,h=new u(t,e);if(this.style===o.STYLE.BAR||this.style===o.STYLE.BARCOLOR||this.style===o.STYLE.BARSIZE)for(i=this.dataPoints.length-1;i>=0;i--){s=this.dataPoints[i];var d=s.surfaces;if(d)for(var l=d.length-1;l>=0;l--){var c=d[l],p=c.corners,f=[p[0].screen,p[1].screen,p[2].screen],m=[p[2].screen,p[3].screen,p[0].screen];if(this._insideTriangle(h,f)||this._insideTriangle(h,m))return s}}else for(i=0;i<this.dataPoints.length;i++){s=this.dataPoints[i];var v=s.screen;if(v){var g=Math.abs(t-v.x),y=Math.abs(e-v.y),b=Math.sqrt(g*g+y*y);(null===a||b<a)&&b<n&&(a=b,r=s)}}return r},o.prototype._showTooltip=function(t){var e,i,o;this.tooltip?(e=this.tooltip.dom.content,i=this.tooltip.dom.line,o=this.tooltip.dom.dot):(e=document.createElement("div"),e.style.position="absolute",e.style.padding="10px",e.style.border="1px solid #4d4d4d",e.style.color="#1a1a1a",e.style.background="rgba(255,255,255,0.7)",e.style.borderRadius="2px",e.style.boxShadow="5px 5px 10px rgba(128,128,128,0.5)",i=document.createElement("div"),i.style.position="absolute",i.style.height="40px",i.style.width="0",i.style.borderLeft="1px solid #4d4d4d",o=document.createElement("div"),o.style.position="absolute",o.style.height="0",o.style.width="0",o.style.border="5px solid #4d4d4d",o.style.borderRadius="5px",this.tooltip={dataPoint:null,dom:{content:e,line:i,dot:o}}),this._hideTooltip(),this.tooltip.dataPoint=t,"function"==typeof this.showTooltip?e.innerHTML=this.showTooltip(t.point):e.innerHTML="<table><tr><td>"+this.xLabel+":</td><td>"+t.point.x+"</td></tr><tr><td>"+this.yLabel+":</td><td>"+t.point.y+"</td></tr><tr><td>"+this.zLabel+":</td><td>"+t.point.z+"</td></tr></table>",e.style.left="0",e.style.top="0",this.frame.appendChild(e),this.frame.appendChild(i),this.frame.appendChild(o);var n=e.offsetWidth,s=e.offsetHeight,r=i.offsetHeight,a=o.offsetWidth,h=o.offsetHeight,d=t.screen.x-n/2;d=Math.min(Math.max(d,10),this.frame.clientWidth-10-n),i.style.left=t.screen.x+"px",i.style.top=t.screen.y-r+"px",e.style.left=d+"px",e.style.top=t.screen.y-r-s+"px",o.style.left=t.screen.x-a/2+"px",o.style.top=t.screen.y-h/2+"px"},o.prototype._hideTooltip=function(){if(this.tooltip){this.tooltip.dataPoint=null;for(var t in this.tooltip.dom)if(this.tooltip.dom.hasOwnProperty(t)){var e=this.tooltip.dom[t];e&&e.parentNode&&e.parentNode.removeChild(e)}}},o.prototype.setCameraPosition=function(t){v.setCameraPosition(t,this),this.redraw()},o.prototype.setSize=function(t,e){this._setSize(t,e),this.redraw()},t.exports=o},function(t,e){function i(t){if(t)return o(t)}function o(t){for(var e in i.prototype)t[e]=i.prototype[e];return t}t.exports=i,i.prototype.on=i.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks[t]=this._callbacks[t]||[]).push(e),this},i.prototype.once=function(t,e){function i(){o.off(t,i),e.apply(this,arguments)}var o=this;return this._callbacks=this._callbacks||{},i.fn=e,this.on(t,i),this},i.prototype.off=i.prototype.removeListener=i.prototype.removeAllListeners=i.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i=this._callbacks[t];if(!i)return this;if(1==arguments.length)return delete this._callbacks[t],this;for(var o,n=0;n<i.length;n++)if(o=i[n],o===e||o.fn===e){i.splice(n,1);break}return this},i.prototype.emit=function(t){this._callbacks=this._callbacks||{};var e=[].slice.call(arguments,1),i=this._callbacks[t];if(i){i=i.slice(0);for(var o=0,n=i.length;o<n;++o)i[o].apply(this,e)}return this},i.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks[t]||[]},i.prototype.hasListeners=function(t){return!!this.listeners(t).length}},function(t,e){function i(t,e,i){this.x=void 0!==t?t:0,this.y=void 0!==e?e:0,this.z=void 0!==i?i:0}i.subtract=function(t,e){var o=new i;return o.x=t.x-e.x,o.y=t.y-e.y,o.z=t.z-e.z,o},i.add=function(t,e){var o=new i;return o.x=t.x+e.x,o.y=t.y+e.y,o.z=t.z+e.z,o},i.avg=function(t,e){return new i((t.x+e.x)/2,(t.y+e.y)/2,(t.z+e.z)/2)},i.crossProduct=function(t,e){var o=new i;return o.x=t.y*e.z-t.z*e.y,o.y=t.z*e.x-t.x*e.z,o.z=t.x*e.y-t.y*e.x,o},i.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},t.exports=i},function(t,e){function i(t,e){
-this.x=void 0!==t?t:0,this.y=void 0!==e?e:0}t.exports=i},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(){this.armLocation=new a,this.armRotation={},this.armRotation.horizontal=0,this.armRotation.vertical=0,this.armLength=1.7,this.cameraOffset=new a,this.offsetMultiplier=.6,this.cameraLocation=new a,this.cameraRotation=new a(.5*Math.PI,0,0),this.calculateCameraOrientation()}var s=i(99),r=o(s),a=i(96);n.prototype.setOffset=function(t,e){var i=Math.abs,o=r.default,n=this.offsetMultiplier,s=this.armLength*n;i(t)>s&&(t=o(t)*s),i(e)>s&&(e=o(e)*s),this.cameraOffset.x=t,this.cameraOffset.y=e,this.calculateCameraOrientation()},n.prototype.getOffset=function(t,e){return this.cameraOffset},n.prototype.setArmLocation=function(t,e,i){this.armLocation.x=t,this.armLocation.y=e,this.armLocation.z=i,this.calculateCameraOrientation()},n.prototype.setArmRotation=function(t,e){void 0!==t&&(this.armRotation.horizontal=t),void 0!==e&&(this.armRotation.vertical=e,this.armRotation.vertical<0&&(this.armRotation.vertical=0),this.armRotation.vertical>.5*Math.PI&&(this.armRotation.vertical=.5*Math.PI)),void 0===t&&void 0===e||this.calculateCameraOrientation()},n.prototype.getArmRotation=function(){var t={};return t.horizontal=this.armRotation.horizontal,t.vertical=this.armRotation.vertical,t},n.prototype.setArmLength=function(t){void 0!==t&&(this.armLength=t,this.armLength<.71&&(this.armLength=.71),this.armLength>5&&(this.armLength=5),this.setOffset(this.cameraOffset.x,this.cameraOffset.y),this.calculateCameraOrientation())},n.prototype.getArmLength=function(){return this.armLength},n.prototype.getCameraLocation=function(){return this.cameraLocation},n.prototype.getCameraRotation=function(){return this.cameraRotation},n.prototype.calculateCameraOrientation=function(){this.cameraLocation.x=this.armLocation.x-this.armLength*Math.sin(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.y=this.armLocation.y-this.armLength*Math.cos(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.z=this.armLocation.z+this.armLength*Math.sin(this.armRotation.vertical),this.cameraRotation.x=Math.PI/2-this.armRotation.vertical,this.cameraRotation.y=0,this.cameraRotation.z=-this.armRotation.horizontal;var t=this.cameraRotation.x,e=(this.cameraRotation.y,this.cameraRotation.z),i=this.cameraOffset.x,o=this.cameraOffset.y,n=Math.sin,s=Math.cos;this.cameraLocation.x=this.cameraLocation.x+i*s(e)+o*-n(e)*s(t),this.cameraLocation.y=this.cameraLocation.y+i*n(e)+o*s(e)*s(t),this.cameraLocation.z=this.cameraLocation.z+o*n(t)},t.exports=n},function(t,e,i){t.exports={default:i(100),__esModule:!0}},function(t,e,i){i(101),t.exports=i(17).Math.sign},function(t,e,i){var o=i(15);o(o.S,"Math",{sign:i(102)})},function(t,e){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,e,i){function o(t,e,i){this.data=t,this.column=e,this.graph=i,this.index=void 0,this.value=void 0,this.values=i.getDistinctValues(t.get(),this.column),this.values.sort(function(t,e){return t>e?1:t<e?-1:0}),this.values.length>0&&this.selectValue(0),this.dataPoints=[],this.loaded=!1,this.onLoadCallback=void 0,i.animationPreload?(this.loaded=!1,this.loadInBackground()):this.loaded=!0}var n=i(93);o.prototype.isLoaded=function(){return this.loaded},o.prototype.getLoadedProgress=function(){for(var t=this.values.length,e=0;this.dataPoints[e];)e++;return Math.round(e/t*100)},o.prototype.getLabel=function(){return this.graph.filterLabel},o.prototype.getColumn=function(){return this.column},o.prototype.getSelectedValue=function(){if(void 0!==this.index)return this.values[this.index]},o.prototype.getValues=function(){return this.values},o.prototype.getValue=function(t){if(t>=this.values.length)throw new Error("Index out of range");return this.values[t]},o.prototype._getDataPoints=function(t){if(void 0===t&&(t=this.index),void 0===t)return[];var e;if(this.dataPoints[t])e=this.dataPoints[t];else{var i={};i.column=this.column,i.value=this.values[t];var o=new n(this.data,{filter:function(t){return t[i.column]==i.value}}).get();e=this.graph._getDataPoints(o),this.dataPoints[t]=e}return e},o.prototype.setOnLoadCallback=function(t){this.onLoadCallback=t},o.prototype.selectValue=function(t){if(t>=this.values.length)throw new Error("Index out of range");this.index=t,this.value=this.values[t]},o.prototype.loadInBackground=function(t){void 0===t&&(t=0);var e=this.graph.frame;if(t<this.values.length){this._getDataPoints(t);void 0===e.progress&&(e.progress=document.createElement("DIV"),e.progress.style.position="absolute",e.progress.style.color="gray",e.appendChild(e.progress));var i=this.getLoadedProgress();e.progress.innerHTML="Loading animation... "+i+"%",e.progress.style.bottom="60px",e.progress.style.left="10px";var o=this;setTimeout(function(){o.loadInBackground(t+1)},10),this.loaded=!1}else this.loaded=!0,void 0!==e.progress&&(e.removeChild(e.progress),e.progress=void 0),this.onLoadCallback&&this.onLoadCallback()},t.exports=o},function(t,e,i){function o(t,e){if(void 0===t)throw new Error("No container element defined");if(this.container=t,this.visible=!e||void 0==e.visible||e.visible,this.visible){this.frame=document.createElement("DIV"),this.frame.style.width="100%",this.frame.style.position="relative",this.container.appendChild(this.frame),this.frame.prev=document.createElement("INPUT"),this.frame.prev.type="BUTTON",this.frame.prev.value="Prev",this.frame.appendChild(this.frame.prev),this.frame.play=document.createElement("INPUT"),this.frame.play.type="BUTTON",this.frame.play.value="Play",this.frame.appendChild(this.frame.play),this.frame.next=document.createElement("INPUT"),this.frame.next.type="BUTTON",this.frame.next.value="Next",this.frame.appendChild(this.frame.next),this.frame.bar=document.createElement("INPUT"),this.frame.bar.type="BUTTON",this.frame.bar.style.position="absolute",this.frame.bar.style.border="1px solid red",this.frame.bar.style.width="100px",this.frame.bar.style.height="6px",this.frame.bar.style.borderRadius="2px",this.frame.bar.style.MozBorderRadius="2px",this.frame.bar.style.border="1px solid #7F7F7F",this.frame.bar.style.backgroundColor="#E5E5E5",this.frame.appendChild(this.frame.bar),this.frame.slide=document.createElement("INPUT"),this.frame.slide.type="BUTTON",this.frame.slide.style.margin="0px",this.frame.slide.value=" ",this.frame.slide.style.position="relative",this.frame.slide.style.left="-100px",this.frame.appendChild(this.frame.slide);var i=this;this.frame.slide.onmousedown=function(t){i._onMouseDown(t)},this.frame.prev.onclick=function(t){i.prev(t)},this.frame.play.onclick=function(t){i.togglePlay(t)},this.frame.next.onclick=function(t){i.next(t)}}this.onChangeCallback=void 0,this.values=[],this.index=void 0,this.playTimeout=void 0,this.playInterval=1e3,this.playLoop=!0}var n=i(1);o.prototype.prev=function(){var t=this.getIndex();t>0&&(t--,this.setIndex(t))},o.prototype.next=function(){var t=this.getIndex();t<this.values.length-1&&(t++,this.setIndex(t))},o.prototype.playNext=function(){var t=new Date,e=this.getIndex();e<this.values.length-1?(e++,this.setIndex(e)):this.playLoop&&(e=0,this.setIndex(e));var i=new Date,o=i-t,n=Math.max(this.playInterval-o,0),s=this;this.playTimeout=setTimeout(function(){s.playNext()},n)},o.prototype.togglePlay=function(){void 0===this.playTimeout?this.play():this.stop()},o.prototype.play=function(){this.playTimeout||(this.playNext(),this.frame&&(this.frame.play.value="Stop"))},o.prototype.stop=function(){clearInterval(this.playTimeout),this.playTimeout=void 0,this.frame&&(this.frame.play.value="Play")},o.prototype.setOnChangeCallback=function(t){this.onChangeCallback=t},o.prototype.setPlayInterval=function(t){this.playInterval=t},o.prototype.getPlayInterval=function(t){return this.playInterval},o.prototype.setPlayLoop=function(t){this.playLoop=t},o.prototype.onChange=function(){void 0!==this.onChangeCallback&&this.onChangeCallback()},o.prototype.redraw=function(){if(this.frame){this.frame.bar.style.top=this.frame.clientHeight/2-this.frame.bar.offsetHeight/2+"px",this.frame.bar.style.width=this.frame.clientWidth-this.frame.prev.clientWidth-this.frame.play.clientWidth-this.frame.next.clientWidth-30+"px";var t=this.indexToLeft(this.index);this.frame.slide.style.left=t+"px"}},o.prototype.setValues=function(t){this.values=t,this.values.length>0?this.setIndex(0):this.index=void 0},o.prototype.setIndex=function(t){if(!(t<this.values.length))throw new Error("Index out of range");this.index=t,this.redraw(),this.onChange()},o.prototype.getIndex=function(){return this.index},o.prototype.get=function(){return this.values[this.index]},o.prototype._onMouseDown=function(t){var e=t.which?1===t.which:1===t.button;if(e){this.startClientX=t.clientX,this.startSlideX=parseFloat(this.frame.slide.style.left),this.frame.style.cursor="move";var i=this;this.onmousemove=function(t){i._onMouseMove(t)},this.onmouseup=function(t){i._onMouseUp(t)},n.addEventListener(document,"mousemove",this.onmousemove),n.addEventListener(document,"mouseup",this.onmouseup),n.preventDefault(t)}},o.prototype.leftToIndex=function(t){var e=parseFloat(this.frame.bar.style.width)-this.frame.slide.clientWidth-10,i=t-3,o=Math.round(i/e*(this.values.length-1));return o<0&&(o=0),o>this.values.length-1&&(o=this.values.length-1),o},o.prototype.indexToLeft=function(t){var e=parseFloat(this.frame.bar.style.width)-this.frame.slide.clientWidth-10,i=t/(this.values.length-1)*e,o=i+3;return o},o.prototype._onMouseMove=function(t){var e=t.clientX-this.startClientX,i=this.startSlideX+e,o=this.leftToIndex(i);this.setIndex(o),n.preventDefault()},o.prototype._onMouseUp=function(t){this.frame.style.cursor="auto",n.removeEventListener(document,"mousemove",this.onmousemove),n.removeEventListener(document,"mouseup",this.onmouseup),n.preventDefault()},t.exports=o},function(t,e){function i(t,e,i,o){this._start=0,this._end=0,this._step=1,this.prettyStep=!0,this.precision=5,this._current=0,this.setRange(t,e,i,o)}i.prototype.isNumeric=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},i.prototype.setRange=function(t,e,i,o){if(!this.isNumeric(t))throw new Error("Parameter 'start' is not numeric; value: "+t);if(!this.isNumeric(e))throw new Error("Parameter 'end' is not numeric; value: "+t);if(!this.isNumeric(i))throw new Error("Parameter 'step' is not numeric; value: "+t);this._start=t?t:0,this._end=e?e:0,this.setStep(i,o)},i.prototype.setStep=function(t,e){void 0===t||t<=0||(void 0!==e&&(this.prettyStep=e),this.prettyStep===!0?this._step=i.calculatePrettyStep(t):this._step=t)},i.calculatePrettyStep=function(t){var e=function(t){return Math.log(t)/Math.LN10},i=Math.pow(10,Math.round(e(t))),o=2*Math.pow(10,Math.round(e(t/2))),n=5*Math.pow(10,Math.round(e(t/5))),s=i;return Math.abs(o-t)<=Math.abs(s-t)&&(s=o),Math.abs(n-t)<=Math.abs(s-t)&&(s=n),s<=0&&(s=1),s},i.prototype.getCurrent=function(){return parseFloat(this._current.toPrecision(this.precision))},i.prototype.getStep=function(){return this._step},i.prototype.start=function(t){void 0===t&&(t=!1),this._current=this._start-this._start%this._step,t&&this.getCurrent()<this._start&&this.next()},i.prototype.next=function(){this._current+=this._step},i.prototype.end=function(){return this._current>this._end},t.exports=i},function(t,e){function i(){this.min=void 0,this.max=void 0}i.prototype.adjust=function(t){void 0!==t&&((void 0===this.min||this.min>t)&&(this.min=t),(void 0===this.max||this.max<t)&&(this.max=t))},i.prototype.combine=function(t){this.add(t.min),this.add(t.max)},i.prototype.expand=function(t){if(void 0!==t){var e=this.min-t,i=this.max+t;if(e>i)throw new Error("Passed expansion value makes range invalid");this.min=e,this.max=i}},i.prototype.range=function(){return this.max-this.min},i.prototype.center=function(){return(this.min+this.max)/2},t.exports=i},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0}function s(t){return void 0===t||""===t||"string"!=typeof t?t:t.charAt(0).toUpperCase()+t.slice(1)}function r(t,e){return void 0===t||""===t?e:t+s(e)}function a(t,e,i,o){var n,s;for(var a in i)n=i[a],s=r(o,n),e[s]=t[n]}function h(t,e,i,o){var n,s;for(var a in i)n=i[a],void 0!==t[n]&&(s=r(o,n),e[s]=t[n])}function d(t,e){if(void 0===t||n(t))throw new Error("No DEFAULTS passed");if(void 0===e)throw new Error("No dst passed");M=t,a(t,e,D),a(t,e,S,"default"),u(t,e),e.margin=10,e.showGrayBottom=!1,e.showTooltip=!1,e.onclick_callback=null,e.eye=new x(0,0,-1)}function l(t,e){if(void 0!==t){if(void 0===e)throw new Error("No dst passed");if(void 0===M||n(M))throw new Error("DEFAULTS not set for module Settings");h(t,e,D),h(t,e,S,"default"),u(t,e)}}function u(t,e){void 0!==t.backgroundColor&&v(t.backgroundColor,e),g(t.dataColor,e),m(t.style,e),c(t.showLegend,e),y(t.cameraPosition,e),void 0!==t.tooltip&&(e.showTooltip=t.tooltip),void 0!=t.onclick&&(e.onclick_callback=t.onclick)}function c(t,e){if(void 0===t){var i=void 0===M.showLegend;if(i){var o=e.style===k.DOTCOLOR||e.style===k.DOTSIZE;e.showLegend=o}}else e.showLegend=t}function p(t){var e=O[t];return void 0===e?-1:e}function f(t){var e=!1;for(var i in k)if(k[i]===t){e=!0;break}return e}function m(t,e){if(void 0!==t){var i;if("string"==typeof t){if(i=p(t),i===-1)throw new Error("Style '"+t+"' is invalid")}else{if(!f(t))throw new Error("Style '"+t+"' is invalid");i=t}e.style=i}}function v(t,e){var i="white",o="gray",n=1;if("string"==typeof t)i=t,o="none",n=0;else{if("object"!==("undefined"==typeof t?"undefined":(0,_.default)(t)))throw new Error("Unsupported type of backgroundColor");void 0!==t.fill&&(i=t.fill),void 0!==t.stroke&&(o=t.stroke),void 0!==t.strokeWidth&&(n=t.strokeWidth)}e.frame.style.backgroundColor=i,e.frame.style.borderColor=o,e.frame.style.borderWidth=n+"px",e.frame.style.borderStyle="solid"}function g(t,e){void 0!==t&&(void 0===e.dataColor&&(e.dataColor={}),"string"==typeof t?(e.dataColor.fill=t,e.dataColor.stroke=t):(t.fill&&(e.dataColor.fill=t.fill),t.stroke&&(e.dataColor.stroke=t.stroke),void 0!==t.strokeWidth&&(e.dataColor.strokeWidth=t.strokeWidth)))}function y(t,e){var i=t;void 0!==i&&(void 0===e.camera&&(e.camera=new w),e.camera.setArmRotation(i.horizontal,i.vertical),e.camera.setArmLength(i.distance))}var b=i(62),_=o(b),w=i(98),x=i(96),k={BAR:0,BARCOLOR:1,BARSIZE:2,DOT:3,DOTLINE:4,DOTCOLOR:5,DOTSIZE:6,GRID:7,LINE:8,SURFACE:9},O={dot:k.DOT,"dot-line":k.DOTLINE,"dot-color":k.DOTCOLOR,"dot-size":k.DOTSIZE,line:k.LINE,grid:k.GRID,surface:k.SURFACE,bar:k.BAR,"bar-color":k.BARCOLOR,"bar-size":k.BARSIZE},D=["width","height","filterLabel","legendLabel","xLabel","yLabel","zLabel","xValueLabel","yValueLabel","zValueLabel","showGrid","showPerspective","showShadow","keepAspectRatio","verticalRatio","dotSizeRatio","showAnimationControls","animationInterval","animationPreload","animationAutoStart","axisColor","gridColor","xCenter","yCenter"],S=["xBarWidth","yBarWidth","valueMin","valueMax","xMin","xMax","xStep","yMin","yMax","yStep","zMin","zMax","zStep"],M=void 0;t.exports.STYLE=k,t.exports.setDefaults=d,t.exports.setOptions=l,t.exports.setCameraPosition=y},function(t,e,i){if("undefined"!=typeof window){var o=i(109),n=window.Hammer||i(110);t.exports=o(n,{preventDefault:"mouse"})}else t.exports=function(){throw Error("hammer.js is only available in a browser, not in node.js.")}},function(t,e,i){var o,n,s;!function(i){n=[],o=i,s="function"==typeof o?o.apply(e,n):o,!(void 0!==s&&(t.exports=s))}(function(){var t=null;return function e(i,o){function n(t){return t.match(/[^ ]+/g)}function s(e){if("hammer.input"!==e.type){if(e.srcEvent._handled||(e.srcEvent._handled={}),e.srcEvent._handled[e.type])return;e.srcEvent._handled[e.type]=!0}var i=!1;e.stopPropagation=function(){i=!0};var o=e.srcEvent.stopPropagation.bind(e.srcEvent);"function"==typeof o&&(e.srcEvent.stopPropagation=function(){o(),e.stopPropagation()}),e.firstTarget=t;for(var n=t;n&&!i;){var s=n.hammer;if(s)for(var r,a=0;a<s.length;a++)if(r=s[a]._handlers[e.type])for(var h=0;h<r.length&&!i;h++)r[h](e);n=n.parentNode}}var r=o||{preventDefault:!1};if(i.Manager){var a=i,h=function(t,i){var o=Object.create(r);return i&&a.assign(o,i),e(new a(t,o),o)};return a.assign(h,a),h.Manager=function(t,i){var o=Object.create(r);return i&&a.assign(o,i),e(new a.Manager(t,o),o)},h}var d=Object.create(i),l=i.element;return l.hammer||(l.hammer=[]),l.hammer.push(d),i.on("hammer.input",function(e){r.preventDefault!==!0&&r.preventDefault!==e.pointerType||e.preventDefault(),e.isFirst&&(t=e.target)}),d._handlers={},d.on=function(t,e){return n(t).forEach(function(t){var o=d._handlers[t];o||(d._handlers[t]=o=[],i.on(t,s)),o.push(e)}),d},d.off=function(t,e){return n(t).forEach(function(t){var o=d._handlers[t];o&&(o=e?o.filter(function(t){return t!==e}):[],o.length>0?d._handlers[t]=o:(i.off(t,s),delete d._handlers[t]))}),d},d.emit=function(e,o){t=o.target,i.emit(e,o)},d.destroy=function(){var t=i.element.hammer,e=t.indexOf(d);e!==-1&&t.splice(e,1),t.length||delete i.element.hammer,d._handlers={},i.destroy()},d}})},function(t,e,i){var o;!function(n,s,r,a){function h(t,e,i){return setTimeout(p(t,i),e)}function d(t,e,i){return!!Array.isArray(t)&&(l(t,i[e],i),!0)}function l(t,e,i){var o;if(t)if(t.forEach)t.forEach(e,i);else if(t.length!==a)for(o=0;o<t.length;)e.call(i,t[o],o,t),o++;else for(o in t)t.hasOwnProperty(o)&&e.call(i,t[o],o,t)}function u(t,e,i){var o="DEPRECATED METHOD: "+e+"\n"+i+" AT \n";return function(){var e=new Error("get-stack-trace"),i=e&&e.stack?e.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",s=n.console&&(n.console.warn||n.console.log);return s&&s.call(n.console,o,i),t.apply(this,arguments)}}function c(t,e,i){var o,n=e.prototype;o=t.prototype=Object.create(n),o.constructor=t,o._super=n,i&&mt(o,i)}function p(t,e){return function(){return t.apply(e,arguments)}}function f(t,e){return typeof t==yt?t.apply(e?e[0]||a:a,e):t}function m(t,e){return t===a?e:t}function v(t,e,i){l(_(e),function(e){t.addEventListener(e,i,!1)})}function g(t,e,i){l(_(e),function(e){t.removeEventListener(e,i,!1)})}function y(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1}function b(t,e){return t.indexOf(e)>-1}function _(t){return t.trim().split(/\s+/g)}function w(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;o<t.length;){if(i&&t[o][i]==e||!i&&t[o]===e)return o;o++}return-1}function x(t){return Array.prototype.slice.call(t,0)}function k(t,e,i){for(var o=[],n=[],s=0;s<t.length;){var r=e?t[s][e]:t[s];w(n,r)<0&&o.push(t[s]),n[s]=r,s++}return i&&(o=e?o.sort(function(t,i){return t[e]>i[e]}):o.sort()),o}function O(t,e){for(var i,o,n=e[0].toUpperCase()+e.slice(1),s=0;s<vt.length;){if(i=vt[s],o=i?i+n:e,o in t)return o;s++}return a}function D(){return Ot++}function S(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||n}function M(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){f(t.options.enable,[t])&&i.handler(e)},this.init()}function C(t){var e,i=t.options.inputClass;return new(e=i?i:Mt?W:Ct?V:St?q:j)(t,T)}function T(t,e,i){var o=i.pointers.length,n=i.changedPointers.length,s=e&zt&&o-n===0,r=e&(Lt|At)&&o-n===0;i.isFirst=!!s,i.isFinal=!!r,s&&(t.session={}),i.eventType=e,E(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function E(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=N(e)),n>1&&!i.firstMultiple?i.firstMultiple=N(e):1===n&&(i.firstMultiple=!1);var s=i.firstInput,r=i.firstMultiple,a=r?r.center:s.center,h=e.center=z(o);e.timeStamp=wt(),e.deltaTime=e.timeStamp-s.timeStamp,e.angle=B(a,h),e.distance=A(a,h),P(i,e),e.offsetDirection=L(e.deltaX,e.deltaY);var d=R(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=_t(d.x)>_t(d.y)?d.x:d.y,e.scale=r?H(r.pointers,o):1,e.rotation=r?F(r.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,I(i,e);var l=t.element;y(e.srcEvent.target,l)&&(l=e.srcEvent.target),e.target=l}function P(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},s=t.prevInput||{};e.eventType!==zt&&s.eventType!==Lt||(n=t.prevDelta={x:s.deltaX||0,y:s.deltaY||0},o=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=n.x+(i.x-o.x),e.deltaY=n.y+(i.y-o.y)}function I(t,e){var i,o,n,s,r=t.lastInterval||e,h=e.timeStamp-r.timeStamp;if(e.eventType!=At&&(h>Nt||r.velocity===a)){var d=e.deltaX-r.deltaX,l=e.deltaY-r.deltaY,u=R(h,d,l);o=u.x,n=u.y,i=_t(u.x)>_t(u.y)?u.x:u.y,s=L(d,l),t.lastInterval=e}else i=r.velocity,o=r.velocityX,n=r.velocityY,s=r.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=s}function N(t){for(var e=[],i=0;i<t.pointers.length;)e[i]={clientX:bt(t.pointers[i].clientX),clientY:bt(t.pointers[i].clientY)},i++;return{timeStamp:wt(),pointers:e,center:z(e),deltaX:t.deltaX,deltaY:t.deltaY}}function z(t){var e=t.length;if(1===e)return{x:bt(t[0].clientX),y:bt(t[0].clientY)};for(var i=0,o=0,n=0;n<e;)i+=t[n].clientX,o+=t[n].clientY,n++;return{x:bt(i/e),y:bt(o/e)}}function R(t,e,i){return{x:e/t||0,y:i/t||0}}function L(t,e){return t===e?Bt:_t(t)>=_t(e)?t<0?Ft:Ht:e<0?jt:Wt}function A(t,e,i){i||(i=Ut);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return Math.sqrt(o*o+n*n)}function B(t,e,i){i||(i=Ut);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return 180*Math.atan2(n,o)/Math.PI}function F(t,e){return B(e[1],e[0],qt)+B(t[1],t[0],qt)}function H(t,e){return A(e[0],e[1],qt)/A(t[0],t[1],qt)}function j(){this.evEl=Zt,this.evWin=Kt,this.pressed=!1,M.apply(this,arguments)}function W(){this.evEl=$t,this.evWin=te,M.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function Y(){this.evTarget=ie,this.evWin=oe,this.started=!1,M.apply(this,arguments)}function G(t,e){var i=x(t.touches),o=x(t.changedTouches);return e&(Lt|At)&&(i=k(i.concat(o),"identifier",!0)),[i,o]}function V(){this.evTarget=se,this.targetIds={},M.apply(this,arguments)}function U(t,e){var i=x(t.touches),o=this.targetIds;if(e&(zt|Rt)&&1===i.length)return o[i[0].identifier]=!0,[i,i];var n,s,r=x(t.changedTouches),a=[],h=this.target;if(s=i.filter(function(t){return y(t.target,h)}),e===zt)for(n=0;n<s.length;)o[s[n].identifier]=!0,n++;for(n=0;n<r.length;)o[r[n].identifier]&&a.push(r[n]),e&(Lt|At)&&delete o[r[n].identifier],n++;return a.length?[k(s.concat(a),"identifier",!0),a]:void 0}function q(){M.apply(this,arguments);var t=p(this.handler,this);this.touch=new V(this.manager,t),this.mouse=new j(this.manager,t),this.primaryTouch=null,this.lastTouches=[]}function X(t,e){t&zt?(this.primaryTouch=e.changedPointers[0].identifier,Z.call(this,e)):t&(Lt|At)&&Z.call(this,e)}function Z(t){var e=t.changedPointers[0];if(e.identifier===this.primaryTouch){var i={x:e.clientX,y:e.clientY};this.lastTouches.push(i);var o=this.lastTouches,n=function(){var t=o.indexOf(i);t>-1&&o.splice(t,1)};setTimeout(n,re)}}function K(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o<this.lastTouches.length;o++){var n=this.lastTouches[o],s=Math.abs(e-n.x),r=Math.abs(i-n.y);if(s<=ae&&r<=ae)return!0}return!1}function Q(t,e){this.manager=t,this.set(e)}function J(t){if(b(t,pe))return pe;var e=b(t,fe),i=b(t,me);return e&&i?pe:e||i?e?fe:me:b(t,ce)?ce:ue}function $(){if(!de)return!1;var t={},e=n.CSS&&n.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(i){t[i]=!e||n.CSS.supports("touch-action",i)}),t}function tt(t){this.options=mt({},this.defaults,t||{}),this.id=D(),this.manager=null,this.options.enable=m(this.options.enable,!0),this.state=ge,this.simultaneous={},this.requireFail=[]}function et(t){return t&xe?"cancel":t&_e?"end":t&be?"move":t&ye?"start":""}function it(t){return t==Wt?"down":t==jt?"up":t==Ft?"left":t==Ht?"right":""}function ot(t,e){var i=e.manager;return i?i.get(t):t}function nt(){tt.apply(this,arguments)}function st(){nt.apply(this,arguments),this.pX=null,this.pY=null}function rt(){nt.apply(this,arguments)}function at(){tt.apply(this,arguments),this._timer=null,this._input=null}function ht(){nt.apply(this,arguments)}function dt(){nt.apply(this,arguments)}function lt(){tt.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ut(t,e){return e=e||{},e.recognizers=m(e.recognizers,ut.defaults.preset),new ct(t,e)}function ct(t,e){this.options=mt({},ut.defaults,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=C(this),this.touchAction=new Q(this,this.options.touchAction),pt(this,!0),l(this.options.recognizers,function(t){var e=this.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])},this)}function pt(t,e){var i=t.element;if(i.style){var o;l(t.options.cssProps,function(n,s){o=O(i.style,s),e?(t.oldCssProps[o]=i.style[o],i.style[o]=n):i.style[o]=t.oldCssProps[o]||""}),e||(t.oldCssProps={})}}function ft(t,e){var i=s.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e,e.target.dispatchEvent(i)}var mt,vt=["","webkit","Moz","MS","ms","o"],gt=s.createElement("div"),yt="function",bt=Math.round,_t=Math.abs,wt=Date.now;mt="function"!=typeof Object.assign?function(t){if(t===a||null===t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),i=1;i<arguments.length;i++){var o=arguments[i];if(o!==a&&null!==o)for(var n in o)o.hasOwnProperty(n)&&(e[n]=o[n])}return e}:Object.assign;var xt=u(function(t,e,i){for(var o=Object.keys(e),n=0;n<o.length;)(!i||i&&t[o[n]]===a)&&(t[o[n]]=e[o[n]]),n++;return t},"extend","Use `assign`."),kt=u(function(t,e){return xt(t,e,!0)},"merge","Use `assign`."),Ot=1,Dt=/mobile|tablet|ip(ad|hone|od)|android/i,St="ontouchstart"in n,Mt=O(n,"PointerEvent")!==a,Ct=St&&Dt.test(navigator.userAgent),Tt="touch",Et="pen",Pt="mouse",It="kinect",Nt=25,zt=1,Rt=2,Lt=4,At=8,Bt=1,Ft=2,Ht=4,jt=8,Wt=16,Yt=Ft|Ht,Gt=jt|Wt,Vt=Yt|Gt,Ut=["x","y"],qt=["clientX","clientY"];M.prototype={handler:function(){},init:function(){this.evEl&&v(this.element,this.evEl,this.domHandler),this.evTarget&&v(this.target,this.evTarget,this.domHandler),this.evWin&&v(S(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&g(this.element,this.evEl,this.domHandler),this.evTarget&&g(this.target,this.evTarget,this.domHandler),this.evWin&&g(S(this.element),this.evWin,this.domHandler)}};var Xt={mousedown:zt,mousemove:Rt,mouseup:Lt},Zt="mousedown",Kt="mousemove mouseup";c(j,M,{handler:function(t){var e=Xt[t.type];e&zt&&0===t.button&&(this.pressed=!0),e&Rt&&1!==t.which&&(e=Lt),this.pressed&&(e&Lt&&(this.pressed=!1),this.callback(this.manager,e,{pointers:[t],changedPointers:[t],pointerType:Pt,srcEvent:t}))}});var Qt={pointerdown:zt,pointermove:Rt,pointerup:Lt,pointercancel:At,pointerout:At},Jt={2:Tt,3:Et,4:Pt,5:It},$t="pointerdown",te="pointermove pointerup pointercancel";n.MSPointerEvent&&!n.PointerEvent&&($t="MSPointerDown",te="MSPointerMove MSPointerUp MSPointerCancel"),c(W,M,{handler:function(t){var e=this.store,i=!1,o=t.type.toLowerCase().replace("ms",""),n=Qt[o],s=Jt[t.pointerType]||t.pointerType,r=s==Tt,a=w(e,t.pointerId,"pointerId");n&zt&&(0===t.button||r)?a<0&&(e.push(t),a=e.length-1):n&(Lt|At)&&(i=!0),a<0||(e[a]=t,this.callback(this.manager,n,{pointers:e,changedPointers:[t],pointerType:s,srcEvent:t}),i&&e.splice(a,1))}});var ee={touchstart:zt,touchmove:Rt,touchend:Lt,touchcancel:At},ie="touchstart",oe="touchstart touchmove touchend touchcancel";c(Y,M,{handler:function(t){var e=ee[t.type];if(e===zt&&(this.started=!0),this.started){var i=G.call(this,t,e);e&(Lt|At)&&i[0].length-i[1].length===0&&(this.started=!1),this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Tt,srcEvent:t})}}});var ne={touchstart:zt,touchmove:Rt,touchend:Lt,touchcancel:At},se="touchstart touchmove touchend touchcancel";c(V,M,{handler:function(t){var e=ne[t.type],i=U.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Tt,srcEvent:t})}});var re=2500,ae=25;c(q,M,{handler:function(t,e,i){var o=i.pointerType==Tt,n=i.pointerType==Pt;if(!(n&&i.sourceCapabilities&&i.sourceCapabilities.firesTouchEvents)){if(o)X.call(this,e,i);else if(n&&K.call(this,i))return;this.callback(t,e,i)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var he=O(gt.style,"touchAction"),de=he!==a,le="compute",ue="auto",ce="manipulation",pe="none",fe="pan-x",me="pan-y",ve=$();Q.prototype={set:function(t){t==le&&(t=this.compute()),de&&this.manager.element.style&&ve[t]&&(this.manager.element.style[he]=t),this.actions=t.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var t=[];return l(this.manager.recognizers,function(e){f(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))}),J(t.join(" "))},preventDefaults:function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)return void e.preventDefault();var o=this.actions,n=b(o,pe)&&!ve[pe],s=b(o,me)&&!ve[me],r=b(o,fe)&&!ve[fe];if(n){var a=1===t.pointers.length,h=t.distance<2,d=t.deltaTime<250;if(a&&h&&d)return}return r&&s?void 0:n||s&&i&Yt||r&&i&Gt?this.preventSrc(e):void 0},preventSrc:function(t){this.manager.session.prevented=!0,t.preventDefault()}};var ge=1,ye=2,be=4,_e=8,we=_e,xe=16,ke=32;tt.prototype={defaults:{},set:function(t){return mt(this.options,t),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(t){if(d(t,"recognizeWith",this))return this;var e=this.simultaneous;return t=ot(t,this),e[t.id]||(e[t.id]=t,t.recognizeWith(this)),this},dropRecognizeWith:function(t){return d(t,"dropRecognizeWith",this)?this:(t=ot(t,this),delete this.simultaneous[t.id],this)},requireFailure:function(t){if(d(t,"requireFailure",this))return this;var e=this.requireFail;return t=ot(t,this),w(e,t)===-1&&(e.push(t),t.requireFailure(this)),this},dropRequireFailure:function(t){if(d(t,"dropRequireFailure",this))return this;t=ot(t,this);var e=w(this.requireFail,t);return e>-1&&this.requireFail.splice(e,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(t){return!!this.simultaneous[t.id]},emit:function(t){function e(e){i.manager.emit(e,t)}var i=this,o=this.state;o<_e&&e(i.options.event+et(o)),e(i.options.event),t.additionalEvent&&e(t.additionalEvent),o>=_e&&e(i.options.event+et(o))},tryEmit:function(t){return this.canEmit()?this.emit(t):void(this.state=ke)},canEmit:function(){for(var t=0;t<this.requireFail.length;){if(!(this.requireFail[t].state&(ke|ge)))return!1;t++}return!0},recognize:function(t){var e=mt({},t);return f(this.options.enable,[this,e])?(this.state&(we|xe|ke)&&(this.state=ge),this.state=this.process(e),void(this.state&(ye|be|_e|xe)&&this.tryEmit(e))):(this.reset(),void(this.state=ke))},process:function(t){},getTouchAction:function(){},reset:function(){}},c(nt,tt,{defaults:{pointers:1},attrTest:function(t){var e=this.options.pointers;return 0===e||t.pointers.length===e},process:function(t){var e=this.state,i=t.eventType,o=e&(ye|be),n=this.attrTest(t);return o&&(i&At||!n)?e|xe:o||n?i&Lt?e|_e:e&ye?e|be:ye:ke}}),c(st,nt,{defaults:{event:"pan",threshold:10,pointers:1,direction:Vt},getTouchAction:function(){var t=this.options.direction,e=[];return t&Yt&&e.push(me),t&Gt&&e.push(fe),e},directionTest:function(t){var e=this.options,i=!0,o=t.distance,n=t.direction,s=t.deltaX,r=t.deltaY;return n&e.direction||(e.direction&Yt?(n=0===s?Bt:s<0?Ft:Ht,i=s!=this.pX,o=Math.abs(t.deltaX)):(n=0===r?Bt:r<0?jt:Wt,i=r!=this.pY,o=Math.abs(t.deltaY))),t.direction=n,i&&o>e.threshold&&n&e.direction},attrTest:function(t){return nt.prototype.attrTest.call(this,t)&&(this.state&ye||!(this.state&ye)&&this.directionTest(t))},emit:function(t){this.pX=t.deltaX,this.pY=t.deltaY;var e=it(t.direction);e&&(t.additionalEvent=this.options.event+e),this._super.emit.call(this,t)}}),c(rt,nt,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[pe];
-},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.scale-1)>this.options.threshold||this.state&ye)},emit:function(t){if(1!==t.scale){var e=t.scale<1?"in":"out";t.additionalEvent=this.options.event+e}this._super.emit.call(this,t)}}),c(at,tt,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[ue]},process:function(t){var e=this.options,i=t.pointers.length===e.pointers,o=t.distance<e.threshold,n=t.deltaTime>e.time;if(this._input=t,!o||!i||t.eventType&(Lt|At)&&!n)this.reset();else if(t.eventType&zt)this.reset(),this._timer=h(function(){this.state=we,this.tryEmit()},e.time,this);else if(t.eventType&Lt)return we;return ke},reset:function(){clearTimeout(this._timer)},emit:function(t){this.state===we&&(t&&t.eventType&Lt?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=wt(),this.manager.emit(this.options.event,this._input)))}}),c(ht,nt,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[pe]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.rotation)>this.options.threshold||this.state&ye)}}),c(dt,nt,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Yt|Gt,pointers:1},getTouchAction:function(){return st.prototype.getTouchAction.call(this)},attrTest:function(t){var e,i=this.options.direction;return i&(Yt|Gt)?e=t.overallVelocity:i&Yt?e=t.overallVelocityX:i&Gt&&(e=t.overallVelocityY),this._super.attrTest.call(this,t)&&i&t.offsetDirection&&t.distance>this.options.threshold&&t.maxPointers==this.options.pointers&&_t(e)>this.options.velocity&&t.eventType&Lt},emit:function(t){var e=it(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)}}),c(lt,tt,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ce]},process:function(t){var e=this.options,i=t.pointers.length===e.pointers,o=t.distance<e.threshold,n=t.deltaTime<e.time;if(this.reset(),t.eventType&zt&&0===this.count)return this.failTimeout();if(o&&n&&i){if(t.eventType!=Lt)return this.failTimeout();var s=!this.pTime||t.timeStamp-this.pTime<e.interval,r=!this.pCenter||A(this.pCenter,t.center)<e.posThreshold;this.pTime=t.timeStamp,this.pCenter=t.center,r&&s?this.count+=1:this.count=1,this._input=t;var a=this.count%e.taps;if(0===a)return this.hasRequireFailures()?(this._timer=h(function(){this.state=we,this.tryEmit()},e.interval,this),ye):we}return ke},failTimeout:function(){return this._timer=h(function(){this.state=ke},this.options.interval,this),ke},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==we&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),ut.VERSION="2.0.7",ut.defaults={domEvents:!1,touchAction:le,enable:!0,inputTarget:null,inputClass:null,preset:[[ht,{enable:!1}],[rt,{enable:!1},["rotate"]],[dt,{direction:Yt}],[st,{direction:Yt},["swipe"]],[lt],[lt,{event:"doubletap",taps:2},["tap"]],[at]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var Oe=1,De=2;ct.prototype={set:function(t){return mt(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},stop:function(t){this.session.stopped=t?De:Oe},recognize:function(t){var e=this.session;if(!e.stopped){this.touchAction.preventDefaults(t);var i,o=this.recognizers,n=e.curRecognizer;(!n||n&&n.state&we)&&(n=e.curRecognizer=null);for(var s=0;s<o.length;)i=o[s],e.stopped===De||n&&i!=n&&!i.canRecognizeWith(n)?i.reset():i.recognize(t),!n&&i.state&(ye|be|_e)&&(n=e.curRecognizer=i),s++}},get:function(t){if(t instanceof tt)return t;for(var e=this.recognizers,i=0;i<e.length;i++)if(e[i].options.event==t)return e[i];return null},add:function(t){if(d(t,"add",this))return this;var e=this.get(t.options.event);return e&&this.remove(e),this.recognizers.push(t),t.manager=this,this.touchAction.update(),t},remove:function(t){if(d(t,"remove",this))return this;if(t=this.get(t)){var e=this.recognizers,i=w(e,t);i!==-1&&(e.splice(i,1),this.touchAction.update())}return this},on:function(t,e){if(t!==a&&e!==a){var i=this.handlers;return l(_(t),function(t){i[t]=i[t]||[],i[t].push(e)}),this}},off:function(t,e){if(t!==a){var i=this.handlers;return l(_(t),function(t){e?i[t]&&i[t].splice(w(i[t],e),1):delete i[t]}),this}},emit:function(t,e){this.options.domEvents&&ft(t,e);var i=this.handlers[t]&&this.handlers[t].slice();if(i&&i.length){e.type=t,e.preventDefault=function(){e.srcEvent.preventDefault()};for(var o=0;o<i.length;)i[o](e),o++}},destroy:function(){this.element&&pt(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},mt(ut,{INPUT_START:zt,INPUT_MOVE:Rt,INPUT_END:Lt,INPUT_CANCEL:At,STATE_POSSIBLE:ge,STATE_BEGAN:ye,STATE_CHANGED:be,STATE_ENDED:_e,STATE_RECOGNIZED:we,STATE_CANCELLED:xe,STATE_FAILED:ke,DIRECTION_NONE:Bt,DIRECTION_LEFT:Ft,DIRECTION_RIGHT:Ht,DIRECTION_UP:jt,DIRECTION_DOWN:Wt,DIRECTION_HORIZONTAL:Yt,DIRECTION_VERTICAL:Gt,DIRECTION_ALL:Vt,Manager:ct,Input:M,TouchAction:Q,TouchInput:V,MouseInput:j,PointerEventInput:W,TouchMouseInput:q,SingleTouchInput:Y,Recognizer:tt,AttrRecognizer:nt,Tap:lt,Pan:st,Swipe:dt,Pinch:rt,Rotate:ht,Press:at,on:v,off:g,each:l,merge:kt,extend:xt,assign:mt,inherit:c,bindFn:p,prefixed:O});var Se="undefined"!=typeof n?n:"undefined"!=typeof self?self:{};Se.Hammer=ut,o=function(){return ut}.call(e,i,e,t),!(o!==a&&(t.exports=o))}(window,document,"Hammer")},function(t,e,i){var o,n,s;!function(i,r){n=[],o=r,s="function"==typeof o?o.apply(e,n):o,!(void 0!==s&&(t.exports=s))}(this,function(){function t(t){var e,i=t&&t.preventDefault||!1,o=t&&t.container||window,n={},s={keydown:{},keyup:{}},r={};for(e=97;e<=122;e++)r[String.fromCharCode(e)]={code:65+(e-97),shift:!1};for(e=65;e<=90;e++)r[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)r[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)r["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)r["num"+e]={code:96+e,shift:!1};r["num*"]={code:106,shift:!1},r["num+"]={code:107,shift:!1},r["num-"]={code:109,shift:!1},r["num/"]={code:111,shift:!1},r["num."]={code:110,shift:!1},r.left={code:37,shift:!1},r.up={code:38,shift:!1},r.right={code:39,shift:!1},r.down={code:40,shift:!1},r.space={code:32,shift:!1},r.enter={code:13,shift:!1},r.shift={code:16,shift:void 0},r.esc={code:27,shift:!1},r.backspace={code:8,shift:!1},r.tab={code:9,shift:!1},r.ctrl={code:17,shift:!1},r.alt={code:18,shift:!1},r.delete={code:46,shift:!1},r.pageup={code:33,shift:!1},r.pagedown={code:34,shift:!1},r["="]={code:187,shift:!1},r["-"]={code:189,shift:!1},r["]"]={code:221,shift:!1},r["["]={code:219,shift:!1};var a=function(t){d(t,"keydown")},h=function(t){d(t,"keyup")},d=function(t,e){if(void 0!==s[e][t.keyCode]){for(var o=s[e][t.keyCode],n=0;n<o.length;n++)void 0===o[n].shift?o[n].fn(t):1==o[n].shift&&1==t.shiftKey?o[n].fn(t):0==o[n].shift&&0==t.shiftKey&&o[n].fn(t);1==i&&t.preventDefault()}};return n.bind=function(t,e,i){if(void 0===i&&(i="keydown"),void 0===r[t])throw new Error("unsupported key: "+t);void 0===s[i][r[t].code]&&(s[i][r[t].code]=[]),s[i][r[t].code].push({fn:e,shift:r[t].shift})},n.bindAll=function(t,e){void 0===e&&(e="keydown");for(var i in r)r.hasOwnProperty(i)&&n.bind(i,t,e)},n.getKey=function(t){for(var e in r)if(r.hasOwnProperty(e)){if(1==t.shiftKey&&1==r[e].shift&&t.keyCode==r[e].code)return e;if(0==t.shiftKey&&0==r[e].shift&&t.keyCode==r[e].code)return e;if(t.keyCode==r[e].code&&"shift"==e)return e}return"unknown key, currently not supported"},n.unbind=function(t,e,i){if(void 0===i&&(i="keydown"),void 0===r[t])throw new Error("unsupported key: "+t);if(void 0!==e){var o=[],n=s[i][r[t].code];if(void 0!==n)for(var a=0;a<n.length;a++)n[a].fn==e&&n[a].shift==r[t].shift||o.push(s[i][r[t].code][a]);s[i][r[t].code]=o}else s[i][r[t].code]=[]},n.reset=function(){s={keydown:{},keyup:{}}},n.destroy=function(){s={keydown:{},keyup:{}},o.removeEventListener("keydown",a,!0),o.removeEventListener("keyup",h,!0)},o.addEventListener("keydown",a,!0),o.addEventListener("keyup",h,!0),n}return t})},function(t,e,i){e.util=i(1),e.DOMutil=i(90),e.DataSet=i(91),e.DataView=i(93),e.Queue=i(92),e.Timeline=i(113),e.Graph2d=i(144),e.timeline={Core:i(126),DateUtil:i(125),Range:i(123),stack:i(131),TimeStep:i(129),components:{items:{Item:i(133),BackgroundItem:i(137),BoxItem:i(135),PointItem:i(136),RangeItem:i(132)},BackgroundGroup:i(134),Component:i(124),CurrentTime:i(142),CustomTime:i(140),DataAxis:i(146),DataScale:i(147),GraphGroup:i(148),Group:i(130),ItemSet:i(127),Legend:i(152),LineGraph:i(145),TimeAxis:i(138)}},e.moment=i(84),e.Hammer=i(108),e.keycharm=i(111)},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i,o){if(!(this instanceof n))throw new SyntaxError("Constructor must be called with the new operator");if(!(Array.isArray(i)||i instanceof u||i instanceof c)&&i instanceof Object){var s=o;o=i,i=s}o&&o.throttleRedraw&&console.warn('Timeline option "throttleRedraw" is DEPRICATED and no longer supported. It will be removed in the next MAJOR release.');var r=this;if(this.defaultOptions={start:null,end:null,autoResize:!0,orientation:{axis:"bottom",item:"bottom"},moment:d,width:null,height:null,maxHeight:null,minHeight:null},this.options=l.deepExtend({},this.defaultOptions),this._create(t),!o||o&&"undefined"==typeof o.rtl){for(var a,h=this.dom.root;!a&&h;)a=window.getComputedStyle(h,null).direction,h=h.parentElement;this.options.rtl=a&&"rtl"==a.toLowerCase()}else this.options.rtl=o.rtl;this.options.rollingMode=o&&o.rollingMode,this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{getScale:function(){return r.timeAxis.step.scale},getStep:function(){return r.timeAxis.step.step},toScreen:r._toScreen.bind(r),toGlobalScreen:r._toGlobalScreen.bind(r),toTime:r._toTime.bind(r),toGlobalTime:r._toGlobalTime.bind(r)}},this.range=new p(this.body,this.options),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new m(this.body,this.options),this.timeAxis2=null,this.components.push(this.timeAxis),this.currentTime=new v(this.body,this.options),this.components.push(this.currentTime),this.itemSet=new y(this.body,this.options),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,this.dom.root.onclick=function(t){r.emit("click",r.getEventProperties(t))},this.dom.root.ondblclick=function(t){r.emit("doubleClick",r.getEventProperties(t))},this.dom.root.oncontextmenu=function(t){r.emit("contextmenu",r.getEventProperties(t))},this.dom.root.onmouseover=function(t){r.emit("mouseOver",r.getEventProperties(t))},this.dom.root.onmousemove=function(t){r.emit("mouseMove",r.getEventProperties(t))},this.fitDone=!1,this.on("changed",function(){if(null!=this.itemsData&&!this.options.rollingMode&&!r.fitDone)if(r.fitDone=!0,void 0!=r.options.start||void 0!=r.options.end){if(void 0==r.options.start||void 0==r.options.end)var t=r.getItemRange();var e=void 0!=r.options.start?r.options.start:t.min,i=void 0!=r.options.end?r.options.end:t.max;r.setWindow(e,i,{animation:!1})}else r.fit({animation:!1})}),o&&this.setOptions(o),i&&this.setGroups(i),e&&this.setItems(e),this._redraw()}var s=i(114),r=o(s),a=i(122),h=o(a),d=(i(95),i(108),i(84)),l=i(1),u=i(91),c=i(93),p=i(123),f=i(126),m=i(138),v=i(142),g=i(140),y=i(127),b=i(122).printStyle,_=i(143).allOptions,w=i(143).configureOptions;n.prototype=new f,n.prototype._createConfigurator=function(){return new r.default(this,this.dom.container,w)},n.prototype.redraw=function(){this.itemSet&&this.itemSet.markDirty({refreshItems:!0}),this._redraw()},n.prototype.setOptions=function(t){var e=h.default.validate(t,_);if(e===!0&&console.log("%cErrors have been found in the supplied options object.",b),f.prototype.setOptions.call(this,t),"type"in t&&t.type!==this.options.type){this.options.type=t.type;var i=this.itemsData;if(i){var o=this.getSelection();this.setItems(null),this.setItems(i),this.setSelection(o)}}},n.prototype.setItems=function(t){var e;e=t?t instanceof u||t instanceof c?t:new u(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e)},n.prototype.setGroups=function(t){var e;if(t){var i=function(t){return t.visible!==!1};e=t instanceof u||t instanceof c?new c(t,{filter:i}):new u(t.filter(i))}else e=null;this.groupsData=e,this.itemSet.setGroups(e)},n.prototype.setData=function(t){t&&t.groups&&this.setGroups(t.groups),t&&t.items&&this.setItems(t.items)},n.prototype.setSelection=function(t,e){this.itemSet&&this.itemSet.setSelection(t),e&&e.focus&&this.focus(t,e)},n.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},n.prototype.focus=function(t,e){if(this.itemsData&&void 0!=t){var i=Array.isArray(t)?t:[t],o=this.itemsData.getDataSet().get(i,{type:{start:"Date",end:"Date"}}),n=null,s=null;if(o.forEach(function(t){var e=t.start.valueOf(),i="end"in t?t.end.valueOf():t.start.valueOf();(null===n||e<n)&&(n=e),(null===s||i>s)&&(s=i)}),null!==n&&null!==s){var r=(n+s)/2,a=Math.max(this.range.end-this.range.start,1.1*(s-n)),h=!e||void 0===e.animation||e.animation;this.range.setRange(r-a/2,r+a/2,h)}}},n.prototype.fit=function(t){var e,i=!t||void 0===t.animation||t.animation,o=this.itemsData&&this.itemsData.getDataSet();1===o.length&&void 0===o.get()[0].end?(e=this.getDataRange(),this.moveTo(e.min.valueOf(),{animation:i})):(e=this.getItemRange(),this.range.setRange(e.min,e.max,i))},n.prototype.getItemRange=function(){var t=this,e=this.getDataRange(),i=null!==e.min?e.min.valueOf():null,o=null!==e.max?e.max.valueOf():null,n=null,s=null;if(null!=i&&null!=o){var r,a,h,d,u;!function(){var e=function(t){return l.convert(t.data.start,"Date").valueOf()},c=function(t){var e=void 0!=t.data.end?t.data.end:t.data.start;return l.convert(e,"Date").valueOf()};r=o-i,r<=0&&(r=10),a=r/t.props.center.width,l.forEach(t.itemSet.items,function(t){t.groupShowing&&(t.show(),t.repositionX());var r=e(t),h=c(t);if(this.options.rtl)var d=r-(t.getWidthRight()+10)*a,l=h+(t.getWidthLeft()+10)*a;else var d=r-(t.getWidthLeft()+10)*a,l=h+(t.getWidthRight()+10)*a;d<i&&(i=d,n=t),l>o&&(o=l,s=t)}.bind(t)),n&&s&&(h=n.getWidthLeft()+10,d=s.getWidthRight()+10,u=t.props.center.width-h-d,u>0&&(t.options.rtl?(i=e(n)-d*r/u,o=c(s)+h*r/u):(i=e(n)-h*r/u,o=c(s)+d*r/u)))}()}return{min:null!=i?new Date(i):null,max:null!=o?new Date(o):null}},n.prototype.getDataRange=function(){var t=null,e=null,i=this.itemsData&&this.itemsData.getDataSet();return i&&i.forEach(function(i){var o=l.convert(i.start,"Date").valueOf(),n=l.convert(void 0!=i.end?i.end:i.start,"Date").valueOf();(null===t||o<t)&&(t=o),(null===e||n>e)&&(e=n)}),{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},n.prototype.getEventProperties=function(t){var e=t.center?t.center.x:t.clientX,i=t.center?t.center.y:t.clientY;if(this.options.rtl)var o=l.getAbsoluteRight(this.dom.centerContainer)-e;else var o=e-l.getAbsoluteLeft(this.dom.centerContainer);var n=i-l.getAbsoluteTop(this.dom.centerContainer),s=this.itemSet.itemFromTarget(t),r=this.itemSet.groupFromTarget(t),a=g.customTimeFromTarget(t),h=this.itemSet.options.snap||null,d=this.body.util.getScale(),u=this.body.util.getStep(),c=this._toTime(o),p=h?h(c,d,u):c,f=l.getTarget(t),m=null;return null!=s?m="item":null!=a?m="custom-time":l.hasParent(f,this.timeAxis.dom.foreground)?m="axis":this.timeAxis2&&l.hasParent(f,this.timeAxis2.dom.foreground)?m="axis":l.hasParent(f,this.itemSet.dom.labelSet)?m="group-label":l.hasParent(f,this.currentTime.bar)?m="current-time":l.hasParent(f,this.dom.center)&&(m="background"),{event:t,item:s?s.id:null,group:r?r.groupId:null,what:m,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:o,y:n,time:c,snappedTime:p}},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(82),s=o(n),r=i(62),a=o(r),h=i(115),d=o(h),l=i(116),u=o(l),c=i(120),p=o(c),f=i(1),m=function(){function t(e,i,o){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1;(0,d.default)(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},f.extend(this.options,this.defaultOptions),this.configureOptions=o,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new p.default(n),this.wrapper=void 0}return(0,u.default)(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;"string"==typeof t?this.options.filter=t:t instanceof Array?this.options.filter=t.join():"object"===("undefined"==typeof t?"undefined":(0,a.default)(t))?(void 0!==t.container&&(this.options.container=t.container),void 0!==t.filter&&(this.options.filter=t.filter),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)):"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0),this.options.filter===!1&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,this.options.enabled===!0&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){var t=this;this._clean(),this.changedOptions=[];var e=this.options.filter,i=0,o=!1;for(var n in this.configureOptions)this.configureOptions.hasOwnProperty(n)&&(this.allowCreation=!1,o=!1,"function"==typeof e?(o=e(n,[]),o=o||this._handleObject(this.configureOptions[n],[n],!0)):e!==!0&&e.indexOf(n)===-1||(o=!0),o!==!1&&(this.allowCreation=!0,i>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),i++);this.options.showButton===!0&&!function(){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerHTML="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},t.optionsContainer=document.createElement("div"),t.optionsContainer.className="vis-configuration vis-config-option-container",t.domElements.push(t.optionsContainer),t.domElements.push(e)}(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t<this.domElements.length;t++)this.wrapper.appendChild(this.domElements[t]);this._showPopupIfNeeded()}},{key:"_clean",value:function(){for(var t=0;t<this.domElements.length;t++)this.wrapper.removeChild(this.domElements[t]);void 0!==this.wrapper&&(this.container.removeChild(this.wrapper),this.wrapper=void 0),this.domElements=[],this._removePopup()}},{key:"_getValue",value:function(t){for(var e=this.moduleOptions,i=0;i<t.length;i++){if(void 0===e[t[i]]){e=void 0;break}e=e[t[i]]}return e}},{key:"_makeItem",value:function(t){var e=arguments,i=this;if(this.allowCreation===!0){var o,n,s,r=function(){var r=document.createElement("div");for(r.className="vis-configuration vis-config-item vis-config-s"+t.length,o=e.length,n=Array(o>1?o-1:0),s=1;s<o;s++)n[s-1]=e[s];return n.forEach(function(t){r.appendChild(t)}),i.domElements.push(r),{v:i.domElements.length}}();if("object"===("undefined"==typeof r?"undefined":(0,a.default)(r)))return r.v}return 0}},{key:"_makeHeader",value:function(t){var e=document.createElement("div");e.className="vis-configuration vis-config-header",e.innerHTML=t,this._makeItem([],e)}},{key:"_makeLabel",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=document.createElement("div");return o.className="vis-configuration vis-config-label vis-config-s"+e.length,i===!0?o.innerHTML="<i><b>"+t+":</b></i>":o.innerHTML=t+":",o}},{key:"_makeDropdown",value:function(t,e,i){var o=document.createElement("select");o.className="vis-configuration vis-config-select";var n=0;void 0!==e&&t.indexOf(e)!==-1&&(n=t.indexOf(e));for(var s=0;s<t.length;s++){var r=document.createElement("option");r.value=t[s],s===n&&(r.selected="selected"),r.innerHTML=t[s],o.appendChild(r)}var a=this;o.onchange=function(){a._update(this.value,i)};var h=this._makeLabel(i[i.length-1],i);this._makeItem(i,h,o)}},{key:"_makeRange",value:function(t,e,i){var o=t[0],n=t[1],s=t[2],r=t[3],a=document.createElement("input");a.className="vis-configuration vis-config-range";try{a.type="range",a.min=n,a.max=s}catch(t){}a.step=r;var h="",d=0;if(void 0!==e){var l=1.2;e<0&&e*l<n?(a.min=Math.ceil(e*l),d=a.min,h="range increased"):e/l<n&&(a.min=Math.ceil(e/l),d=a.min,h="range increased"),e*l>s&&1!==s&&(a.max=Math.ceil(e*l),d=a.max,h="range increased"),a.value=e}else a.value=o;var u=document.createElement("input");u.className="vis-configuration vis-config-rangeinput",u.value=a.value;var c=this;a.onchange=function(){u.value=this.value,c._update(Number(this.value),i)},a.oninput=function(){u.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,u);""!==h&&this.popupHistory[f]!==d&&(this.popupHistory[f]=d,this._setupPopup(h,f))}},{key:"_setupPopup",value:function(t,e){var i=this;if(this.initialized===!0&&this.allowCreation===!0&&this.popupCounter<this.popupLimit){var o=document.createElement("div");o.id="vis-configuration-popup",o.className="vis-configuration-popup",o.innerHTML=t,o.onclick=function(){i._removePopup()},this.popupCounter+=1,this.popupDiv={html:o,index:e}}}},{key:"_removePopup",value:function(){void 0!==this.popupDiv.html&&(this.popupDiv.html.parentNode.removeChild(this.popupDiv.html),clearTimeout(this.popupDiv.hideTimeout),clearTimeout(this.popupDiv.deleteTimeout),this.popupDiv={})}},{key:"_showPopupIfNeeded",value:function(){var t=this;if(void 0!==this.popupDiv.html){var e=this.domElements[this.popupDiv.index],i=e.getBoundingClientRect();this.popupDiv.html.style.left=i.left+"px",this.popupDiv.html.style.top=i.top-30+"px",document.body.appendChild(this.popupDiv.html),this.popupDiv.hideTimeout=setTimeout(function(){t.popupDiv.html.style.opacity=0},1500),this.popupDiv.deleteTimeout=setTimeout(function(){t._removePopup()},1800)}}},{key:"_makeCheckbox",value:function(t,e,i){var o=document.createElement("input");o.type="checkbox",o.className="vis-configuration vis-config-checkbox",o.checked=t,void 0!==e&&(o.checked=e,e!==t&&("object"===("undefined"==typeof t?"undefined":(0,a.default)(t))?e!==t.enabled&&this.changedOptions.push({path:i,value:e}):this.changedOptions.push({path:i,value:e})));var n=this;o.onchange=function(){n._update(this.checked,i)};var s=this._makeLabel(i[i.length-1],i);this._makeItem(i,s,o)}},{key:"_makeTextInput",value:function(t,e,i){var o=document.createElement("input");o.type="text",o.className="vis-configuration vis-config-text",o.value=e,e!==t&&this.changedOptions.push({path:i,value:e});var n=this;o.onchange=function(){n._update(this.value,i)};var s=this._makeLabel(i[i.length-1],i);this._makeItem(i,s,o)}},{key:"_makeColorField",value:function(t,e,i){var o=this,n=t[1],s=document.createElement("div");e=void 0===e?n:e,"none"!==e?(s.className="vis-configuration vis-config-colorBlock",s.style.backgroundColor=e):s.className="vis-configuration vis-config-colorBlock none",e=void 0===e?n:e,s.onclick=function(){o._showColorPicker(e,s,i)};var r=this._makeLabel(i[i.length-1],i);this._makeItem(i,r,s)}},{key:"_showColorPicker",value:function(t,e,i){var o=this;e.onclick=function(){},this.colorPicker.insertTo(e),this.colorPicker.show(),this.colorPicker.setColor(t),this.colorPicker.setUpdateCallback(function(t){var n="rgba("+t.r+","+t.g+","+t.b+","+t.a+")";e.style.backgroundColor=n,o._update(n,i)}),this.colorPicker.setCloseCallback(function(){e.onclick=function(){o._showColorPicker(t,e,i)}})}},{key:"_handleObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=!1,n=this.options.filter,s=!1;for(var r in t)if(t.hasOwnProperty(r)){o=!0;var a=t[r],h=f.copyAndExtendArray(e,r);if("function"==typeof n&&(o=n(r,e),o===!1&&!(a instanceof Array)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,o=this._handleObject(a,h,!0),this.allowCreation=i===!1)),o!==!1){s=!0;var d=this._getValue(h);if(a instanceof Array)this._handleArray(a,d,h);else if("string"==typeof a)this._makeTextInput(a,d,h);else if("boolean"==typeof a)this._makeCheckbox(a,d,h);else if(a instanceof Object){var l=!0;if(e.indexOf("physics")!==-1&&this.moduleOptions.physics.solver!==r&&(l=!1),l===!0)if(void 0!==a.enabled){var u=f.copyAndExtendArray(h,"enabled"),c=this._getValue(u);if(c===!0){var p=this._makeLabel(r,h,!0);this._makeItem(h,p),s=this._handleObject(a,h)||s}else this._makeCheckbox(a,c,h)}else{var m=this._makeLabel(r,h,!0);this._makeItem(h,m),s=this._handleObject(a,h)||s}}else console.error("dont know how to handle",a,r,h)}}return s}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=i;t="true"===t||t,t="false"!==t&&t;for(var n=0;n<e.length;n++)"global"!==e[n]&&(void 0===o[e[n]]&&(o[e[n]]={}),n!==e.length-1?o=o[e[n]]:o[e[n]]=t);return i}},{key:"_printOptions",value:function(){var t=this.getOptions();this.optionsContainer.innerHTML="<pre>var options = "+(0,s.default)(t,null,2)+"</pre>"}},{key:"getOptions",value:function(){for(var t={},e=0;e<this.changedOptions.length;e++)this._constructOptions(this.changedOptions[e].value,this.changedOptions[e].path,t);return t}}]),t}();e.default=m},function(t,e){e.__esModule=!0,e.default=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(117),s=o(n);e.default=function(){function t(t,e){for(var i=0;i<e.length;i++){var o=e[i];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),(0,s.default)(t,o.key,o)}}return function(e,i,o){return i&&t(e.prototype,i),o&&t(e,o),e}}()},function(t,e,i){t.exports={default:i(118),__esModule:!0}},function(t,e,i){i(119);var o=i(17).Object;t.exports=function(t,e,i){return o.defineProperty(t,e,i)}},function(t,e,i){var o=i(15);o(o.S+o.F*!i(25),"Object",{defineProperty:i(21).f})},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(82),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(108),u=i(121),c=i(1),p=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;(0,a.default)(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return(0,d.default)(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){var e={black:"#000000",navy:"#000080",darkblue:"#00008B",mediumblue:"#0000CD",blue:"#0000FF",darkgreen:"#006400",green:"#008000",teal:"#008080",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",lime:"#00FF00",springgreen:"#00FF7F",aqua:"#00FFFF",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",mediumaquamarine:"#66CDAA",dimgray:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",lightslategray:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",maroon:"#800000",purple:"#800080",olive:"#808000",gray:"#808080",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370D8",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",silver:"#C0C0C0",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgrey:"#D3D3D3",palevioletred:"#D87093",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",red:"#FF0000",fuchsia:"#FF00FF",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",yellow:"#FFFF00",lightyellow:"#FFFFE0",ivory:"#FFFFF0",white:"#FFFFFF"};if("string"==typeof t)return e[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i=void 0,o=this._isColorString(t);if(void 0!==o&&(t=o),c.isString(t)===!0){if(c.isValidRGB(t)===!0){var n=t.substr(4).substr(0,t.length-5).split(",");i={r:n[0],g:n[1],b:n[2],a:1}}else if(c.isValidRGBA(t)===!0){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(c.isValidHex(t)===!0){var a=c.hexToRGB(t);i={r:a.r,g:a.g,b:a.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var h=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:h}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+(0,
-s.default)(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this,e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];e===!0&&(this.previousColor=c.extend({},this.color)),this.applied===!0&&this.updateCallback(this.initialColor),this.frame.style.display="none",setTimeout(function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)},0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e===!0&&(this.initialColor=c.extend({},t)),this.color=t;var i=c.RGBToHSV(t.r,t.g,t.b),o=2*Math.PI,n=this.r*i.s,s=this.centerCoordinates.x+n*Math.sin(o*i.h),r=this.centerCoordinates.y+n*Math.cos(o*i.h);this.colorPickerSelector.style.left=s-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=c.RGBToHSV(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=c.HSVToRGB(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=c.RGBToHSV(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var o=this.colorPickerCanvas.clientWidth,n=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,o,n),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),i.fill(),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var t=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var e=document.createElement("DIV");e.style.color="red",e.style.fontWeight="bold",e.style.padding="10px",e.innerHTML="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(e)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var i=this;this.opacityRange.onchange=function(){i._setOpacity(this.value)},this.opacityRange.oninput=function(){i._setOpacity(this.value)},this.brightnessRange.onchange=function(){i._setBrightness(this.value)},this.brightnessRange.oninput=function(){i._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerHTML="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerHTML="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerHTML="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerHTML="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerHTML="cancel",this.cancelButton.onclick=this._hide.bind(this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerHTML="apply",this.applyButton.onclick=this._apply.bind(this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerHTML="save",this.saveButton.onclick=this._save.bind(this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerHTML="load last",this.loadButton.onclick=this._loadLast.bind(this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new l(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),u.onTouch(this.hammer,function(e){t._moveSelector(e)}),this.hammer.on("tap",function(e){t._moveSelector(e)}),this.hammer.on("panstart",function(e){t._moveSelector(e)}),this.hammer.on("panmove",function(e){t._moveSelector(e)}),this.hammer.on("panend",function(e){t._moveSelector(e)})}},{key:"_generateHueCircle",value:function(){if(this.generated===!1){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e=this.colorPickerCanvas.clientWidth,i=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,e,i);var o=void 0,n=void 0,s=void 0,r=void 0;this.centerCoordinates={x:.5*e,y:.5*i},this.r=.49*e;var a=2*Math.PI/360,h=1/360,d=1/this.r,l=void 0;for(s=0;s<360;s++)for(r=0;r<this.r;r++)o=this.centerCoordinates.x+r*Math.sin(a*s),n=this.centerCoordinates.y+r*Math.cos(a*s),l=c.HSVToRGB(s*h,r*d,1),t.fillStyle="rgb("+l.r+","+l.g+","+l.b+")",t.fillRect(o-.5,n-.5,2,2);t.strokeStyle="rgba(0,0,0,1)",t.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),t.stroke(),this.hueCircle=t.getImageData(0,0,e,i)}this.generated=!0}},{key:"_moveSelector",value:function(t){var e=this.colorPickerDiv.getBoundingClientRect(),i=t.center.x-e.left,o=t.center.y-e.top,n=.5*this.colorPickerDiv.clientHeight,s=.5*this.colorPickerDiv.clientWidth,r=i-s,a=o-n,h=Math.atan2(r,a),d=.98*Math.min(Math.sqrt(r*r+a*a),s),l=Math.cos(h)*d+n,u=Math.sin(h)*d+s;this.colorPickerSelector.style.top=l-.5*this.colorPickerSelector.clientHeight+"px",this.colorPickerSelector.style.left=u-.5*this.colorPickerSelector.clientWidth+"px";var p=h/(2*Math.PI);p=p<0?p+1:p;var f=d/this.r,m=c.RGBToHSV(this.color.r,this.color.g,this.color.b);m.h=p,m.s=f;var v=c.HSVToRGB(m.h,m.s,m.v);v.a=this.color.a,this.color=v,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}}]),t}();e.default=p},function(t,e,i){i(108);e.onTouch=function(t,e){e.inputHandler=function(t){t.isFirst&&e(t)},t.on("hammer.input",e.inputHandler)},e.onRelease=function(t,e){return e.inputHandler=function(t){t.isFinal&&e(t)},t.on("hammer.input",e.inputHandler)},e.offTouch=function(t,e){t.off("hammer.input",e.inputHandler)},e.offRelease=e.offTouch,e.disablePreventDefaultVertically=function(t){var e="pan-y";return t.getTouchAction=function(){return[e]},t}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.printStyle=void 0;var n=i(82),s=o(n),r=i(62),a=o(r),h=i(58),d=o(h),l=i(115),u=o(l),c=i(116),p=o(c),f=i(1),m=!1,v=void 0,g="background: #FFeeee; color: #dd0000",y=function(){function t(){(0,u.default)(this,t)}return(0,p.default)(t,null,[{key:"validate",value:function(e,i,o){m=!1,v=i;var n=i;return void 0!==o&&(n=i[o]),t.parse(e,n,[]),m}},{key:"parse",value:function(e,i,o){for(var n in e)e.hasOwnProperty(n)&&t.check(n,e,i,o)}},{key:"check",value:function(e,i,o,n){void 0===o[e]&&void 0===o.__any__?t.getSuggestion(e,o,n):void 0===o[e]&&void 0!==o.__any__?"object"===t.getType(i[e])&&void 0!==o.__any__.__type__?t.checkFields(e,i,o,"__any__",o.__any__.__type__,n):t.checkFields(e,i,o,"__any__",o.__any__,n):void 0!==o[e].__type__?t.checkFields(e,i,o,e,o[e].__type__,n):t.checkFields(e,i,o,e,o[e],n)}},{key:"checkFields",value:function(e,i,o,n,s,r){var a=t.getType(i[e]),h=s[a];void 0!==h?"array"===t.getType(h)&&h.indexOf(i[e])===-1?(console.log('%cInvalid option detected in "'+e+'". Allowed values are:'+t.print(h)+' not "'+i[e]+'". '+t.printLocation(r,e),g),m=!0):"object"===a&&"__any__"!==n&&(r=f.copyAndExtendArray(r,e),t.parse(i[e],o[n],r)):void 0===s.any&&(console.log('%cInvalid type received for "'+e+'". Expected: '+t.print((0,d.default)(s))+". Received ["+a+'] "'+i[e]+'"'+t.printLocation(r,e),g),m=!0)}},{key:"getType",value:function(t){var e="undefined"==typeof t?"undefined":(0,a.default)(t);return"object"===e?null===t?"null":t instanceof Boolean?"boolean":t instanceof Number?"number":t instanceof String?"string":Array.isArray(t)?"array":t instanceof Date?"date":void 0!==t.nodeType?"dom":t._isAMomentObject===!0?"moment":"object":"number"===e?"number":"boolean"===e?"boolean":"string"===e?"string":void 0===e?"undefined":e}},{key:"getSuggestion",value:function(e,i,o){var n=t.findInOptions(e,i,o,!1),s=t.findInOptions(e,v,[],!0),r=8,a=4;void 0!==n.indexMatch?console.log('%cUnknown option detected: "'+e+'" in '+t.printLocation(n.path,e,"")+'Perhaps it was incomplete? Did you mean: "'+n.indexMatch+'"?\n\n',g):s.distance<=a&&n.distance>s.distance?console.log('%cUnknown option detected: "'+e+'" in '+t.printLocation(n.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""),g):n.distance<=r?console.log('%cUnknown option detected: "'+e+'". Did you mean "'+n.closestMatch+'"?'+t.printLocation(n.path,e),g):console.log('%cUnknown option detected: "'+e+'". Did you mean one of these: '+t.print((0,d.default)(i))+t.printLocation(o,e),g),m=!0}},{key:"findInOptions",value:function(e,i,o){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,r="",a=[],h=e.toLowerCase(),d=void 0;for(var l in i){var u=void 0;if(void 0!==i[l].__type__&&n===!0){var c=t.findInOptions(e,i[l],f.copyAndExtendArray(o,l));s>c.distance&&(r=c.closestMatch,a=c.path,s=c.distance,d=c.indexMatch)}else l.toLowerCase().indexOf(h)!==-1&&(d=l),u=t.levenshteinDistance(e,l),s>u&&(r=l,a=f.copyArray(o),s=u)}return{closestMatch:r,path:a,distance:s,indexMatch:d}}},{key:"printLocation",value:function(t,e){for(var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n",o="\n\n"+i+"options = {\n",n=0;n<t.length;n++){for(var s=0;s<n+1;s++)o+="  ";o+=t[n]+": {\n"}for(var r=0;r<t.length+1;r++)o+="  ";o+=e+"\n";for(var a=0;a<t.length+1;a++){for(var h=0;h<t.length-a;h++)o+="  ";o+="}\n"}return o+"\n\n"}},{key:"print",value:function(t){return(0,s.default)(t).replace(/(\")|(\[)|(\])|(,"__type__")/g,"").replace(/(\,)/g,", ")}},{key:"levenshteinDistance",value:function(t,e){if(0===t.length)return e.length;if(0===e.length)return t.length;var i,o=[];for(i=0;i<=e.length;i++)o[i]=[i];var n;for(n=0;n<=t.length;n++)o[0][n]=n;for(i=1;i<=e.length;i++)for(n=1;n<=t.length;n++)e.charAt(i-1)==t.charAt(n-1)?o[i][n]=o[i-1][n-1]:o[i][n]=Math.min(o[i-1][n-1]+1,Math.min(o[i][n-1]+1,o[i-1][n]+1));return o[e.length][t.length]}}]),t}();e.default=y,e.printStyle=g},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){var i=p().hours(0).minutes(0).seconds(0).milliseconds(0),o=i.clone().add(-3,"days").valueOf(),n=i.clone().add(-3,"days").valueOf();void 0===e?(this.start=o,this.end=n):(this.start=e.start||o,this.end=e.end||n),this.rolling=!1,this.body=t,this.deltaDifference=0,this.scaleOffset=0,this.startToFront=!1,this.endToFront=!0,this.defaultOptions={rtl:!1,start:null,end:null,moment:p,direction:"horizontal",moveable:!0,zoomable:!0,min:null,max:null,zoomMin:10,zoomMax:31536e10},this.options=c.extend({},this.defaultOptions),this.props={touch:{}},this.animationTimer=null,this.body.emitter.on("panstart",this._onDragStart.bind(this)),this.body.emitter.on("panmove",this._onDrag.bind(this)),this.body.emitter.on("panend",this._onDragEnd.bind(this)),this.body.emitter.on("mousewheel",this._onMouseWheel.bind(this)),this.body.emitter.on("touch",this._onTouch.bind(this)),this.body.emitter.on("pinch",this._onPinch.bind(this)),this.body.dom.rollingModeBtn.addEventListener("click",this.startRolling.bind(this)),this.setOptions(e)}function s(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'+t+'". Choose "horizontal" or "vertical".')}var r=i(58),a=o(r),h=i(82),d=o(h),l=i(62),u=o(l),c=i(1),p=(i(121),i(84)),f=i(124),m=i(125);n.prototype=new f,n.prototype.setOptions=function(t){if(t){var e=["animation","direction","min","max","zoomMin","zoomMax","moveable","zoomable","moment","activate","hiddenDates","zoomKey","rtl","showCurrentTime","rollMode","horizontalScroll"];c.selectiveExtend(e,this.options,t),t.rollingMode&&this.startRolling(),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},n.prototype.startRolling=function(){function t(){e.stopRolling(),e.rolling=!0;var i=e.end-e.start,o=c.convert(new Date,"Date").valueOf(),n=o-i/2,s=o+i/2;!e.options||void 0===e.options.animation||e.options.animation;e.setRange(n,s,!1);var r=e.conversion(e.body.domProps.center.width).scale,i=1/r/10;i<30&&(i=30),i>1e3&&(i=1e3),e.body.dom.rollingModeBtn.style.visibility="hidden",e.currentTimeTimer=setTimeout(t,i)}var e=this;t()},n.prototype.stopRolling=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),this.rolling=!1,this.body.dom.rollingModeBtn.style.visibility="visible")},n.prototype.setRange=function(t,e,i,o,n){o!==!0&&(o=!1);var s=void 0!=t?c.convert(t,"Date").valueOf():null,r=void 0!=e?c.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),i){var h=this,l=this.start,p=this.end,f="object"===("undefined"==typeof i?"undefined":(0,u.default)(i))&&"duration"in i?i.duration:500,v="object"===("undefined"==typeof i?"undefined":(0,u.default)(i))&&"easingFunction"in i?i.easingFunction:"easeInOutQuad",g=c.easingFunctions[v];if(!g)throw new Error("Unknown easing function "+(0,d.default)(v)+". Choose from: "+(0,a.default)(c.easingFunctions).join(", "));var y=(new Date).valueOf(),b=!1,_=function t(){if(!h.props.touch.dragging){var e=(new Date).valueOf(),i=e-y,a=g(i/f),d=i>f,u=d||null===s?s:l+(s-l)*a,v=d||null===r?r:p+(r-p)*a;w=h._applyRange(u,v),m.updateHiddenDates(h.options.moment,h.body,h.options.hiddenDates),b=b||w;var _={start:new Date(h.start),end:new Date(h.end),byUser:o,event:c.elementsCensor(n)};w&&h.body.emitter.emit("rangechange",_),d?b&&h.body.emitter.emit("rangechanged",_):h.animationTimer=setTimeout(t,20)}};return _()}var w=this._applyRange(s,r);if(m.updateHiddenDates(this.options.moment,this.body,this.options.hiddenDates),w){var x={start:new Date(this.start),end:new Date(this.end),byUser:o,event:c.elementsCensor(n)};this.body.emitter.emit("rangechange",x),this.body.emitter.emit("rangechanged",x)}},n.prototype._cancelAnimation=function(){this.animationTimer&&(clearTimeout(this.animationTimer),this.animationTimer=null)},n.prototype._applyRange=function(t,e){var i,o=null!=t?c.convert(t,"Date").valueOf():this.start,n=null!=e?c.convert(e,"Date").valueOf():this.end,s=null!=this.options.max?c.convert(this.options.max,"Date").valueOf():null,r=null!=this.options.min?c.convert(this.options.min,"Date").valueOf():null;if(isNaN(o)||null===o)throw new Error('Invalid start "'+t+'"');if(isNaN(n)||null===n)throw new Error('Invalid end "'+e+'"');if(n<o&&(n=o),null!==r&&o<r&&(i=r-o,o+=i,n+=i,null!=s&&n>s&&(n=s)),null!==s&&n>s&&(i=n-s,o-=i,n-=i,null!=r&&o<r&&(o=r)),null!==this.options.zoomMin){var a=parseFloat(this.options.zoomMin);a<0&&(a=0),n-o<a&&(this.end-this.start===a&&o>this.start&&n<this.end?(o=this.start,n=this.end):(i=a-(n-o),o-=i/2,n+=i/2))}if(null!==this.options.zoomMax){var h=parseFloat(this.options.zoomMax);h<0&&(h=0),n-o>h&&(this.end-this.start===h&&o<this.start&&n>this.end?(o=this.start,n=this.end):(i=n-o-h,o+=i/2,n-=i/2))}var d=this.start!=o||this.end!=n;return o>=this.start&&o<=this.end||n>=this.start&&n<=this.end||this.start>=o&&this.start<=n||this.end>=o&&this.end<=n||this.body.emitter.emit("checkRangedItems"),this.start=o,this.end=n,d},n.prototype.getRange=function(){return{start:this.start,end:this.end}},n.prototype.conversion=function(t,e){return n.conversion(this.start,this.end,t,e)},n.conversion=function(t,e,i,o){return void 0===o&&(o=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-o)}:{offset:0,scale:1}},n.prototype._onDragStart=function(t){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this._isInsideRange(t)&&this.props.touch.allowDragging&&(this.stopRolling(),this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},n.prototype._onDrag=function(t){if(t&&this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;s(e);var i="horizontal"==e?t.deltaX:t.deltaY;i-=this.deltaDifference;var o=this.props.touch.end-this.props.touch.start,n=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end);o-=n;var r="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height;if(this.options.rtl)var a=i/r*o;else var a=-i/r*o;var h=this.props.touch.start+a,d=this.props.touch.end+a,l=m.snapAwayFromHidden(this.body.hiddenDates,h,this.previousDelta-i,!0),u=m.snapAwayFromHidden(this.body.hiddenDates,d,this.previousDelta-i,!0);if(l!=h||u!=d)return this.deltaDifference+=i,this.props.touch.start=l,this.props.touch.end=u,void this._onDrag(t);this.previousDelta=i,this._applyRange(h,d);var p=new Date(this.start),f=new Date(this.end);this.body.emitter.emit("rangechange",{start:p,end:f,byUser:!0,event:c.elementsCensor(t)}),this.body.emitter.emit("panmove")}},n.prototype._onDragEnd=function(t){this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end),byUser:!0,event:c.elementsCensor(t)}))},n.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),this.options.zoomKey&&!t[this.options.zoomKey]&&this.options.zoomable||!this.options.zoomable&&this.options.moveable){if(this.options.horizontalScroll){t.preventDefault();var i=e*(this.end-this.start)/20,o=this.start-i,n=this.end-i;this.setRange(o,n,!1,!0,t)}}else if(this.options.zoomable&&this.options.moveable&&this._isInsideRange(t)&&e){var s;s=e<0?1-e/5:1/(1+e/5);var r;if(this.rolling)r=(this.start+this.end)/2;else{var a=this.getPointer({x:t.clientX,y:t.clientY},this.body.dom.center);r=this._pointerToDate(a)}this.zoom(s,r,e,t),t.preventDefault()}},n.prototype._onTouch=function(t){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null,this.scaleOffset=0,this.deltaDifference=0},n.prototype._onPinch=function(t){if(this.options.zoomable&&this.options.moveable){this.props.touch.allowDragging=!1,this.props.touch.center||(this.props.touch.center=this.getPointer(t.center,this.body.dom.center)),this.stopRolling();var e=1/(t.scale+this.scaleOffset),i=this._pointerToDate(this.props.touch.center),o=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),n=m.getHiddenDurationBefore(this.options.moment,this.body.hiddenDates,this,i),s=o-n,r=i-n+(this.props.touch.start-(i-n))*e,a=i+s+(this.props.touch.end-(i+s))*e;this.startToFront=1-e<=0,this.endToFront=e-1<=0;var h=m.snapAwayFromHidden(this.body.hiddenDates,r,1-e,!0),d=m.snapAwayFromHidden(this.body.hiddenDates,a,e-1,!0);h==r&&d==a||(this.props.touch.start=h,this.props.touch.end=d,this.scaleOffset=1-t.scale,r=h,a=d),this.setRange(r,a,!1,!0,t),this.startToFront=!1,this.endToFront=!0}},n.prototype._isInsideRange=function(t){var e=t.center?t.center.x:t.clientX;if(this.options.rtl)var i=e-c.getAbsoluteLeft(this.body.dom.centerContainer);else var i=c.getAbsoluteRight(this.body.dom.centerContainer)-e;var o=this.body.util.toTime(i);return o>=this.start&&o<=this.end},n.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(s(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var o=this.body.domProps.center.height;return e=this.conversion(o),t.y/e.scale+e.offset},n.prototype.getPointer=function(t,e){return this.options.rtl?{x:c.getAbsoluteRight(e)-t.x,y:t.y-c.getAbsoluteTop(e)}:{x:t.x-c.getAbsoluteLeft(e),y:t.y-c.getAbsoluteTop(e)}},n.prototype.zoom=function(t,e,i,o){null==e&&(e=(this.start+this.end)/2);var n=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),s=m.getHiddenDurationBefore(this.options.moment,this.body.hiddenDates,this,e),r=n-s,a=e-s+(this.start-(e-s))*t,h=e+r+(this.end-(e+r))*t;this.startToFront=!(i>0),this.endToFront=!(-i>0);var d=m.snapAwayFromHidden(this.body.hiddenDates,a,i,!0),l=m.snapAwayFromHidden(this.body.hiddenDates,h,-i,!0);d==a&&l==h||(a=d,h=l),this.setRange(a,h,!1,!0,o),this.startToFront=!1,this.endToFront=!0},n.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,o=this.end+e*t;this.start=i,this.end=o},n.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,o=this.start-i,n=this.end-i;this.setRange(o,n,!1,!0,event)},t.exports=n},function(t,e,i){function o(t,e){this.options=null,this.props=null}var n=i(1);o.prototype.setOptions=function(t){t&&n.extend(this.options,t)},o.prototype.redraw=function(){return!1},o.prototype.destroy=function(){},o.prototype._isResized=function(){var t=this.props._previousWidth!==this.props.width||this.props._previousHeight!==this.props.height;return this.props._previousWidth=this.props.width,this.props._previousHeight=this.props.height,t},t.exports=o},function(t,e){e.convertHiddenOptions=function(t,i,o){if(o&&!Array.isArray(o))return e.convertHiddenOptions(t,i,[o]);if(i.hiddenDates=[],o&&1==Array.isArray(o)){for(var n=0;n<o.length;n++)if(void 0===o[n].repeat){var s={};s.start=t(o[n].start).toDate().valueOf(),s.end=t(o[n].end).toDate().valueOf(),i.hiddenDates.push(s)}i.hiddenDates.sort(function(t,e){return t.start-e.start})}},e.updateHiddenDates=function(t,i,o){if(o&&!Array.isArray(o))return e.updateHiddenDates(t,i,[o]);if(o&&void 0!==i.domProps.centerContainer.width){e.convertHiddenOptions(t,i,o);for(var n=t(i.range.start),s=t(i.range.end),r=i.range.end-i.range.start,a=r/i.domProps.centerContainer.width,h=0;h<o.length;h++)if(void 0!==o[h].repeat){var d=t(o[h].start),l=t(o[h].end);if("Invalid Date"==d._d)throw new Error("Supplied start date is not valid: "+o[h].start);if("Invalid Date"==l._d)throw new Error("Supplied end date is not valid: "+o[h].end);var u=l-d;if(u>=4*a){var c=0,p=s.clone();switch(o[h].repeat){case"daily":d.day()!=l.day()&&(c=1),d.dayOfYear(n.dayOfYear()),d.year(n.year()),d.subtract(7,"days"),l.dayOfYear(n.dayOfYear()),l.year(n.year()),l.subtract(7-c,"days"),p.add(1,"weeks");break;case"weekly":var f=l.diff(d,"days"),m=d.day();d.date(n.date()),d.month(n.month()),d.year(n.year()),l=d.clone(),d.day(m),l.day(m),l.add(f,"days"),d.subtract(1,"weeks"),l.subtract(1,"weeks"),p.add(1,"weeks");break;case"monthly":d.month()!=l.month()&&(c=1),d.month(n.month()),d.year(n.year()),d.subtract(1,"months"),l.month(n.month()),l.year(n.year()),l.subtract(1,"months"),l.add(c,"months"),p.add(1,"months");break;case"yearly":d.year()!=l.year()&&(c=1),d.year(n.year()),d.subtract(1,"years"),l.year(n.year()),l.subtract(1,"years"),l.add(c,"years"),p.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",o[h].repeat)}for(;d<p;)switch(i.hiddenDates.push({start:d.valueOf(),end:l.valueOf()}),o[h].repeat){case"daily":d.add(1,"days"),l.add(1,"days");break;case"weekly":d.add(1,"weeks"),l.add(1,"weeks");break;case"monthly":d.add(1,"months"),l.add(1,"months");break;case"yearly":d.add(1,"y"),l.add(1,"y");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",o[h].repeat)}i.hiddenDates.push({start:d.valueOf(),end:l.valueOf()})}}e.removeDuplicates(i);var v=e.isHidden(i.range.start,i.hiddenDates),g=e.isHidden(i.range.end,i.hiddenDates),y=i.range.start,b=i.range.end;1==v.hidden&&(y=1==i.range.startToFront?v.startDate-1:v.endDate+1),1==g.hidden&&(b=1==i.range.endToFront?g.startDate-1:g.endDate+1),1!=v.hidden&&1!=g.hidden||i.range._applyRange(y,b)}},e.removeDuplicates=function(t){for(var e=t.hiddenDates,i=[],o=0;o<e.length;o++)for(var n=0;n<e.length;n++)o!=n&&1!=e[n].remove&&1!=e[o].remove&&(e[n].start>=e[o].start&&e[n].end<=e[o].end?e[n].remove=!0:e[n].start>=e[o].start&&e[n].start<=e[o].end?(e[o].end=e[n].end,e[n].remove=!0):e[n].end>=e[o].start&&e[n].end<=e[o].end&&(e[o].start=e[n].start,e[n].remove=!0));for(var o=0;o<e.length;o++)e[o].remove!==!0&&i.push(e[o]);t.hiddenDates=i,t.hiddenDates.sort(function(t,e){return t.start-e.start})},e.printDates=function(t){for(var e=0;e<t.length;e++)console.log(e,new Date(t[e].start),new Date(t[e].end),t[e].start,t[e].end,t[e].remove)},e.stepOverHiddenDates=function(t,e,i){for(var o=!1,n=e.current.valueOf(),s=0;s<e.hiddenDates.length;s++){var r=e.hiddenDates[s].start,a=e.hiddenDates[s].end;if(n>=r&&n<a){o=!0;break}}if(1==o&&n<e._end.valueOf()&&n!=i){var h=t(i),d=t(a);h.year()!=d.year()?e.switchedYear=!0:h.month()!=d.month()?e.switchedMonth=!0:h.dayOfYear()!=d.dayOfYear()&&(e.switchedDay=!0),e.current=d}},e.toScreen=function(t,i,o){if(0==t.body.hiddenDates.length){var n=t.range.conversion(o);return(i.valueOf()-n.offset)*n.scale}var s=e.isHidden(i,t.body.hiddenDates);1==s.hidden&&(i=s.startDate);var r=e.getHiddenDurationBetween(t.body.hiddenDates,t.range.start,t.range.end);if(i<t.range.start){var n=t.range.conversion(o,r),a=e.getHiddenDurationBeforeStart(t.body.hiddenDates,i,n.offset);return i=t.options.moment(i).toDate().valueOf(),i+=a,-(n.offset-i.valueOf())*n.scale}if(i>t.range.end){var h={start:t.range.start,end:i};i=e.correctTimeForHidden(t.options.moment,t.body.hiddenDates,h,i);var n=t.range.conversion(o,r);return(i.valueOf()-n.offset)*n.scale}i=e.correctTimeForHidden(t.options.moment,t.body.hiddenDates,t.range,i);var n=t.range.conversion(o,r);return(i.valueOf()-n.offset)*n.scale},e.toTime=function(t,i,o){if(0==t.body.hiddenDates.length){var n=t.range.conversion(o);return new Date(i/n.scale+n.offset)}var s=e.getHiddenDurationBetween(t.body.hiddenDates,t.range.start,t.range.end),r=t.range.end-t.range.start-s,a=r*i/o,h=e.getAccumulatedHiddenDuration(t.body.hiddenDates,t.range,a),d=new Date(h+a+t.range.start);return d},e.getHiddenDurationBetween=function(t,e,i){for(var o=0,n=0;n<t.length;n++){var s=t[n].start,r=t[n].end;s>=e&&r<i&&(o+=r-s)}return o},e.getHiddenDurationBeforeStart=function(t,e,i){for(var o=0,n=0;n<t.length;n++){var s=t[n].start,r=t[n].end;s>=e&&r<=i&&(o+=r-s)}return o},e.correctTimeForHidden=function(t,i,o,n){return n=t(n).toDate().valueOf(),n-=e.getHiddenDurationBefore(t,i,o,n)},e.getHiddenDurationBefore=function(t,e,i,o){var n=0;o=t(o).toDate().valueOf();for(var s=0;s<e.length;s++){var r=e[s].start,a=e[s].end;r>=i.start&&a<i.end&&o>=a&&(n+=a-r)}return n},e.getAccumulatedHiddenDuration=function(t,e,i){for(var o=0,n=0,s=e.start,r=0;r<t.length;r++){var a=t[r].start,h=t[r].end;if(a>=e.start&&h<e.end){if(n+=a-s,s=h,n>=i)break;o+=h-a}}return o},e.snapAwayFromHidden=function(t,i,o,n){var s=e.isHidden(i,t);return 1==s.hidden?o<0?1==n?s.startDate-(s.endDate-i)-1:s.startDate-1:1==n?s.endDate+(i-s.startDate)+1:s.endDate+1:i},e.isHidden=function(t,e){for(var i=0;i<e.length;i++){var o=e[i].start,n=e[i].end;if(t>=o&&t<n)return{hidden:!0,startDate:o,endDate:n}}return{hidden:!1,startDate:o,endDate:n}}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(){}var s=i(82),r=o(s),a=i(62),h=o(a),d=i(95),l=i(108),u=i(121),c=i(1),p=(i(91),i(93),i(123),i(127),i(138)),f=i(139),m=i(125),v=i(140);d(n.prototype),n.prototype._create=function(t){function e(t){if(this.isActive()&&this.emit("mousewheel",t),this.options.verticalScroll&&!this.options.horizontalScroll&&this.options.zoomKey&&!t[this.options.zoomKey]){t.preventDefault();var e=0;t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3);var i=this.props.scrollTop,o=i+120*e;this.isActive()&&(this._setScrollTop(o),this._redraw(),this.emit("scroll",t))}}function i(t){if(s.options.verticalScroll&&(t.preventDefault(),s.isActive())){var e=-t.target.scrollTop;s._setScrollTop(e),s._redraw(),s.emit("scrollSide",t)}}function o(t){if(t.preventDefault&&t.preventDefault(),!(!t.target.className.indexOf("vis")>-1||h))return t.dataTransfer.dropEffect="move",h=!0,!1}function n(t){try{var e=JSON.parse(t.dataTransfer.getData("text"));if(!e.content)return}catch(t){return!1}return h=!1,t.center={x:t.clientX,y:t.clientY},s.itemSet._onAddItem(t),!1}this.dom={},this.dom.container=t,this.dom.root=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.backgroundVertical=document.createElement("div"),this.dom.backgroundHorizontal=document.createElement("div"),this.dom.centerContainer=document.createElement("div"),this.dom.leftContainer=document.createElement("div"),this.dom.rightContainer=document.createElement("div"),this.dom.center=document.createElement("div"),this.dom.left=document.createElement("div"),this.dom.right=document.createElement("div"),this.dom.top=document.createElement("div"),this.dom.bottom=document.createElement("div"),this.dom.shadowTop=document.createElement("div"),
-this.dom.shadowBottom=document.createElement("div"),this.dom.shadowTopLeft=document.createElement("div"),this.dom.shadowBottomLeft=document.createElement("div"),this.dom.shadowTopRight=document.createElement("div"),this.dom.shadowBottomRight=document.createElement("div"),this.dom.rollingModeBtn=document.createElement("div"),this.dom.root.className="vis-timeline",this.dom.background.className="vis-panel vis-background",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical",this.dom.backgroundHorizontal.className="vis-panel vis-background vis-horizontal",this.dom.centerContainer.className="vis-panel vis-center",this.dom.leftContainer.className="vis-panel vis-left",this.dom.rightContainer.className="vis-panel vis-right",this.dom.top.className="vis-panel vis-top",this.dom.bottom.className="vis-panel vis-bottom",this.dom.left.className="vis-content",this.dom.center.className="vis-content",this.dom.right.className="vis-content",this.dom.shadowTop.className="vis-shadow vis-top",this.dom.shadowBottom.className="vis-shadow vis-bottom",this.dom.shadowTopLeft.className="vis-shadow vis-top",this.dom.shadowBottomLeft.className="vis-shadow vis-bottom",this.dom.shadowTopRight.className="vis-shadow vis-top",this.dom.shadowBottomRight.className="vis-shadow vis-bottom",this.dom.rollingModeBtn.className="vis-rolling-mode-btn",this.dom.root.appendChild(this.dom.background),this.dom.root.appendChild(this.dom.backgroundVertical),this.dom.root.appendChild(this.dom.backgroundHorizontal),this.dom.root.appendChild(this.dom.centerContainer),this.dom.root.appendChild(this.dom.leftContainer),this.dom.root.appendChild(this.dom.rightContainer),this.dom.root.appendChild(this.dom.top),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.rollingModeBtn),this.dom.centerContainer.appendChild(this.dom.center),this.dom.leftContainer.appendChild(this.dom.left),this.dom.rightContainer.appendChild(this.dom.right),this.dom.centerContainer.appendChild(this.dom.shadowTop),this.dom.centerContainer.appendChild(this.dom.shadowBottom),this.dom.leftContainer.appendChild(this.dom.shadowTopLeft),this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft),this.dom.rightContainer.appendChild(this.dom.shadowTopRight),this.dom.rightContainer.appendChild(this.dom.shadowBottomRight),this.props={root:{},background:{},centerContainer:{},leftContainer:{},rightContainer:{},center:{},left:{},right:{},top:{},bottom:{},border:{},scrollTop:0,scrollTopMin:0},this.on("rangechange",function(){this.initialDrawDone===!0&&this._redraw()}.bind(this)),this.on("touch",this._onTouch.bind(this)),this.on("panmove",this._onDrag.bind(this));var s=this;this._origRedraw=this._redraw.bind(this),this._redraw=c.throttle(this._origRedraw),this.on("_change",function(t){s.itemSet&&s.itemSet.initialItemSetDrawn&&t&&1==t.queue?s._redraw():s._origRedraw()}),this.hammer=new l(this.dom.root);var r=this.hammer.get("pinch").set({enable:!0});u.disablePreventDefaultVertically(r),this.hammer.get("pan").set({threshold:5,direction:l.DIRECTION_HORIZONTAL}),this.listeners={};var a=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];a.forEach(function(t){var e=function(e){s.isActive()&&s.emit(t,e)};s.hammer.on(t,e),s.listeners[t]=e}),u.onTouch(this.hammer,function(t){s.emit("touch",t)}.bind(this)),u.onRelease(this.hammer,function(t){s.emit("release",t)}.bind(this)),this.dom.centerContainer.addEventListener?(this.dom.centerContainer.addEventListener("mousewheel",e.bind(this),!1),this.dom.centerContainer.addEventListener("DOMMouseScroll",e.bind(this),!1)):this.dom.centerContainer.attachEvent("onmousewheel",e.bind(this)),this.dom.left.parentNode.addEventListener("scroll",i.bind(this)),this.dom.right.parentNode.addEventListener("scroll",i.bind(this));var h=!1;if(this.dom.center.addEventListener("dragover",o.bind(this),!1),this.dom.center.addEventListener("drop",n.bind(this),!1),this.customTimes=[],this.touch={},this.redrawCount=0,this.initialDrawDone=!1,!t)throw new Error("No container provided");t.appendChild(this.dom.root)},n.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","clickToUse","dataAttributes","hiddenDates","locale","locales","moment","rtl","zoomKey","horizontalScroll","verticalScroll"];if(c.selectiveExtend(e,this.options,t),this.dom.rollingModeBtn.style.visibility="hidden",this.options.rtl&&(this.dom.container.style.direction="rtl",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical-rtl"),this.options.verticalScroll&&(this.options.rtl?this.dom.rightContainer.className="vis-panel vis-right vis-vertical-scroll":this.dom.leftContainer.className="vis-panel vis-left vis-vertical-scroll"),this.options.orientation={item:void 0,axis:void 0},"orientation"in t&&("string"==typeof t.orientation?this.options.orientation={item:t.orientation,axis:t.orientation}:"object"===(0,h.default)(t.orientation)&&("item"in t.orientation&&(this.options.orientation.item=t.orientation.item),"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis))),"both"===this.options.orientation.axis){if(!this.timeAxis2){var i=this.timeAxis2=new p(this.body);i.setOptions=function(t){var e=t?c.extend({},t):{};e.orientation="top",p.prototype.setOptions.call(i,e)},this.components.push(i)}}else if(this.timeAxis2){var o=this.components.indexOf(this.timeAxis2);o!==-1&&this.components.splice(o,1),this.timeAxis2.destroy(),this.timeAxis2=null}if("function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),"hiddenDates"in this.options&&m.convertHiddenOptions(this.options.moment,this.body,this.options.hiddenDates),"clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new f(this.dom.root)):this.activator&&(this.activator.destroy(),delete this.activator)),"showCustomTime"in t)throw new Error("Option `showCustomTime` is deprecated. Create a custom time bar via timeline.addCustomTime(time [, id])");this._initAutoResize()}if(this.components.forEach(function(e){return e.setOptions(t)}),"configure"in t){this.configurator||(this.configurator=this._createConfigurator()),this.configurator.setOptions(t.configure);var n=c.deepExtend({},this.options);this.components.forEach(function(t){c.deepExtend(n,t.options)}),this.configurator.setModuleOptions({global:n})}this._redraw()},n.prototype.isActive=function(){return!this.activator||this.activator.active},n.prototype.destroy=function(){this.setItems(null),this.setGroups(null),this.off(),this._stopAutoResize(),this.dom.root.parentNode&&this.dom.root.parentNode.removeChild(this.dom.root),this.dom=null,this.activator&&(this.activator.destroy(),delete this.activator);for(var t in this.listeners)this.listeners.hasOwnProperty(t)&&delete this.listeners[t];this.listeners=null,this.hammer=null,this.components.forEach(function(t){return t.destroy()}),this.body=null},n.prototype.setCustomTime=function(t,e){var i=this.customTimes.filter(function(t){return e===t.options.id});if(0===i.length)throw new Error("No custom time bar found with id "+(0,r.default)(e));i.length>0&&i[0].setCustomTime(t)},n.prototype.getCustomTime=function(t){var e=this.customTimes.filter(function(e){return e.options.id===t});if(0===e.length)throw new Error("No custom time bar found with id "+(0,r.default)(t));return e[0].getCustomTime()},n.prototype.setCustomTimeTitle=function(t,e){var i=this.customTimes.filter(function(t){return t.options.id===e});if(0===i.length)throw new Error("No custom time bar found with id "+(0,r.default)(e));if(i.length>0)return i[0].setCustomTitle(t)},n.prototype.getEventProperties=function(t){return{event:t}},n.prototype.addCustomTime=function(t,e){var i=void 0!==t?c.convert(t,"Date").valueOf():new Date,o=this.customTimes.some(function(t){return t.options.id===e});if(o)throw new Error("A custom time with id "+(0,r.default)(e)+" already exists");var n=new v(this.body,c.extend({},this.options,{time:i,id:e}));return this.customTimes.push(n),this.components.push(n),this._redraw(),e},n.prototype.removeCustomTime=function(t){var e=this.customTimes.filter(function(e){return e.options.id===t});if(0===e.length)throw new Error("No custom time bar found with id "+(0,r.default)(t));e.forEach(function(t){this.customTimes.splice(this.customTimes.indexOf(t),1),this.components.splice(this.components.indexOf(t),1),t.destroy()}.bind(this))},n.prototype.getVisibleItems=function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]},n.prototype.fit=function(t){var e=this.getDataRange();if(null!==e.min||null!==e.max){var i=e.max-e.min,o=new Date(e.min.valueOf()-.01*i),n=new Date(e.max.valueOf()+.01*i),s=!t||void 0===t.animation||t.animation;this.range.setRange(o,n,s)}},n.prototype.getDataRange=function(){throw new Error("Cannot invoke abstract method getDataRange")},n.prototype.setWindow=function(t,e,i){var o;if(1==arguments.length){var n=arguments[0];o=void 0===n.animation||n.animation,this.range.setRange(n.start,n.end,o)}else o=!i||void 0===i.animation||i.animation,this.range.setRange(t,e,o)},n.prototype.moveTo=function(t,e){var i=this.range.end-this.range.start,o=c.convert(t,"Date").valueOf(),n=o-i/2,s=o+i/2,r=!e||void 0===e.animation||e.animation;this.range.setRange(n,s,r)},n.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},n.prototype.zoomIn=function(t){if(!(!t||t<0||t>1)){var e=this.getWindow(),i=e.start.valueOf(),o=e.end.valueOf(),n=o-i,s=n/(1+t),r=(n-s)/2,a=i+r,h=o-r;this.setWindow({start:a,end:h})}},n.prototype.zoomOut=function(t){if(!(!t||t<0||t>1)){var e=this.getWindow(),i=e.start.valueOf(),o=e.end.valueOf(),n=o-i,s=i-n*t/2,r=o+n*t/2;this.setWindow({start:s,end:r})}},n.prototype.redraw=function(){this._redraw()},n.prototype._redraw=function(){this.redrawCount++;var t=!1,e=this.options,i=this.props,o=this.dom;if(o&&o.container&&0!=o.root.offsetWidth){m.updateHiddenDates(this.options.moment,this.body,this.options.hiddenDates),"top"==e.orientation?(c.addClassName(o.root,"vis-top"),c.removeClassName(o.root,"vis-bottom")):(c.removeClassName(o.root,"vis-top"),c.addClassName(o.root,"vis-bottom")),o.root.style.maxHeight=c.option.asSize(e.maxHeight,""),o.root.style.minHeight=c.option.asSize(e.minHeight,""),o.root.style.width=c.option.asSize(e.width,""),i.border.left=(o.centerContainer.offsetWidth-o.centerContainer.clientWidth)/2,i.border.right=i.border.left,i.border.top=(o.centerContainer.offsetHeight-o.centerContainer.clientHeight)/2,i.border.bottom=i.border.top,i.borderRootHeight=o.root.offsetHeight-o.root.clientHeight,i.borderRootWidth=o.root.offsetWidth-o.root.clientWidth,0===o.centerContainer.clientHeight&&(i.border.left=i.border.top,i.border.right=i.border.left),0===o.root.clientHeight&&(i.borderRootWidth=i.borderRootHeight),i.center.height=o.center.offsetHeight,i.left.height=o.left.offsetHeight,i.right.height=o.right.offsetHeight,i.top.height=o.top.clientHeight||-i.border.top,i.bottom.height=o.bottom.clientHeight||-i.border.bottom;var n=Math.max(i.left.height,i.center.height,i.right.height),s=i.top.height+n+i.bottom.height+i.borderRootHeight+i.border.top+i.border.bottom;o.root.style.height=c.option.asSize(e.height,s+"px"),i.root.height=o.root.offsetHeight,i.background.height=i.root.height-i.borderRootHeight;var r=i.root.height-i.top.height-i.bottom.height-i.borderRootHeight;i.centerContainer.height=r,i.leftContainer.height=r,i.rightContainer.height=i.leftContainer.height,i.root.width=o.root.offsetWidth,i.background.width=i.root.width-i.borderRootWidth,this.initialDrawDone||(i.scrollbarWidth=c.getScrollBarWidth()),e.verticalScroll?e.rtl?(i.left.width=o.leftContainer.clientWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth+i.scrollbarWidth||-i.border.right):(i.left.width=o.leftContainer.clientWidth+i.scrollbarWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth||-i.border.right):(i.left.width=o.leftContainer.clientWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth||-i.border.right),this._setDOM();var a=this._updateScrollTop();"top"!=e.orientation.item&&(a+=Math.max(i.centerContainer.height-i.center.height-i.border.top-i.border.bottom,0)),o.center.style.top=a+"px";var h=0==i.scrollTop?"hidden":"",d=i.scrollTop==i.scrollTopMin?"hidden":"";o.shadowTop.style.visibility=h,o.shadowBottom.style.visibility=d,o.shadowTopLeft.style.visibility=h,o.shadowBottomLeft.style.visibility=d,o.shadowTopRight.style.visibility=h,o.shadowBottomRight.style.visibility=d,e.verticalScroll&&(o.rightContainer.className="vis-panel vis-right vis-vertical-scroll",o.leftContainer.className="vis-panel vis-left vis-vertical-scroll",o.shadowTopRight.style.visibility="hidden",o.shadowBottomRight.style.visibility="hidden",o.shadowTopLeft.style.visibility="hidden",o.shadowBottomLeft.style.visibility="hidden",o.left.style.top="0px",o.right.style.top="0px"),(!e.verticalScroll||i.center.height<i.centerContainer.height)&&(o.left.style.top=a+"px",o.right.style.top=a+"px",o.rightContainer.className=o.rightContainer.className.replace(new RegExp("(?:^|\\s)vis-vertical-scroll(?:\\s|$)")," "),o.leftContainer.className=o.leftContainer.className.replace(new RegExp("(?:^|\\s)vis-vertical-scroll(?:\\s|$)")," "),i.left.width=o.leftContainer.clientWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth||-i.border.right,this._setDOM());var u=i.center.height>i.centerContainer.height;this.hammer.get("pan").set({direction:u?l.DIRECTION_ALL:l.DIRECTION_HORIZONTAL}),this.components.forEach(function(e){t=e.redraw()||t});var p=5;if(t){if(this.redrawCount<p)return void this.body.emitter.emit("_change");console.log("WARNING: infinite loop in redraw?")}else this.redrawCount=0;this.initialDrawDone=!0,this.body.emitter.emit("changed")}},n.prototype._setDOM=function(){var t=this.props,e=this.dom;t.leftContainer.width=t.left.width,t.rightContainer.width=t.right.width;var i=t.root.width-t.left.width-t.right.width-t.borderRootWidth;t.center.width=i,t.centerContainer.width=i,t.top.width=i,t.bottom.width=i,e.background.style.height=t.background.height+"px",e.backgroundVertical.style.height=t.background.height+"px",e.backgroundHorizontal.style.height=t.centerContainer.height+"px",e.centerContainer.style.height=t.centerContainer.height+"px",e.leftContainer.style.height=t.leftContainer.height+"px",e.rightContainer.style.height=t.rightContainer.height+"px",e.background.style.width=t.background.width+"px",e.backgroundVertical.style.width=t.centerContainer.width+"px",e.backgroundHorizontal.style.width=t.background.width+"px",e.centerContainer.style.width=t.center.width+"px",e.top.style.width=t.top.width+"px",e.bottom.style.width=t.bottom.width+"px",e.background.style.left="0",e.background.style.top="0",e.backgroundVertical.style.left=t.left.width+t.border.left+"px",e.backgroundVertical.style.top="0",e.backgroundHorizontal.style.left="0",e.backgroundHorizontal.style.top=t.top.height+"px",e.centerContainer.style.left=t.left.width+"px",e.centerContainer.style.top=t.top.height+"px",e.leftContainer.style.left="0",e.leftContainer.style.top=t.top.height+"px",e.rightContainer.style.left=t.left.width+t.center.width+"px",e.rightContainer.style.top=t.top.height+"px",e.top.style.left=t.left.width+"px",e.top.style.top="0",e.bottom.style.left=t.left.width+"px",e.bottom.style.top=t.top.height+t.centerContainer.height+"px",e.center.style.left="0",e.left.style.left="0",e.right.style.left="0"},n.prototype.repaint=function(){throw new Error("Function repaint is deprecated. Use redraw instead.")},n.prototype.setCurrentTime=function(t){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");this.currentTime.setCurrentTime(t)},n.prototype.getCurrentTime=function(){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");return this.currentTime.getCurrentTime()},n.prototype._toTime=function(t){return m.toTime(this,t,this.props.center.width)},n.prototype._toGlobalTime=function(t){return m.toTime(this,t,this.props.root.width)},n.prototype._toScreen=function(t){return m.toScreen(this,t,this.props.center.width)},n.prototype._toGlobalScreen=function(t){return m.toScreen(this,t,this.props.root.width)},n.prototype._initAutoResize=function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()},n.prototype._startAutoResize=function(){var t=this;this._stopAutoResize(),this._onResize=function(){return 1!=t.options.autoResize?void t._stopAutoResize():void(t.dom.root&&(t.dom.root.offsetWidth==t.props.lastWidth&&t.dom.root.offsetHeight==t.props.lastHeight||(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight,t.props.scrollbarWidth=c.getScrollBarWidth(),t.body.emitter.emit("_change"))))},c.addEventListener(window,"resize",this._onResize),t.dom.root&&(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight),this.watchTimer=setInterval(this._onResize,1e3)},n.prototype._stopAutoResize=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),this._onResize&&(c.removeEventListener(window,"resize",this._onResize),this._onResize=null)},n.prototype._onTouch=function(t){this.touch.allowDragging=!0,this.touch.initialScrollTop=this.props.scrollTop},n.prototype._onPinch=function(t){this.touch.allowDragging=!1},n.prototype._onDrag=function(t){if(t&&this.touch.allowDragging){var e=t.deltaY,i=this._getScrollTop(),o=this._setScrollTop(this.touch.initialScrollTop+e);this.options.verticalScroll&&(this.dom.left.parentNode.scrollTop=-this.props.scrollTop,this.dom.right.parentNode.scrollTop=-this.props.scrollTop),o!=i&&this.emit("verticalDrag")}},n.prototype._setScrollTop=function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop},n.prototype._updateScrollTop=function(){var t=Math.min(this.props.centerContainer.height-this.props.center.height,0);return t!=this.props.scrollTopMin&&("top"!=this.options.orientation.item&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTop<t&&(this.props.scrollTop=t),this.options.verticalScroll&&(this.dom.left.parentNode.scrollTop=-this.props.scrollTop,this.dom.right.parentNode.scrollTop=-this.props.scrollTop),this.props.scrollTop},n.prototype._getScrollTop=function(){return this.props.scrollTop},n.prototype._createConfigurator=function(){throw new Error("Cannot invoke abstract method _createConfigurator")},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){this.body=t,this.defaultOptions={type:null,orientation:{item:"bottom"},align:"auto",stack:!0,stackSubgroups:!0,groupOrderSwap:function(t,e,i){var o=e.order;e.order=t.order,t.order=o},groupOrder:"order",selectable:!0,multiselect:!1,itemsAlwaysDraggable:!1,editable:{updateTime:!1,updateGroup:!1,add:!1,remove:!1,overrideItems:!1},groupEditable:{order:!1,add:!1,remove:!1},snap:m.snap,onAdd:function(t,e){e(t)},onUpdate:function(t,e){e(t)},onMove:function(t,e){e(t)},onRemove:function(t,e){e(t)},onMoving:function(t,e){e(t)},onAddGroup:function(t,e){e(t)},onMoveGroup:function(t,e){e(t)},onRemoveGroup:function(t,e){e(t)},margin:{item:{horizontal:10,vertical:10},axis:20},tooltip:{followMouse:!1,overflowMethod:"flip"},tooltipOnItemUpdateTime:!1},this.options=c.extend({},this.defaultOptions),this.options.rtl=e.rtl,this.itemOptions={type:{start:"Date",end:"Date"}},this.conversion={toScreen:t.util.toScreen,toTime:t.util.toTime},this.dom={},this.props={},this.hammer=null;var i=this;this.itemsData=null,this.groupsData=null,this.itemListeners={add:function(t,e,o){i._onAdd(e.items)},update:function(t,e,o){i._onUpdate(e.items)},remove:function(t,e,o){i._onRemove(e.items)}},this.groupListeners={add:function(t,e,o){i._onAddGroups(e.items)},update:function(t,e,o){i._onUpdateGroups(e.items)},remove:function(t,e,o){i._onRemoveGroups(e.items)}},this.items={},this.groups={},this.groupIds=[],this.selection=[],this.stackDirty=!0,this.touchParams={},this.groupTouchParams={},this._create(),this.setOptions(e)}var s=i(55),r=o(s),a=i(62),h=o(a),d=i(128),l=o(d),u=i(108),c=i(1),p=i(91),f=i(93),m=i(129),v=i(124),g=i(130),y=i(134),b=i(135),_=i(136),w=i(132),x=i(137),k="__ungrouped__",O="__background__";n.prototype=new v,n.types={background:x,box:b,range:w,point:_},n.prototype._create=function(){var t=document.createElement("div");t.className="vis-itemset",t["timeline-itemset"]=this,this.dom.frame=t;var e=document.createElement("div");e.className="vis-background",t.appendChild(e),this.dom.background=e;var i=document.createElement("div");i.className="vis-foreground",t.appendChild(i),this.dom.foreground=i;var o=document.createElement("div");o.className="vis-axis",this.dom.axis=o;var n=document.createElement("div");n.className="vis-labelset",this.dom.labelSet=n,this._updateUngrouped();var s=new y(O,null,this);s.show(),this.groups[O]=s,this.hammer=new u(this.body.dom.centerContainer),this.hammer.on("hammer.input",function(t){t.isFirst&&this._onTouch(t)}.bind(this)),this.hammer.on("panstart",this._onDragStart.bind(this)),this.hammer.on("panmove",this._onDrag.bind(this)),this.hammer.on("panend",this._onDragEnd.bind(this)),this.hammer.get("pan").set({threshold:5,direction:u.DIRECTION_HORIZONTAL}),this.hammer.on("tap",this._onSelectItem.bind(this)),this.hammer.on("press",this._onMultiSelectItem.bind(this)),this.hammer.on("doubletap",this._onAddItem.bind(this)),this.options.rtl?this.groupHammer=new u(this.body.dom.rightContainer):this.groupHammer=new u(this.body.dom.leftContainer),this.groupHammer.on("tap",this._onGroupClick.bind(this)),this.groupHammer.on("panstart",this._onGroupDragStart.bind(this)),this.groupHammer.on("panmove",this._onGroupDrag.bind(this)),this.groupHammer.on("panend",this._onGroupDragEnd.bind(this)),this.groupHammer.get("pan").set({threshold:5,direction:u.DIRECTION_VERTICAL}),this.body.dom.centerContainer.addEventListener("mouseover",this._onMouseOver.bind(this)),this.body.dom.centerContainer.addEventListener("mouseout",this._onMouseOut.bind(this)),this.body.dom.centerContainer.addEventListener("mousemove",this._onMouseMove.bind(this)),this.body.dom.centerContainer.addEventListener("contextmenu",this._onDragEnd.bind(this)),this.show()},n.prototype.setOptions=function(t){if(t){var e=["type","rtl","align","order","stack","stackSubgroups","selectable","multiselect","itemsAlwaysDraggable","multiselectPerGroup","groupOrder","dataAttributes","template","groupTemplate","visibleFrameTemplate","hide","snap","groupOrderSwap","tooltip","tooltipOnItemUpdateTime"];c.selectiveExtend(e,this.options,t),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.item="top"===t.orientation?"top":"bottom":"object"===(0,h.default)(t.orientation)&&"item"in t.orientation&&(this.options.orientation.item=t.orientation.item)),"margin"in t&&("number"==typeof t.margin?(this.options.margin.axis=t.margin,this.options.margin.item.horizontal=t.margin,this.options.margin.item.vertical=t.margin):"object"===(0,h.default)(t.margin)&&(c.selectiveExtend(["axis"],this.options.margin,t.margin),"item"in t.margin&&("number"==typeof t.margin.item?(this.options.margin.item.horizontal=t.margin.item,this.options.margin.item.vertical=t.margin.item):"object"===(0,h.default)(t.margin.item)&&c.selectiveExtend(["horizontal","vertical"],this.options.margin.item,t.margin.item)))),"editable"in t&&("boolean"==typeof t.editable?(this.options.editable.updateTime=t.editable,this.options.editable.updateGroup=t.editable,this.options.editable.add=t.editable,this.options.editable.remove=t.editable,this.options.editable.overrideItems=!1):"object"===(0,h.default)(t.editable)&&c.selectiveExtend(["updateTime","updateGroup","add","remove","overrideItems"],this.options.editable,t.editable)),"groupEditable"in t&&("boolean"==typeof t.groupEditable?(this.options.groupEditable.order=t.groupEditable,this.options.groupEditable.add=t.groupEditable,this.options.groupEditable.remove=t.groupEditable):"object"===(0,h.default)(t.groupEditable)&&c.selectiveExtend(["order","add","remove"],this.options.groupEditable,t.groupEditable));var i=function(e){var i=t[e];if(i){if(!(i instanceof Function))throw new Error("option "+e+" must be a function "+e+"(item, callback)");this.options[e]=i}}.bind(this);["onAdd","onUpdate","onRemove","onMove","onMoving","onAddGroup","onMoveGroup","onRemoveGroup"].forEach(i),this.markDirty()}},n.prototype.markDirty=function(t){this.groupIds=[],this.stackDirty=!0,t&&t.refreshItems&&c.forEach(this.items,function(t){t.dirty=!0,t.displayed&&t.redraw()})},n.prototype.destroy=function(){this.hide(),this.setItems(null),this.setGroups(null),this.hammer=null,this.body=null,this.conversion=null},n.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.axis.parentNode&&this.dom.axis.parentNode.removeChild(this.dom.axis),this.dom.labelSet.parentNode&&this.dom.labelSet.parentNode.removeChild(this.dom.labelSet)},n.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame),this.dom.axis.parentNode||this.body.dom.backgroundVertical.appendChild(this.dom.axis),this.dom.labelSet.parentNode||(this.options.rtl?this.body.dom.right.appendChild(this.dom.labelSet):this.body.dom.left.appendChild(this.dom.labelSet))},n.prototype.setSelection=function(t){var e,i,o,n;for(void 0==t&&(t=[]),Array.isArray(t)||(t=[t]),e=0,i=this.selection.length;e<i;e++)o=this.selection[e],n=this.items[o],n&&n.unselect();for(this.selection=[],e=0,i=t.length;e<i;e++)o=t[e],n=this.items[o],n&&(this.selection.push(o),n.select())},n.prototype.getSelection=function(){return this.selection.concat([])},n.prototype.getVisibleItems=function(){var t=this.body.range.getRange();if(this.options.rtl)var e=this.body.util.toScreen(t.start),i=this.body.util.toScreen(t.end);else var i=this.body.util.toScreen(t.start),e=this.body.util.toScreen(t.end);var o=[];for(var n in this.groups)if(this.groups.hasOwnProperty(n))for(var s=this.groups[n],r=s.visibleItems,a=0;a<r.length;a++){var h=r[a];this.options.rtl?h.right<i&&h.right+h.width>e&&o.push(h.id):h.left<e&&h.left+h.width>i&&o.push(h.id)}return o},n.prototype._deselect=function(t){for(var e=this.selection,i=0,o=e.length;i<o;i++)if(e[i]==t){e.splice(i,1);break}},n.prototype.redraw=function(){var t=this.options.margin,e=this.body.range,i=c.option.asSize,o=this.options,n=o.orientation.item,s=!1,r=this.dom.frame;this.props.top=this.body.domProps.top.height+this.body.domProps.border.top,this.options.rtl?this.props.right=this.body.domProps.right.width+this.body.domProps.border.right:this.props.left=this.body.domProps.left.width+this.body.domProps.border.left,r.className="vis-itemset",s=this._orderGroups()||s;var a=e.end-e.start,h=a!=this.lastVisibleInterval||this.props.width!=this.props.lastWidth;h&&(this.stackDirty=!0),this.lastVisibleInterval=a,this.props.lastWidth=this.props.width;var d=this.stackDirty,l=this._firstGroup(),u={item:t.item,axis:t.axis},p={item:t.item,axis:t.item.vertical/2},f=0,m=t.axis+t.item.vertical;return this.groups[O].redraw(e,p,d),c.forEach(this.groups,function(t){var i=t==l?u:p,o=t.redraw(e,i,d);s=o||s,f+=t.height}),f=Math.max(f,m),this.stackDirty=!1,r.style.height=i(f),this.props.width=r.offsetWidth,this.props.height=f,this.dom.axis.style.top=i("top"==n?this.body.domProps.top.height+this.body.domProps.border.top:this.body.domProps.top.height+this.body.domProps.centerContainer.height),this.options.rtl?this.dom.axis.style.right="0":this.dom.axis.style.left="0",this.initialItemSetDrawn=!0,s=this._isResized()||s},n.prototype._firstGroup=function(){var t="top"==this.options.orientation.item?0:this.groupIds.length-1,e=this.groupIds[t],i=this.groups[e]||this.groups[k];return i||null},n.prototype._updateUngrouped=function(){var t,e,i=this.groups[k];this.groups[O];if(this.groupsData){if(i){i.hide(),delete this.groups[k];for(e in this.items)if(this.items.hasOwnProperty(e)){t=this.items[e],t.parent&&t.parent.remove(t);var o=this._getGroupId(t.data),n=this.groups[o];n&&n.add(t)||t.hide()}}}else if(!i){var s=null,r=null;i=new g(s,r,this),this.groups[k]=i;for(e in this.items)this.items.hasOwnProperty(e)&&(t=this.items[e],i.add(t));i.show()}},n.prototype.getLabelSet=function(){return this.dom.labelSet},n.prototype.setItems=function(t){var e,i=this,o=this.itemsData;if(t){if(!(t instanceof p||t instanceof f))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(o&&(c.forEach(this.itemListeners,function(t,e){o.off(e,t)}),e=o.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;c.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e),this._updateUngrouped()}this.body.emitter.emit("_change",{queue:!0})},n.prototype.getItems=function(){return this.itemsData},n.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(c.forEach(this.groupListeners,function(t,e){i.groupsData.off(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof p||t instanceof f))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var o=this.groupsData;this.groupsData instanceof f&&(o=this.groupsData.getDataSet()),o.get().forEach(function(t){t.nestedGroups&&t.nestedGroups.forEach(function(e){var i=o.get(e);i.nestedInGroup=t.id,0==t.showNested&&(i.visible=!1),o.update(i)})});var n=this.id;c.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,n)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._updateUngrouped(),this._order(),this.body.emitter.emit("_change",{queue:!0})},n.prototype.getGroups=function(){return this.groupsData},n.prototype.removeItem=function(t){var e=this.itemsData.get(t),i=this.itemsData.getDataSet(),o=this.items[t];e&&this.options.onRemove(e,function(e){e&&(i.remove(t),o.popup&&(o.popup.destroy(),o.popup=null))})},n.prototype._getType=function(t){return t.type||this.options.type||(t.end?"range":"box")},n.prototype._getGroupId=function(t){var e=this._getType(t);return"background"==e&&void 0==t.group?O:this.groupsData?t.group:k},n.prototype._onUpdate=function(t){var e=this;t.forEach(function(t){var i,o=e.itemsData.get(t,e.itemOptions),s=e.items[t],r=o?e._getType(o):null,a=n.types[r];if(s&&(a&&s instanceof a?e._updateItem(s,o):(i=s.selected,e._removeItem(s),s=null)),!s&&o){if(!a)throw"rangeoverflow"==r?new TypeError('Item type "rangeoverflow" is deprecated. Use css styling instead: .vis-item.vis-range .vis-item-content {overflow: visible;}'):new TypeError('Unknown item type "'+r+'"');s=new a(o,e.conversion,e.options),s.id=t,e._addItem(s),i&&(this.selection.push(t),s.select())}}.bind(this)),this._order(),this.stackDirty=!0,this.body.emitter.emit("_change",{queue:!0})},n.prototype._onAdd=n.prototype._onUpdate,n.prototype._onRemove=function(t){var e=0,i=this;t.forEach(function(t){var o=i.items[t];o&&(e++,i._removeItem(o))}),e&&(this._order(),this.stackDirty=!0,this.body.emitter.emit("_change",{queue:!0}))},n.prototype._order=function(){c.forEach(this.groups,function(t){t.order()})},n.prototype._onUpdateGroups=function(t){this._onAddGroups(t)},n.prototype._onAddGroups=function(t){var e=this;t.forEach(function(t){var i=e.groupsData.get(t),o=e.groups[t];if(o)o.setData(i);else{if(t==k||t==O)throw new Error("Illegal group id. "+t+" is a reserved id.");var n=(0,r.default)(e.options);c.extend(n,{height:null}),o=new g(t,i,e),e.groups[t]=o;for(var s in e.items)if(e.items.hasOwnProperty(s)){var a=e.items[s];a.data.group==t&&o.add(a)}o.order(),o.show()}}),this.body.emitter.emit("_change",{queue:!0})},n.prototype._onRemoveGroups=function(t){var e=this.groups;t.forEach(function(t){var i=e[t];i&&(i.hide(),delete e[t])}),this.markDirty(),this.body.emitter.emit("_change",{queue:!0})},n.prototype._orderGroups=function(){if(this.groupsData){var t=this.groupsData.getIds({order:this.options.groupOrder});t=this._orderNestedGroups(t);var e=!c.equalArray(t,this.groupIds);
-if(e){var i=this.groups;t.forEach(function(t){i[t].hide()}),t.forEach(function(t){i[t].show()}),this.groupIds=t}return e}return!1},n.prototype._orderNestedGroups=function(t){var e=[];return t.forEach(function(t){var i=this.groupsData.get(t);if(i.nestedInGroup||e.push(t),i.nestedGroups){var o=this.groupsData.get({filter:function(e){return e.nestedInGroup==t}}),n=o.map(function(t){return t.id});e=e.concat(n)}},this),e},n.prototype._addItem=function(t){this.items[t.id]=t;var e=this._getGroupId(t.data),i=this.groups[e];i?i&&i.data&&i.data.showNested&&(t.groupShowing=!0):t.groupShowing=!1,i&&i.add(t)},n.prototype._updateItem=function(t,e){var i=t.data.group,o=t.data.subgroup;t.setData(e);var n=this._getGroupId(t.data),s=this.groups[n];if(s?s&&s.data&&s.data.showNested&&(t.groupShowing=!0):t.groupShowing=!1,i!=t.data.group||o!=t.data.subgroup){var r=this.groups[i];r&&r.remove(t),s&&s.add(t)}},n.prototype._removeItem=function(t){t.hide(),delete this.items[t.id];var e=this.selection.indexOf(t.id);e!=-1&&this.selection.splice(e,1),t.parent&&t.parent.remove(t)},n.prototype._constructByEndArray=function(t){for(var e=[],i=0;i<t.length;i++)t[i]instanceof w&&e.push(t[i]);return e},n.prototype._onTouch=function(t){this.touchParams.item=this.itemFromTarget(t),this.touchParams.dragLeftItem=t.target.dragLeftItem||!1,this.touchParams.dragRightItem=t.target.dragRightItem||!1,this.touchParams.itemProps=null},n.prototype._getGroupIndex=function(t){for(var e=0;e<this.groupIds.length;e++)if(t==this.groupIds[e])return e},n.prototype._onDragStart=function(t){if(!this.touchParams.itemIsDragging){var e,i=this.touchParams.item||null,o=this;if(i&&(i.selected||this.options.itemsAlwaysDraggable)){if(this.options.editable.overrideItems&&!this.options.editable.updateTime&&!this.options.editable.updateGroup)return;if(null!=i.editable&&!i.editable.updateTime&&!i.editable.updateGroup&&!this.options.editable.overrideItems)return;var n=this.touchParams.dragLeftItem,s=this.touchParams.dragRightItem;if(this.touchParams.itemIsDragging=!0,this.touchParams.selectedItem=i,n)e={item:n,initialX:t.center.x,dragLeft:!0,data:this._cloneItemData(i.data)},this.touchParams.itemProps=[e];else if(s)e={item:s,initialX:t.center.x,dragRight:!0,data:this._cloneItemData(i.data)},this.touchParams.itemProps=[e];else{var r=this._getGroupIndex(i.data.group),a=this.options.itemsAlwaysDraggable&&!i.selected?[i.id]:this.getSelection();this.touchParams.itemProps=a.map(function(e){var i=o.items[e],n=o._getGroupIndex(i.data.group);return{item:i,initialX:t.center.x,groupOffset:r-n,data:this._cloneItemData(i.data)}}.bind(this))}t.stopPropagation()}else this.options.editable.add&&(t.srcEvent.ctrlKey||t.srcEvent.metaKey)&&this._onDragStartAddItem(t)}},n.prototype._onDragStartAddItem=function(t){var e=this.options.snap||null;if(this.options.rtl)var i=c.getAbsoluteRight(this.dom.frame),o=i-t.center.x+10;else var i=c.getAbsoluteLeft(this.dom.frame),o=t.center.x-i-10;var n=this.body.util.toTime(o),s=this.body.util.getScale(),r=this.body.util.getStep(),a=e?e(n,s,r):n,h=a,d={type:"range",start:a,end:h,content:"new item"},l=c.randomUUID();d[this.itemsData._fieldId]=l;var u=this.groupFromTarget(t);u&&(d.group=u.groupId);var p=new w(d,this.conversion,this.options);p.id=l,p.data=this._cloneItemData(d),this._addItem(p),this.touchParams.selectedItem=p;var f={item:p,initialX:t.center.x,data:p.data};this.options.rtl?f.dragLeft=!0:f.dragRight=!0,this.touchParams.itemProps=[f],t.stopPropagation()},n.prototype._onDrag=function(t){if(this.touchParams.itemProps){t.stopPropagation();var e=this,i=this.options.snap||null;if(this.options.rtl)var o=this.body.dom.root.offsetLeft+this.body.domProps.right.width;else var o=this.body.dom.root.offsetLeft+this.body.domProps.left.width;var n=this.body.util.getScale(),s=this.body.util.getStep(),r=this.touchParams.selectedItem,a=(this.options.editable.overrideItems||null==r.editable)&&this.options.editable.updateGroup||!this.options.editable.overrideItems&&null!=r.editable&&r.editable.updateGroup,h=null;if(a&&r&&void 0!=r.data.group){var d=e.groupFromTarget(t);d&&(h=this._getGroupIndex(d.groupId))}this.touchParams.itemProps.forEach(function(d){var l=e.body.util.toTime(t.center.x-o),u=e.body.util.toTime(d.initialX-o);if(this.options.rtl)var p=-(l-u);else var p=l-u;var f=this._cloneItemData(d.item.data);if(null==d.item.editable||d.item.editable.updateTime||d.item.editable.updateGroup||e.options.editable.overrideItems){var m=(this.options.editable.overrideItems||null==r.editable)&&this.options.editable.updateTime||!this.options.editable.overrideItems&&null!=r.editable&&r.editable.updateTime;if(m)if(d.dragLeft){if(this.options.rtl){if(void 0!=f.end){var v=c.convert(d.data.end,"Date"),g=new Date(v.valueOf()+p);f.end=i?i(g,n,s):g}}else if(void 0!=f.start){var y=c.convert(d.data.start,"Date"),b=new Date(y.valueOf()+p);f.start=i?i(b,n,s):b}}else if(d.dragRight){if(this.options.rtl){if(void 0!=f.start){var y=c.convert(d.data.start,"Date"),b=new Date(y.valueOf()+p);f.start=i?i(b,n,s):b}}else if(void 0!=f.end){var v=c.convert(d.data.end,"Date"),g=new Date(v.valueOf()+p);f.end=i?i(g,n,s):g}}else if(void 0!=f.start){var y=c.convert(d.data.start,"Date").valueOf(),b=new Date(y+p);if(void 0!=f.end){var v=c.convert(d.data.end,"Date"),_=v.valueOf()-y.valueOf();f.start=i?i(b,n,s):b,f.end=new Date(f.start.valueOf()+_)}else f.start=i?i(b,n,s):b}if(a&&!d.dragLeft&&!d.dragRight&&null!=h&&void 0!=f.group){var w=h-d.groupOffset;w=Math.max(0,w),w=Math.min(e.groupIds.length-1,w),f.group=e.groupIds[w]}f=this._cloneItemData(f),e.options.onMoving(f,function(t){t&&d.item.setData(this._cloneItemData(t,"Date"))}.bind(this))}}.bind(this)),this.stackDirty=!0,this.body.emitter.emit("_change")}},n.prototype._moveToGroup=function(t,e){var i=this.groups[e];if(i&&i.groupId!=t.data.group){var o=t.parent;o.remove(t),o.order(),i.add(t),i.order(),t.data.group=i.groupId}},n.prototype._onDragEnd=function(t){if(this.touchParams.itemIsDragging=!1,this.touchParams.itemProps){t.stopPropagation();var e=this,i=this.itemsData.getDataSet(),o=this.touchParams.itemProps;this.touchParams.itemProps=null,o.forEach(function(t){var o=t.item.id,n=null!=e.itemsData.get(o,e.itemOptions);if(n){var s=this._cloneItemData(t.item.data);e.options.onMove(s,function(n){n?(n[i._fieldId]=o,i.update(n)):(t.item.setData(t.data),e.stackDirty=!0,e.body.emitter.emit("_change"))})}else e.options.onAdd(t.item.data,function(i){e._removeItem(t.item),i&&e.itemsData.getDataSet().add(i),e.stackDirty=!0,e.body.emitter.emit("_change")})}.bind(this))}},n.prototype._onGroupClick=function(t){var e=this.groupFromTarget(t);if(e.nestedGroups){var i=this.groupsData;this.groupsData instanceof f&&(i=this.groupsData.getDataSet()),e.showNested=!e.showNested;var o=i.get(e.nestedGroups).map(function(t){return void 0==t.visible&&(t.visible=!0),t.visible=!!e.showNested,t});if(i.update(o),e.showNested)c.removeClassName(e.dom.label,"collapsed"),c.addClassName(e.dom.label,"expanded");else{c.removeClassName(e.dom.label,"expanded");var n=this.options.rtl?"collapsed-rtl":"collapsed";c.addClassName(e.dom.label,n)}}},n.prototype._onGroupDragStart=function(t){this.options.groupEditable.order&&(this.groupTouchParams.group=this.groupFromTarget(t),this.groupTouchParams.group&&(t.stopPropagation(),this.groupTouchParams.originalOrder=this.groupsData.getIds({order:this.options.groupOrder})))},n.prototype._onGroupDrag=function(t){if(this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this.groupsData;this.groupsData instanceof f&&(e=this.groupsData.getDataSet());var i=this.groupFromTarget(t);if(i&&i.height!=this.groupTouchParams.group.height){var o=i.top<this.groupTouchParams.group.top,n=t.center?t.center.y:t.clientY,s=c.getAbsoluteTop(i.dom.foreground),r=this.groupTouchParams.group.height;if(o){if(s+r<n)return}else{var a=i.height;if(s+a-r>n)return}}if(i&&i!=this.groupTouchParams.group){var h=e.get(i.groupId),d=e.get(this.groupTouchParams.group.groupId);d&&h&&(this.options.groupOrderSwap(d,h,e),e.update(d),e.update(h));var l=e.getIds({order:this.options.groupOrder});if(!c.equalArray(l,this.groupTouchParams.originalOrder))for(var u=this.groupTouchParams.originalOrder,p=this.groupTouchParams.group.groupId,m=Math.min(u.length,l.length),v=0,g=0,y=0;v<m;){for(;v+g<m&&v+y<m&&l[v+g]==u[v+y];)v++;if(v+g>=m)break;if(l[v+g]!=p)if(u[v+y]!=p){var b=l.indexOf(u[v+y]),_=e.get(l[v+g]),w=e.get(u[v+y]);this.options.groupOrderSwap(_,w,e),e.update(_),e.update(w);var x=l[v+g];l[v+g]=u[v+y],l[b]=x,v++}else y=1;else g=1}}}},n.prototype._onGroupDragEnd=function(t){if(this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this,i=e.groupTouchParams.group.groupId,o=e.groupsData.getDataSet(),n=c.extend({},o.get(i));e.options.onMoveGroup(n,function(t){if(t)t[o._fieldId]=i,o.update(t);else{var n=o.getIds({order:e.options.groupOrder});if(!c.equalArray(n,e.groupTouchParams.originalOrder))for(var s=e.groupTouchParams.originalOrder,r=Math.min(s.length,n.length),a=0;a<r;){for(;a<r&&n[a]==s[a];)a++;if(a>=r)break;var h=n.indexOf(s[a]),d=o.get(n[a]),l=o.get(s[a]);e.options.groupOrderSwap(d,l,o),groupsData.update(d),groupsData.update(l);var u=n[a];n[a]=s[a],n[h]=u,a++}}}),e.body.emitter.emit("groupDragged",{groupId:i})}},n.prototype._onSelectItem=function(t){if(this.options.selectable){var e=t.srcEvent&&(t.srcEvent.ctrlKey||t.srcEvent.metaKey),i=t.srcEvent&&t.srcEvent.shiftKey;if(e||i)return void this._onMultiSelectItem(t);var o=this.getSelection(),n=this.itemFromTarget(t),s=n?[n.id]:[];this.setSelection(s);var r=this.getSelection();(r.length>0||o.length>0)&&this.body.emitter.emit("select",{items:r,event:c.elementsCensor(t)})}},n.prototype._onMouseOver=function(t){var e=this.itemFromTarget(t);if(e){var i=this.itemFromRelatedTarget(t);if(e!==i){if(e.getTitle()){null==e.popup&&e.setPopup(new l.default(this.body.dom.root,this.options.tooltip.overflowMethod||"flip"));var o=this.body.dom.centerContainer;e.popup.setPosition(t.clientX-c.getAbsoluteLeft(o)+o.offsetLeft,t.clientY-c.getAbsoluteTop(o)+o.offsetTop),e.popup.show()}this.body.emitter.emit("itemover",{item:e.id,event:c.elementsCensor(t)})}}},n.prototype._onMouseOut=function(t){var e=this.itemFromTarget(t);if(e){var i=this.itemFromRelatedTarget(t);e!==i&&(null!=e.popup&&e.popup.hide(),this.body.emitter.emit("itemout",{item:e.id,event:c.elementsCensor(t)}))}},n.prototype._onMouseMove=function(t){var e=this.itemFromTarget(t);if(e&&this.options.tooltip.followMouse&&e.popup&&!e.popup.hidden){var i=this.body.dom.centerContainer;e.popup.setPosition(t.clientX-c.getAbsoluteLeft(i)+i.offsetLeft,t.clientY-c.getAbsoluteTop(i)+i.offsetTop),e.popup.show()}},n.prototype._onUpdateItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this;if(t){var i=e.itemsData.get(t.id);this.options.onUpdate(i,function(t){t&&e.itemsData.getDataSet().update(t)})}}},n.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this,i=this.options.snap||null,o=this.itemFromTarget(t);if(!o){if(this.options.rtl)var n=c.getAbsoluteRight(this.dom.frame),s=n-t.center.x;else var n=c.getAbsoluteLeft(this.dom.frame),s=t.center.x-n;var r=this.body.util.toTime(s),a=this.body.util.getScale(),h=this.body.util.getStep(),d={start:i?i(r,a,h):r,content:"new item"};if("drop"==t.type){var l=JSON.parse(t.dataTransfer.getData("text"));if(d.content=l.content,d.type=l.type||"box",d[this.itemsData._fieldId]=l.id||c.randomUUID(),"range"==l.type||l.end&&l.start)if(l.end)d.end=l.end,d.start=l.start;else{var u=this.body.util.toTime(s+this.props.width/5);d.end=i?i(u,a,h):u}}else if(d[this.itemsData._fieldId]=c.randomUUID(),"range"===this.options.type){var u=this.body.util.toTime(s+this.props.width/5);d.end=i?i(u,a,h):u}var p=this.groupFromTarget(t);p&&(d.group=p.groupId),d=this._cloneItemData(d),this.options.onAdd(d,function(i){i&&(e.itemsData.getDataSet().add(i),"drop"==t.type&&e.setSelection([i.id]))})}}},n.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e=this.itemFromTarget(t);if(e){var i=this.options.multiselect?this.getSelection():[],o=t.srcEvent&&t.srcEvent.shiftKey||!1;if(o&&this.options.multiselect){var s=this.itemsData.get(e.id).group,r=void 0;this.options.multiselectPerGroup&&i.length>0&&(r=this.itemsData.get(i[0]).group),this.options.multiselectPerGroup&&void 0!=r&&r!=s||i.push(e.id);var a=n._getItemRange(this.itemsData.get(i,this.itemOptions));if(!this.options.multiselectPerGroup||r==s){i=[];for(var h in this.items)if(this.items.hasOwnProperty(h)){var d=this.items[h],l=d.data.start,u=void 0!==d.data.end?d.data.end:l;!(l>=a.min&&u<=a.max)||this.options.multiselectPerGroup&&r!=this.itemsData.get(d.id).group||d instanceof x||i.push(d.id)}}}else{var p=i.indexOf(e.id);p==-1?i.push(e.id):i.splice(p,1)}this.setSelection(i),this.body.emitter.emit("select",{items:this.getSelection(),event:c.elementsCensor(t)})}}},n._getItemRange=function(t){var e=null,i=null;return t.forEach(function(t){(null==i||t.start<i)&&(i=t.start),void 0!=t.end?(null==e||t.end>e)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)}),{min:i,max:e}},n.prototype.itemFromElement=function(t){for(var e=t;e;){if(e.hasOwnProperty("timeline-item"))return e["timeline-item"];e=e.parentNode}return null},n.prototype.itemFromTarget=function(t){return this.itemFromElement(t.target)},n.prototype.itemFromRelatedTarget=function(t){return this.itemFromElement(t.relatedTarget)},n.prototype.groupFromTarget=function(t){for(var e=t.center?t.center.y:t.clientY,i=0;i<this.groupIds.length;i++){var o=this.groupIds[i],n=this.groups[o],s=n.dom.foreground,r=c.getAbsoluteTop(s);if(e>r&&e<r+s.offsetHeight)return n;if("top"===this.options.orientation.item){if(i===this.groupIds.length-1&&e>r)return n}else if(0===i&&e<r+s.offset)return n}return null},n.itemSetFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-itemset"))return e["timeline-itemset"];e=e.parentNode}return null},n.prototype._cloneItemData=function(t,e){var i=c.extend({},t);return e||(e=this.itemsData.getDataSet()._options.type),void 0!=i.start&&(i.start=c.convert(i.start,e&&e.start||"Date")),void 0!=i.end&&(i.end=c.convert(i.end,e&&e.end||"Date")),i},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i){(0,s.default)(this,t),this.container=e,this.overflowMethod=i||"cap",this.x=0,this.y=0,this.padding=5,this.hidden=!1,this.frame=document.createElement("div"),this.frame.className="vis-tooltip",this.container.appendChild(this.frame)}return(0,a.default)(t,[{key:"setPosition",value:function(t,e){this.x=parseInt(t),this.y=parseInt(e)}},{key:"setText",value:function(t){t instanceof Element?(this.frame.innerHTML="",this.frame.appendChild(t)):this.frame.innerHTML=t}},{key:"show",value:function(t){if(void 0===t&&(t=!0),t===!0){var e=this.frame.clientHeight,i=this.frame.clientWidth,o=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,s=0,r=0;if("flip"==this.overflowMethod){var a=!1,h=!0;this.y-e<this.padding&&(h=!1),this.x+i>n-this.padding&&(a=!0),s=a?this.x-i:this.x,r=h?this.y-e:this.y}else r=this.y-e,r+e+this.padding>o&&(r=o-e-this.padding),r<this.padding&&(r=this.padding),s=this.x,s+i+this.padding>n&&(s=n-i-this.padding),s<this.padding&&(s=this.padding);this.frame.style.left=s+"px",this.frame.style.top=r+"px",this.frame.style.visibility="visible",this.hidden=!1}else this.hide()}},{key:"hide",value:function(){this.hidden=!0,this.frame.style.visibility="hidden"}},{key:"destroy",value:function(){this.frame.parentNode.removeChild(this.frame)}}]),t}();e.default=h},function(t,e,i){function o(t,e,i,s){this.moment=n,this.current=this.moment(),this._start=this.moment(),this._end=this.moment(),this.autoScale=!0,this.scale="day",this.step=1,this.setRange(t,e,i),this.switchedDay=!1,this.switchedMonth=!1,this.switchedYear=!1,Array.isArray(s)?this.hiddenDates=s:void 0!=s?this.hiddenDates=[s]:this.hiddenDates=[],this.format=o.FORMAT}var n=i(84),s=i(125),r=i(1);o.FORMAT={minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",month:"YYYY",year:""}},o.prototype.setMoment=function(t){this.moment=t,this.current=this.moment(this.current.valueOf()),this._start=this.moment(this._start.valueOf()),this._end=this.moment(this._end.valueOf())},o.prototype.setFormat=function(t){var e=r.deepExtend({},o.FORMAT);this.format=r.deepExtend(e,t)},o.prototype.setRange=function(t,e,i){if(!(t instanceof Date&&e instanceof Date))throw"No legal start or end date in method setRange";this._start=void 0!=t?this.moment(t.valueOf()):new Date,this._end=void 0!=e?this.moment(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i)},o.prototype.start=function(){this.current=this._start.clone(),this.roundToMinor()},o.prototype.roundToMinor=function(){switch(this.scale){case"year":this.current.year(this.step*Math.floor(this.current.year()/this.step)),this.current.month(0);case"month":this.current.date(1);case"day":case"weekday":this.current.hours(0);case"hour":this.current.minutes(0);case"minute":this.current.seconds(0);case"second":this.current.milliseconds(0)}if(1!=this.step)switch(this.scale){case"millisecond":this.current.subtract(this.current.milliseconds()%this.step,"milliseconds");break;case"second":this.current.subtract(this.current.seconds()%this.step,"seconds");break;case"minute":this.current.subtract(this.current.minutes()%this.step,"minutes");break;case"hour":this.current.subtract(this.current.hours()%this.step,"hours");break;case"weekday":case"day":this.current.subtract((this.current.date()-1)%this.step,"day");break;case"month":this.current.subtract(this.current.month()%this.step,"month");break;case"year":this.current.subtract(this.current.year()%this.step,"year")}},o.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},o.prototype.next=function(){var t=this.current.valueOf();if(this.current.month()<6)switch(this.scale){case"millisecond":this.current.add(this.step,"millisecond");break;case"second":this.current.add(this.step,"second");break;case"minute":this.current.add(this.step,"minute");break;case"hour":this.current.add(this.step,"hour"),this.current.subtract(this.current.hours()%this.step,"hour");break;case"weekday":case"day":this.current.add(this.step,"day");break;case"month":this.current.add(this.step,"month");break;case"year":this.current.add(this.step,"year")}else switch(this.scale){case"millisecond":this.current.add(this.step,"millisecond");break;case"second":this.current.add(this.step,"second");break;case"minute":this.current.add(this.step,"minute");break;case"hour":this.current.add(this.moment.duration(this.step,"hour")),this.current.hours()%this.step!==0&&this.current.add(this.step-this.current.hours()%this.step,"hour");break;case"weekday":case"day":this.current.add(this.step,"day");break;case"month":this.current.add(this.step,"month");break;case"year":this.current.add(this.step,"year")}if(1!=this.step)switch(this.scale){case"millisecond":this.current.milliseconds()>0&&this.current.milliseconds()<this.step&&this.current.milliseconds(0);break;case"second":this.current.seconds()>0&&this.current.seconds()<this.step&&this.current.seconds(0);break;case"minute":this.current.minutes()>0&&this.current.minutes()<this.step&&this.current.minutes(0);break;case"hour":this.current.hours()>0&&this.current.hours()<this.step&&this.current.hours(0);break;case"weekday":case"day":this.current.date()<this.step+1&&this.current.date(1);break;case"month":this.current.month()<this.step&&this.current.month(0);break;case"year":}this.current.valueOf()==t&&(this.current=this._end.clone()),this.switchedDay=!1,this.switchedMonth=!1,this.switchedYear=!1,s.stepOverHiddenDates(this.moment,this,t)},o.prototype.getCurrent=function(){return this.current},o.prototype.setScale=function(t){t&&"string"==typeof t.scale&&(this.scale=t.scale,this.step=t.step>0?t.step:1,this.autoScale=!1)},o.prototype.setAutoScale=function(t){this.autoScale=t},o.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,o=864e5,n=36e5,s=6e4,r=1e3,a=1;1e3*e>t&&(this.scale="year",this.step=1e3),500*e>t&&(this.scale="year",this.step=500),100*e>t&&(this.scale="year",this.step=100),50*e>t&&(this.scale="year",this.step=50),10*e>t&&(this.scale="year",this.step=10),5*e>t&&(this.scale="year",this.step=5),e>t&&(this.scale="year",this.step=1),3*i>t&&(this.scale="month",this.step=3),i>t&&(this.scale="month",this.step=1),5*o>t&&(this.scale="day",this.step=5),2*o>t&&(this.scale="day",this.step=2),o>t&&(this.scale="day",this.step=1),o/2>t&&(this.scale="weekday",this.step=1),4*n>t&&(this.scale="hour",this.step=4),n>t&&(this.scale="hour",this.step=1),15*s>t&&(this.scale="minute",this.step=15),10*s>t&&(this.scale="minute",this.step=10),5*s>t&&(this.scale="minute",this.step=5),s>t&&(this.scale="minute",this.step=1),15*r>t&&(this.scale="second",this.step=15),10*r>t&&(this.scale="second",this.step=10),5*r>t&&(this.scale="second",this.step=5),r>t&&(this.scale="second",this.step=1),200*a>t&&(this.scale="millisecond",this.step=200),100*a>t&&(this.scale="millisecond",this.step=100),50*a>t&&(this.scale="millisecond",this.step=50),10*a>t&&(this.scale="millisecond",this.step=10),5*a>t&&(this.scale="millisecond",this.step=5),a>t&&(this.scale="millisecond",this.step=1)}},o.snap=function(t,e,i){var o=n(t);if("year"==e){var s=o.year()+Math.round(o.month()/12);o.year(Math.round(s/i)*i),o.month(0),o.date(0),o.hours(0),o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("month"==e)o.date()>15?(o.date(1),o.add(1,"month")):o.date(1),o.hours(0),o.minutes(0),o.seconds(0),o.milliseconds(0);else if("day"==e){switch(i){case 5:case 2:o.hours(24*Math.round(o.hours()/24));break;default:o.hours(12*Math.round(o.hours()/12))}o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:o.hours(12*Math.round(o.hours()/12));break;default:o.hours(6*Math.round(o.hours()/6))}o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("hour"==e){switch(i){case 4:o.minutes(60*Math.round(o.minutes()/60));break;default:o.minutes(30*Math.round(o.minutes()/30))}o.seconds(0),o.milliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:o.minutes(5*Math.round(o.minutes()/5)),o.seconds(0);break;case 5:o.seconds(60*Math.round(o.seconds()/60));break;default:o.seconds(30*Math.round(o.seconds()/30))}o.milliseconds(0)}else if("second"==e)switch(i){case 15:case 10:o.seconds(5*Math.round(o.seconds()/5)),o.milliseconds(0);break;case 5:o.milliseconds(1e3*Math.round(o.milliseconds()/1e3));break;default:o.milliseconds(500*Math.round(o.milliseconds()/500))}else if("millisecond"==e){var r=i>5?i/2:1;o.milliseconds(Math.round(o.milliseconds()/r)*r)}return o},o.prototype.isMajor=function(){if(1==this.switchedYear)switch(this.scale){case"year":case"month":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.scale){case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}var t=this.moment(this.current);switch(this.scale){case"millisecond":return 0==t.milliseconds();case"second":return 0==t.seconds();case"minute":return 0==t.hours()&&0==t.minutes();case"hour":return 0==t.hours();case"weekday":case"day":return 1==t.date();case"month":return 0==t.month();case"year":return!1;default:return!1}},o.prototype.getLabelMinor=function(t){if(void 0==t&&(t=this.current),"function"==typeof this.format.minorLabels)return this.format.minorLabels(t,this.scale,this.step);var e=this.format.minorLabels[this.scale];return e&&e.length>0?this.moment(t).format(e):""},o.prototype.getLabelMajor=function(t){if(void 0==t&&(t=this.current),"function"==typeof this.format.majorLabels)return this.format.majorLabels(t,this.scale,this.step);var e=this.format.majorLabels[this.scale];return e&&e.length>0?this.moment(t).format(e):""},o.prototype.getClassName=function(){function t(t){return t/h%2==0?" vis-even":" vis-odd"}function e(t){return t.isSame(new Date,"day")?" vis-today":t.isSame(s().add(1,"day"),"day")?" vis-tomorrow":t.isSame(s().add(-1,"day"),"day")?" vis-yesterday":""}function i(t){return t.isSame(new Date,"week")?" vis-current-week":""}function o(t){return t.isSame(new Date,"month")?" vis-current-month":""}function n(t){return t.isSame(new Date,"year")?" vis-current-year":""}var s=this.moment,r=this.moment(this.current),a=r.locale?r.locale("en"):r.lang("en"),h=this.step;switch(this.scale){case"millisecond":return e(a)+t(a.milliseconds()).trim();case"second":return e(a)+t(a.seconds()).trim();case"minute":return e(a)+t(a.minutes()).trim();case"hour":return"vis-h"+a.hours()+(4==this.step?"-h"+(a.hours()+4):"")+e(a)+t(a.hours());case"weekday":return"vis-"+a.format("dddd").toLowerCase()+e(a)+i(a)+t(a.date());case"day":return"vis-day"+a.date()+" vis-"+a.format("MMMM").toLowerCase()+e(a)+o(a)+(this.step<=2?e(a):"")+(this.step<=2?" vis-"+a.format("dddd").toLowerCase():""+t(a.date()-1));case"month":return"vis-"+a.format("MMMM").toLowerCase()+o(a)+t(a.month());case"year":var d=a.year();return"vis-year"+d+n(a)+t(d);default:return""}},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i){this.groupId=t,this.subgroups={},this.subgroupIndex=0,this.subgroupOrderer=e&&e.subgroupOrder,this.itemSet=i,this.isVisible=null,e&&e.nestedGroups&&(this.nestedGroups=e.nestedGroups,0==e.showNested?this.showNested=!1:this.showNested=!0),this.nestedInGroup=null,this.dom={},this.props={label:{width:0,height:0}},this.className=null,this.items={},this.visibleItems=[],this.itemsInRange=[],this.orderedItems={byStart:[],byEnd:[]},this.checkRangedItems=!1;var o=this;this.itemSet.body.emitter.on("checkRangedItems",function(){o.checkRangedItems=!0}),this._create(),this.setData(e)}var s=i(58),r=o(s),a=i(1),h=i(131);i(132);n.prototype._create=function(){var t=document.createElement("div");this.itemSet.options.groupEditable.order?t.className="vis-label draggable":t.className="vis-label",this.dom.label=t;var e=document.createElement("div");e.className="vis-inner",t.appendChild(e),this.dom.inner=e;var i=document.createElement("div");i.className="vis-group",i["timeline-group"]=this,this.dom.foreground=i,this.dom.background=document.createElement("div"),this.dom.background.className="vis-group",this.dom.axis=document.createElement("div"),this.dom.axis.className="vis-group",this.dom.marker=document.createElement("div"),this.dom.marker.style.visibility="hidden",this.dom.marker.style.position="absolute",this.dom.marker.innerHTML="",this.dom.background.appendChild(this.dom.marker)},n.prototype.setData=function(t){var e,i;if(this.itemSet.options&&this.itemSet.options.groupTemplate?(i=this.itemSet.options.groupTemplate.bind(this),e=i(t,this.dom.inner)):e=t&&t.content,e instanceof Element){for(this.dom.inner.appendChild(e);this.dom.inner.firstChild;)this.dom.inner.removeChild(this.dom.inner.firstChild);this.dom.inner.appendChild(e)}else e instanceof Object?i(t,this.dom.inner):void 0!==e&&null!==e?this.dom.inner.innerHTML=e:this.dom.inner.innerHTML=this.groupId||"";if(this.dom.label.title=t&&t.title||"",this.dom.inner.firstChild?a.removeClassName(this.dom.inner,"vis-hidden"):a.addClassName(this.dom.inner,"vis-hidden"),t&&t.nestedGroups)if(0==t.showNested?this.showNested=!1:this.showNested=!0,a.addClassName(this.dom.label,"vis-nesting-group"),this.showNested)a.removeClassName(this.dom.label,"collapsed"),a.addClassName(this.dom.label,"expanded");else{a.removeClassName(this.dom.label,"expanded");var o=this.itemSet.options.rtl?"collapsed-rtl":"collapsed";a.addClassName(this.dom.label,o)}t&&t.nestedInGroup&&(a.addClassName(this.dom.label,"vis-nested-group"),this.itemSet.options&&this.itemSet.options.rtl?this.dom.inner.style.paddingRight="30px":this.dom.inner.style.paddingLeft="30px");var n=t&&t.className||null;n!=this.className&&(this.className&&(a.removeClassName(this.dom.label,this.className),a.removeClassName(this.dom.foreground,this.className),a.removeClassName(this.dom.background,this.className),a.removeClassName(this.dom.axis,this.className)),a.addClassName(this.dom.label,n),a.addClassName(this.dom.foreground,n),a.addClassName(this.dom.background,n),a.addClassName(this.dom.axis,n),this.className=n),this.style&&(a.removeCssText(this.dom.label,this.style),this.style=null),t&&t.style&&(a.addCssText(this.dom.label,t.style),this.style=t.style)},n.prototype.getLabelWidth=function(){return this.props.label.width},n.prototype.redraw=function(t,e,i){var o=!1,n=this.dom.marker.clientHeight;n!=this.lastMarkerHeight&&(this.lastMarkerHeight=n,a.forEach(this.items,function(t){t.dirty=!0,t.displayed&&t.redraw()}),i=!0),this._calculateSubGroupHeights(e);var s=this.dom.foreground;if(this.top=s.offsetTop,this.right=s.offsetLeft,this.width=s.offsetWidth,this.isVisible=this._isGroupVisible(t,e),"function"==typeof this.itemSet.options.order){if(i){var r=this,d=!1;a.forEach(this.items,function(t){t.displayed||(t.redraw(),r.visibleItems.push(t)),t.repositionX(d)});var l=this.orderedItems.byStart.slice().sort(function(t,e){return r.itemSet.options.order(t.data,e.data)});h.stack(l,e,!0)}this.visibleItems=this._updateItemsInRange(this.orderedItems,this.visibleItems,t)}else this.visibleItems=this._updateItemsInRange(this.orderedItems,this.visibleItems,t),this.itemSet.options.stack?h.stack(this.visibleItems,e,i):h.nostack(this.visibleItems,e,this.subgroups,this.itemSet.options.stackSubgroups);this._updateSubgroupsSizes();var u=this._calculateHeight(e),s=this.dom.foreground;this.top=s.offsetTop,this.right=s.offsetLeft,this.width=s.offsetWidth,o=a.updateProperty(this,"height",u)||o,o=a.updateProperty(this.props.label,"width",this.dom.inner.clientWidth)||o,o=a.updateProperty(this.props.label,"height",this.dom.inner.clientHeight)||o,this.dom.background.style.height=u+"px",this.dom.foreground.style.height=u+"px",this.dom.label.style.height=u+"px";for(var c=0,p=this.visibleItems.length;c<p;c++){var f=this.visibleItems[c];f.repositionY(e),this.isVisible||"__background__"==this.groupId||f.displayed&&f.hide()}return!this.isVisible&&this.height?o=!1:o},n.prototype._calculateSubGroupHeights=function(t){if((0,r.default)(this.subgroups).length>0){var e=this;this.resetSubgroups(),a.forEach(this.visibleItems,function(i){void 0!==i.data.subgroup&&(e.subgroups[i.data.subgroup].height=Math.max(e.subgroups[i.data.subgroup].height,i.height+t.item.vertical),e.subgroups[i.data.subgroup].visible=!0)})}},n.prototype._isGroupVisible=function(t,e){var i=this.top<=t.body.domProps.centerContainer.height-t.body.domProps.scrollTop+e.axis&&this.top+this.height+e.axis>=-t.body.domProps.scrollTop;return i},n.prototype._calculateHeight=function(t){var e,i=this.visibleItems;if(i.length>0){var o=i[0].top,n=i[0].top+i[0].height;if(a.forEach(i,function(t){o=Math.min(o,t.top),n=Math.max(n,t.top+t.height)}),o>t.axis){var s=o-t.axis;n-=s,a.forEach(i,function(t){t.top-=s})}e=n+t.item.vertical/2}else e=0;return e=Math.max(e,this.props.label.height)},n.prototype.show=function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)},n.prototype.hide=function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var o=this.dom.axis;o.parentNode&&o.parentNode.removeChild(o)},n.prototype.add=function(t){
-if(this.items[t.id]=t,t.setParent(this),void 0!==t.data.subgroup&&(void 0===this.subgroups[t.data.subgroup]&&(this.subgroups[t.data.subgroup]={height:0,top:0,start:t.data.start,end:t.data.end,visible:!1,index:this.subgroupIndex,items:[]},this.subgroupIndex++),new Date(t.data.start)<new Date(this.subgroups[t.data.subgroup].start)&&(this.subgroups[t.data.subgroup].start=t.data.start),new Date(t.data.end)>new Date(this.subgroups[t.data.subgroup].end)&&(this.subgroups[t.data.subgroup].end=t.data.end),this.subgroups[t.data.subgroup].items.push(t)),this.orderSubgroups(),this.visibleItems.indexOf(t)==-1){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},n.prototype._updateSubgroupsSizes=function(){var t=this;if(t.subgroups)for(var e in t.subgroups){var i=t.subgroups[e].items[0].data.start,o=t.subgroups[e].items[0].data.end;t.subgroups[e].items.forEach(function(t){new Date(t.data.start)<new Date(i)&&(i=t.data.start),new Date(t.data.end)>new Date(o)&&(o=t.data.end)}),t.subgroups[e].start=i,t.subgroups[e].end=o}},n.prototype.orderSubgroups=function(){if(void 0!==this.subgroupOrderer){var t=[];if("string"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push({subgroup:e,sortField:this.subgroups[e].items[0].data[this.subgroupOrderer]});t.sort(function(t,e){return t.sortField-e.sortField})}else if("function"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push(this.subgroups[e].items[0].data);t.sort(this.subgroupOrderer)}if(t.length>0)for(var i=0;i<t.length;i++)this.subgroups[t[i].subgroup].index=i}},n.prototype.resetSubgroups=function(){for(var t in this.subgroups)this.subgroups.hasOwnProperty(t)&&(this.subgroups[t].visible=!1)},n.prototype.remove=function(t){delete this.items[t.id],t.setParent(null);var e=this.visibleItems.indexOf(t);if(e!=-1&&this.visibleItems.splice(e,1),void 0!==t.data.subgroup){var i=this.subgroups[t.data.subgroup];if(i){var o=i.items.indexOf(t);i.items.splice(o,1),i.items.length?this._updateSubgroupsSizes():(delete this.subgroups[t.data.subgroup],this.subgroupIndex--),this.orderSubgroups()}}},n.prototype.removeFromDataSet=function(t){this.itemSet.removeItem(t.id)},n.prototype.order=function(){for(var t=a.toArray(this.items),e=[],i=[],o=0;o<t.length;o++)void 0!==t[o].data.end&&i.push(t[o]),e.push(t[o]);this.orderedItems={byStart:e,byEnd:i},h.orderByStart(this.orderedItems.byStart),h.orderByEnd(this.orderedItems.byEnd)},n.prototype._updateItemsInRange=function(t,e,i){var o=[],n={},s=(i.end-i.start)/4,r=i.start-s,h=i.end+s,d=function(t){return t<r?-1:t<=h?0:1};if(e.length>0)for(var l=0;l<e.length;l++)this._checkIfVisibleWithReference(e[l],o,n,i);var u=a.binarySearchCustom(t.byStart,d,"data","start");if(this._traceVisible(u,t.byStart,o,n,function(t){return t.data.start<r||t.data.start>h}),1==this.checkRangedItems)for(this.checkRangedItems=!1,l=0;l<t.byEnd.length;l++)this._checkIfVisibleWithReference(t.byEnd[l],o,n,i);else{var c=a.binarySearchCustom(t.byEnd,d,"data","end");this._traceVisible(c,t.byEnd,o,n,function(t){return t.data.end<r||t.data.end>h})}for(var l=0;l<o.length;l++){var p=o[l];p.displayed||p.show(),p.repositionX()}return o},n.prototype._traceVisible=function(t,e,i,o,n){if(t!=-1){for(var s=t;s>=0;s--){var r=e[s];if(n(r))break;void 0===o[r.id]&&(o[r.id]=!0,i.push(r))}for(var s=t+1;s<e.length;s++){var r=e[s];if(n(r))break;void 0===o[r.id]&&(o[r.id]=!0,i.push(r))}}},n.prototype._checkIfVisible=function(t,e,i){t.isVisible(i)?(t.displayed||t.show(),t.repositionX(),e.push(t)):t.displayed&&t.hide()},n.prototype._checkIfVisibleWithReference=function(t,e,i,o){t.isVisible(o)?void 0===i[t.id]&&(i[t.id]=!0,e.push(t)):t.displayed&&t.hide()},t.exports=n},function(t,e){var i=.001;e.orderByStart=function(t){t.sort(function(t,e){return t.data.start-e.data.start})},e.orderByEnd=function(t){t.sort(function(t,e){var i="end"in t.data?t.data.end:t.data.start,o="end"in e.data?e.data.end:e.data.start;return i-o})},e.stack=function(t,i,o){if(o)for(var n=0;n<t.length;n++)t[n].top=null;for(var n=0;n<t.length;n++){var s=t[n];if(s.stack&&null===s.top){s.top=i.axis;do{for(var r=null,a=0,h=t.length;a<h;a++){var d=t[a];if(null!==d.top&&d!==s&&d.stack&&e.collision(s,d,i.item,d.options.rtl)){r=d;break}}null!=r&&(s.top=r.top+r.height+i.item.vertical)}while(r)}}},e.nostack=function(t,i,o,n){for(var s=0;s<t.length;s++)if(void 0==t[s].data.subgroup)t[s].top=i.item.vertical;else if(void 0!==t[s].data.subgroup&&n){var r=0;for(var a in o)o.hasOwnProperty(a)&&1==o[a].visible&&o[a].index<o[t[s].data.subgroup].index&&(r+=o[a].height,o[t[s].data.subgroup].top=r);t[s].top=r+.5*i.item.vertical}n||e.stackSubgroups(t,i,o)},e.stackSubgroups=function(t,i,o){for(var n in o)if(o.hasOwnProperty(n)){o[n].top=0;do{var s=null;for(var r in o)if(null!==o[r].top&&r!==n&&o[n].index>o[r].index&&e.collisionByTimes(o[n],o[r])){s=o[r];break}null!=s&&(o[n].top=s.top+s.height)}while(s)}for(var a=0;a<t.length;a++)void 0!==t[a].data.subgroup&&(t[a].top=o[t[a].data.subgroup].top+.5*i.item.vertical)},e.collision=function(t,e,o,n){return n?t.right-o.horizontal+i<e.right+e.width&&t.right+t.width+o.horizontal-i>e.right&&t.top-o.vertical+i<e.top+e.height&&t.top+t.height+o.vertical-i>e.top:t.left-o.horizontal+i<e.left+e.width&&t.left+t.width+o.horizontal-i>e.left&&t.top-o.vertical+i<e.top+e.height&&t.top+t.height+o.vertical-i>e.top},e.collisionByTimes=function(t,e){return t.start<=e.start&&t.end>=e.start&&t.top<e.top+e.height&&t.top+t.height>e.top||e.start<=t.start&&e.end>=t.start&&e.top<t.top+t.height&&e.top+e.height>t.top}},function(t,e,i){function o(t,e,i){if(this.props={content:{width:0}},this.overflow=!1,this.options=i,t){if(void 0==t.start)throw new Error('Property "start" missing in item '+t.id);if(void 0==t.end)throw new Error('Property "end" missing in item '+t.id)}n.call(this,t,e,i)}var n=(i(108),i(133));o.prototype=new n(null,null,null),o.prototype.baseClassName="vis-item vis-range",o.prototype.isVisible=function(t){return this.data.start<t.end&&this.data.end>t.start},o.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.box=document.createElement("div"),t.frame=document.createElement("div"),t.frame.className="vis-item-overflow",t.box.appendChild(t.frame),t.visibleFrame=document.createElement("div"),t.visibleFrame.className="vis-item-visible-frame",t.box.appendChild(t.visibleFrame),t.content=document.createElement("div"),t.content.className="vis-item-content",t.frame.appendChild(t.content),t.box["timeline-item"]=this,this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.foreground;if(!e)throw new Error("Cannot redraw item: parent has no foreground container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var i=(this.options.editable.updateTime||this.options.editable.updateGroup||this.editable===!0)&&this.editable!==!1,o=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(i?" vis-editable":" vis-readonly");t.box.className=this.baseClassName+o,this.overflow="hidden"!==window.getComputedStyle(t.frame).overflow,this.dom.content.style.maxWidth="none",this.props.content.width=this.dom.content.offsetWidth,this.height=this.dom.box.offsetHeight,this.dom.content.style.maxWidth="",this.dirty=!1}this._repaintOnItemUpdateTimeTooltip(t.box),this._repaintDeleteButton(t.box),this._repaintDragCenter(),this._repaintDragLeft(),this._repaintDragRight()},o.prototype.show=function(){this.displayed||this.redraw()},o.prototype.hide=function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.displayed=!1}},o.prototype.repositionX=function(t){var e,i,o=this.parent.width,n=this.conversion.toScreen(this.data.start),s=this.conversion.toScreen(this.data.end);void 0!==t&&t!==!0||(n<-o&&(n=-o),s>2*o&&(s=2*o));var r=Math.max(s-n+.5,1);switch(this.overflow?(this.options.rtl?this.right=n:this.left=n,this.width=r+this.props.content.width,i=this.props.content.width):(this.options.rtl?this.right=n:this.left=n,this.width=r,i=Math.min(s-n,this.props.content.width)),this.options.rtl?this.dom.box.style.right=this.right+"px":this.dom.box.style.left=this.left+"px",this.dom.box.style.width=r+"px",this.options.align){case"left":this.options.rtl?this.dom.content.style.right="0":this.dom.content.style.left="0";break;case"right":this.options.rtl?this.dom.content.style.right=Math.max(r-i,0)+"px":this.dom.content.style.left=Math.max(r-i,0)+"px";break;case"center":this.options.rtl?this.dom.content.style.right=Math.max((r-i)/2,0)+"px":this.dom.content.style.left=Math.max((r-i)/2,0)+"px";break;default:e=this.overflow?s>0?Math.max(-n,0):-i:n<0?-n:0,this.options.rtl?this.dom.content.style.right=e+"px":(this.dom.content.style.left=e+"px",this.dom.content.style.width="calc(100% - "+e+"px)")}},o.prototype.repositionY=function(){var t=this.options.orientation.item,e=this.dom.box;"top"==t?e.style.top=this.top+"px":e.style.top=this.parent.height-this.top-this.height+"px"},o.prototype._repaintDragLeft=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="vis-drag-left",t.dragLeftItem=this,this.dom.box.appendChild(t),this.dom.dragLeft=t}else!this.selected&&this.dom.dragLeft&&(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)},o.prototype._repaintDragRight=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="vis-drag-right",t.dragRightItem=this,this.dom.box.appendChild(t),this.dom.dragRight=t}else!this.selected&&this.dom.dragRight&&(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null)},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i){this.id=null,this.parent=null,this.data=t,this.dom=null,this.conversion=e||{},this.options=i||{},this.selected=!1,this.displayed=!1,this.groupShowing=!0,this.dirty=!0,this.popup=null,this.top=null,this.right=null,this.left=null,this.width=null,this.height=null,this.editable=null,this.data&&this.data.hasOwnProperty("editable")&&("boolean"==typeof this.data.editable?this.editable={updateTime:this.data.editable,updateGroup:this.data.editable,remove:this.data.editable}:"object"===(0,h.default)(i.editable)&&(this.editable={},l.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,t.editable)))}var s=i(58),r=o(s),a=i(62),h=o(a),d=i(108),l=i(1),u=i(84);n.prototype.stack=!0,n.prototype.select=function(){this.selected=!0,this.dirty=!0,this.displayed&&this.redraw()},n.prototype.unselect=function(){this.selected=!1,this.dirty=!0,this.displayed&&this.redraw()},n.prototype.setData=function(t){var e=void 0!=t.group&&this.data.group!=t.group;e&&this.parent.itemSet._moveToGroup(this,t.group),t.hasOwnProperty("editable")&&("boolean"==typeof t.editable?this.editable={updateTime:this.data.editable,updateGroup:this.data.editable,remove:this.data.editable}:"object"===(0,h.default)(options.editable)&&(this.editable={},l.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,t.editable))),this.data=t,this.dirty=!0,this.displayed&&this.redraw()},n.prototype.setParent=function(t){this.displayed?(this.hide(),this.parent=t,this.parent&&this.show()):this.parent=t},n.prototype.isVisible=function(t){return!1},n.prototype.show=function(){return!1},n.prototype.hide=function(){return!1},n.prototype.redraw=function(){},n.prototype.repositionX=function(){},n.prototype.repositionY=function(){},n.prototype._repaintDragCenter=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragCenter){var t=this,e=document.createElement("div");e.className="vis-drag-center",e.dragCenterItem=this,new d(e).on("doubletap",function(e){e.stopPropagation(),t.parent.itemSet._onUpdateItem(t)}),this.dom.box?this.dom.box.appendChild(e):this.dom.point&&this.dom.point.appendChild(e),this.dom.dragCenter=e}else!this.selected&&this.dom.dragCenter&&(this.dom.dragCenter.parentNode&&this.dom.dragCenter.parentNode.removeChild(this.dom.dragCenter),this.dom.dragCenter=null)},n.prototype._repaintDeleteButton=function(t){var e=(this.options.editable.overrideItems||null==this.editable)&&this.options.editable.remove||!this.options.editable.overrideItems&&null!=this.editable&&this.editable.remove;if(this.selected&&e&&!this.dom.deleteButton){var i=this,o=document.createElement("div");this.options.rtl?o.className="vis-delete-rtl":o.className="vis-delete",o.title="Delete this item",new d(o).on("tap",function(t){t.stopPropagation(),i.parent.removeFromDataSet(i)}),t.appendChild(o),this.dom.deleteButton=o}else!this.selected&&this.dom.deleteButton&&(this.dom.deleteButton.parentNode&&this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton),this.dom.deleteButton=null)},n.prototype._repaintOnItemUpdateTimeTooltip=function(t){if(this.options.tooltipOnItemUpdateTime){var e=(this.options.editable.updateTime||this.data.editable===!0)&&this.data.editable!==!1;if(this.selected&&e&&!this.dom.onItemUpdateTimeTooltip){var i=document.createElement("div");i.className="vis-onUpdateTime-tooltip",t.appendChild(i),this.dom.onItemUpdateTimeTooltip=i}else!this.selected&&this.dom.onItemUpdateTimeTooltip&&(this.dom.onItemUpdateTimeTooltip.parentNode&&this.dom.onItemUpdateTimeTooltip.parentNode.removeChild(this.dom.onItemUpdateTimeTooltip),this.dom.onItemUpdateTimeTooltip=null);if(this.dom.onItemUpdateTimeTooltip){this.dom.onItemUpdateTimeTooltip.style.visibility=this.parent.itemSet.touchParams.itemIsDragging?"visible":"hidden",this.options.rtl?this.dom.onItemUpdateTimeTooltip.style.right=this.dom.content.style.right:this.dom.onItemUpdateTimeTooltip.style.left=this.dom.content.style.left;var o,n=50,s=this.parent.itemSet.body.domProps.scrollTop;o="top"==this.options.orientation.item?this.top:this.parent.height-this.top-this.height;var r=o+this.parent.top-n<-s;r?(this.dom.onItemUpdateTimeTooltip.style.bottom="",this.dom.onItemUpdateTimeTooltip.style.top=this.height+2+"px"):(this.dom.onItemUpdateTimeTooltip.style.top="",this.dom.onItemUpdateTimeTooltip.style.bottom=this.height+2+"px");var a,h;this.options.tooltipOnItemUpdateTime&&this.options.tooltipOnItemUpdateTime.template?(h=this.options.tooltipOnItemUpdateTime.template.bind(this),a=h(this.data)):(a="start: "+u(this.data.start).format("MM/DD/YYYY hh:mm"),this.data.end&&(a+="<br> end: "+u(this.data.end).format("MM/DD/YYYY hh:mm"))),this.dom.onItemUpdateTimeTooltip.innerHTML=a}}},n.prototype._updateContents=function(t){var e,i,o,n,s=this.parent.itemSet.itemsData.get(this.id),r=this.dom.box||this.dom.point,a=r.getElementsByClassName("vis-item-visible-frame")[0];if(this.options.visibleFrameTemplate?(n=this.options.visibleFrameTemplate.bind(this),o=n(s,r)):o="",a)if(o instanceof Object&&!(o instanceof Element))n(s,a);else{var h=this._contentToString(this.itemVisibleFrameContent)!==this._contentToString(o);if(h){if(o instanceof Element)a.innerHTML="",a.appendChild(o);else if(void 0!=o)a.innerHTML=o;else if("background"!=this.data.type||void 0!==this.data.content)throw new Error('Property "content" missing in item '+this.id);this.itemVisibleFrameContent=o}}if(this.options.template?(i=this.options.template.bind(this),e=i(s,t)):e=this.data.content,e instanceof Object&&!(e instanceof Element))i(s,t);else{var h=this._contentToString(this.content)!==this._contentToString(e);if(h){if(e instanceof Element)t.innerHTML="",t.appendChild(e);else if(void 0!=e)t.innerHTML=e;else if("background"!=this.data.type||void 0!==this.data.content)throw new Error('Property "content" missing in item '+this.id);this.content=e}}},n.prototype._updateTitle=function(){null!=this.data.title&&null!=this.popup&&this.popup.setText(this.data.title||"")},n.prototype._updateDataAttributes=function(t){if(this.options.dataAttributes&&this.options.dataAttributes.length>0){var e=[];if(Array.isArray(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=(0,r.default)(this.data)}for(var i=0;i<e.length;i++){var o=e[i],n=this.data[o];null!=n?t.setAttribute("data-"+o,n):t.removeAttribute("data-"+o)}}},n.prototype._updateStyle=function(t){this.style&&(l.removeCssText(t,this.style),this.style=null),this.data.style&&(l.addCssText(t,this.data.style),this.style=this.data.style)},n.prototype._contentToString=function(t){return"string"==typeof t?t:t&&"outerHTML"in t?t.outerHTML:t},n.prototype.getWidthLeft=function(){return 0},n.prototype.getWidthRight=function(){return 0},n.prototype.getTitle=function(){return this.data.title},n.prototype.setPopup=function(t){this.popup=t,this._updateTitle()},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i){a.call(this,t,e,i),this.width=0,this.height=0,this.top=0,this.left=0}var s=i(55),r=o(s),a=(i(1),i(130));n.prototype=(0,r.default)(a.prototype),n.prototype.redraw=function(t,e,i){var o=!1;this.visibleItems=this._updateItemsInRange(this.orderedItems,this.visibleItems,t),this.width=this.dom.background.offsetWidth,this.dom.background.style.height="0";for(var n=0,s=this.visibleItems.length;n<s;n++){var r=this.visibleItems[n];r.repositionY(e)}return o},n.prototype.show=function(){this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background)},t.exports=n},function(t,e,i){function o(t,e,i){if(this.props={dot:{width:0,height:0},line:{width:0,height:0}},this.options=i,t&&void 0==t.start)throw new Error('Property "start" missing in item '+t);n.call(this,t,e,i)}var n=i(133);i(1);o.prototype=new n(null,null,null),o.prototype.isVisible=function(t){var e,i=this.options.align,o=(t.end-t.start)/t.body.dom.center.clientWidth,n=this.width*o;return e="right"==i?this.data.start.getTime()>t.start&&this.data.start.getTime()-n<t.end:"left"==i?this.data.start.getTime()+n>t.start&&this.data.start.getTime()<t.end:this.data.start.getTime()+n/2>t.start&&this.data.start.getTime()-n/2<t.end},o.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="vis-item-content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="vis-line",t.dot=document.createElement("DIV"),t.dot.className="vis-dot",t.box["timeline-item"]=this,this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.foreground;if(!e)throw new Error("Cannot redraw item: parent has no foreground container element");e.appendChild(t.box)}if(!t.line.parentNode){var i=this.parent.dom.background;if(!i)throw new Error("Cannot redraw item: parent has no background container element");i.appendChild(t.line)}if(!t.dot.parentNode){var o=this.parent.dom.axis;if(!i)throw new Error("Cannot redraw item: parent has no axis container element");o.appendChild(t.dot)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var n=(this.options.editable.updateTime||this.options.editable.updateGroup||this.editable===!0)&&this.editable!==!1,s=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(n?" vis-editable":" vis-readonly");t.box.className="vis-item vis-box"+s,t.line.className="vis-item vis-line"+s,t.dot.className="vis-item vis-dot"+s;var r=t.box.style.right,a=t.box.style.left;this.options.rtl?t.box.style.right="0px":t.box.style.left="0px",this.props.dot.height=t.dot.offsetHeight,this.props.dot.width=t.dot.offsetWidth,this.props.line.width=t.line.offsetWidth,this.width=t.box.offsetWidth,this.height=t.box.offsetHeight,this.options.rtl?t.box.style.right=r:t.box.style.left=a,this.dirty=!1}this._repaintOnItemUpdateTimeTooltip(t.box),this._repaintDragCenter(),this._repaintDeleteButton(t.box)},o.prototype.show=function(){this.displayed||this.redraw()},o.prototype.hide=function(){if(this.displayed){var t=this.dom;t.box.parentNode&&t.box.parentNode.removeChild(t.box),t.line.parentNode&&t.line.parentNode.removeChild(t.line),t.dot.parentNode&&t.dot.parentNode.removeChild(t.dot),this.displayed=!1}},o.prototype.repositionX=function(){var t=this.conversion.toScreen(this.data.start),e=this.options.align;"right"==e?this.options.rtl?(this.right=t-this.width,this.dom.box.style.right=this.right+"px",this.dom.line.style.right=t-this.props.line.width+"px",this.dom.dot.style.right=t-this.props.line.width/2-this.props.dot.width/2+"px"):(this.left=t-this.width,this.dom.box.style.left=this.left+"px",this.dom.line.style.left=t-this.props.line.width+"px",this.dom.dot.style.left=t-this.props.line.width/2-this.props.dot.width/2+"px"):"left"==e?this.options.rtl?(this.right=t,this.dom.box.style.right=this.right+"px",this.dom.line.style.right=t+"px",this.dom.dot.style.right=t+this.props.line.width/2-this.props.dot.width/2+"px"):(this.left=t,this.dom.box.style.left=this.left+"px",this.dom.line.style.left=t+"px",this.dom.dot.style.left=t+this.props.line.width/2-this.props.dot.width/2+"px"):this.options.rtl?(this.right=t-this.width/2,this.dom.box.style.right=this.right+"px",this.dom.line.style.right=t-this.props.line.width+"px",this.dom.dot.style.right=t-this.props.dot.width/2+"px"):(this.left=t-this.width/2,this.dom.box.style.left=this.left+"px",this.dom.line.style.left=t-this.props.line.width/2+"px",this.dom.dot.style.left=t-this.props.dot.width/2+"px")},o.prototype.repositionY=function(){var t=this.options.orientation.item,e=this.dom.box,i=this.dom.line,o=this.dom.dot;if("top"==t)e.style.top=(this.top||0)+"px",i.style.top="0",i.style.height=this.parent.top+this.top+1+"px",i.style.bottom="";else{var n=this.parent.itemSet.props.height,s=n-this.parent.top-this.parent.height+this.top;e.style.top=(this.parent.height-this.top-this.height||0)+"px",i.style.top=n-s+"px",i.style.bottom="0"}o.style.top=-this.props.dot.height/2+"px"},o.prototype.getWidthLeft=function(){return this.width/2},o.prototype.getWidthRight=function(){return this.width/2},t.exports=o},function(t,e,i){function o(t,e,i){if(this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0,marginRight:0}},this.options=i,t&&void 0==t.start)throw new Error('Property "start" missing in item '+t);n.call(this,t,e,i)}var n=i(133);o.prototype=new n(null,null,null),o.prototype.isVisible=function(t){var e=(t.end-t.start)/t.body.dom.center.clientWidth,i=this.width*e;return this.data.start.getTime()+i>t.start&&this.data.start<t.end},o.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="vis-item-content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.point.appendChild(t.dot),t.point["timeline-item"]=this,this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.point.parentNode){var e=this.parent.dom.foreground;if(!e)throw new Error("Cannot redraw item: parent has no foreground container element");e.appendChild(t.point)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(),this._updateDataAttributes(this.dom.point),this._updateStyle(this.dom.point);var i=(this.options.editable.updateTime||this.options.editable.updateGroup||this.editable===!0)&&this.editable!==!1,o=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(i?" vis-editable":" vis-readonly");t.point.className="vis-item vis-point"+o,t.dot.className="vis-item vis-dot"+o,this.props.dot.width=t.dot.offsetWidth,this.props.dot.height=t.dot.offsetHeight,this.props.content.height=t.content.offsetHeight,this.options.rtl?t.content.style.marginRight=2*this.props.dot.width+"px":t.content.style.marginLeft=2*this.props.dot.width+"px",this.width=t.point.offsetWidth,this.height=t.point.offsetHeight,t.dot.style.top=(this.height-this.props.dot.height)/2+"px",this.options.rtl?t.dot.style.right=this.props.dot.width/2+"px":t.dot.style.left=this.props.dot.width/2+"px",this.dirty=!1}this._repaintOnItemUpdateTimeTooltip(t.point),this._repaintDragCenter(),this._repaintDeleteButton(t.point)},o.prototype.show=function(){this.displayed||this.redraw()},o.prototype.hide=function(){this.displayed&&(this.dom.point.parentNode&&this.dom.point.parentNode.removeChild(this.dom.point),this.displayed=!1)},o.prototype.repositionX=function(){var t=this.conversion.toScreen(this.data.start);this.options.rtl?(this.right=t-this.props.dot.width,this.dom.point.style.right=this.right+"px"):(this.left=t-this.props.dot.width,this.dom.point.style.left=this.left+"px")},o.prototype.repositionY=function(){var t=this.options.orientation.item,e=this.dom.point;"top"==t?e.style.top=this.top+"px":e.style.top=this.parent.height-this.top-this.height+"px"},o.prototype.getWidthLeft=function(){return this.props.dot.width},o.prototype.getWidthRight=function(){return this.props.dot.width},t.exports=o},function(t,e,i){function o(t,e,i){if(this.props={content:{width:0}},this.overflow=!1,t){if(void 0==t.start)throw new Error('Property "start" missing in item '+t.id);if(void 0==t.end)throw new Error('Property "end" missing in item '+t.id)}n.call(this,t,e,i)}var n=(i(108),i(133)),s=i(134),r=i(132);o.prototype=new n(null,null,null),o.prototype.baseClassName="vis-item vis-background",o.prototype.stack=!1,o.prototype.isVisible=function(t){return this.data.start<t.end&&this.data.end>t.start},o.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.box=document.createElement("div"),t.frame=document.createElement("div"),t.frame.className="vis-item-overflow",t.box.appendChild(t.frame),t.content=document.createElement("div"),t.content.className="vis-item-content",t.frame.appendChild(t.content),this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.background;if(!e)throw new Error("Cannot redraw item: parent has no background container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"");t.box.className=this.baseClassName+i,this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.props.content.width=this.dom.content.offsetWidth,this.height=0,this.dirty=!1}},o.prototype.show=r.prototype.show,o.prototype.hide=r.prototype.hide,o.prototype.repositionX=r.prototype.repositionX,o.prototype.repositionY=function(t){var e;if(void 0!==this.data.subgroup){var i=this.data.subgroup,o=this.parent.subgroups;o[i].index;this.dom.box.style.height=this.parent.subgroups[i].height+"px";var n=this.options.orientation.item;"top"==n?this.dom.box.style.top=this.parent.top+this.parent.subgroups[i].top+"px":this.dom.box.style.top=this.parent.top+this.parent.height-this.parent.subgroups[i].top-this.parent.subgroups[i].height+"px",this.dom.box.style.bottom=""}else this.parent instanceof s?(e=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.top="top"==n?"0":"",this.dom.box.style.bottom="top"==n?"":"0"):(e=this.parent.height,this.dom.box.style.top=this.parent.top+"px",this.dom.box.style.bottom="");this.dom.box.style.height=e+"px"},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){this.dom={foreground:null,lines:[],majorTexts:[],minorTexts:[],redundant:{lines:[],majorTexts:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.defaultOptions={orientation:{axis:"bottom"},showMinorLabels:!0,showMajorLabels:!0,maxMinorChars:7,format:d.FORMAT,moment:u,timeAxis:null},this.options=a.extend({},this.defaultOptions),this.body=t,this._create(),this.setOptions(e)}var s=i(62),r=o(s),a=i(1),h=i(124),d=i(129),l=i(125),u=i(84);n.prototype=new h,n.prototype.setOptions=function(t){t&&(a.selectiveExtend(["showMinorLabels","showMajorLabels","maxMinorChars","hiddenDates","timeAxis","moment","rtl"],this.options,t),a.selectiveDeepExtend(["format"],this.options,t),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.axis=t.orientation:"object"===(0,r.default)(t.orientation)&&"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis)),"locale"in t&&("function"==typeof u.locale?u.locale(t.locale):u.lang(t.locale)))},n.prototype._create=function(){this.dom.foreground=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.foreground.className="vis-time-axis vis-foreground",this.dom.background.className="vis-time-axis vis-background"},n.prototype.destroy=function(){this.dom.foreground.parentNode&&this.dom.foreground.parentNode.removeChild(this.dom.foreground),this.dom.background.parentNode&&this.dom.background.parentNode.removeChild(this.dom.background),this.body=null},n.prototype.redraw=function(){var t=this.props,e=this.dom.foreground,i=this.dom.background,o="top"==this.options.orientation.axis?this.body.dom.top:this.body.dom.bottom,n=e.parentNode!==o;this._calculateCharSize();var s=this.options.showMinorLabels&&"none"!==this.options.orientation.axis,r=this.options.showMajorLabels&&"none"!==this.options.orientation.axis;t.minorLabelHeight=s?t.minorCharHeight:0,t.majorLabelHeight=r?t.majorCharHeight:0,t.height=t.minorLabelHeight+t.majorLabelHeight,t.width=e.offsetWidth,t.minorLineHeight=this.body.domProps.root.height-t.majorLabelHeight-("top"==this.options.orientation.axis?this.body.domProps.bottom.height:this.body.domProps.top.height),t.minorLineWidth=1,t.majorLineHeight=t.minorLineHeight+t.majorLabelHeight,t.majorLineWidth=1;var a=e.nextSibling,h=i.nextSibling;return e.parentNode&&e.parentNode.removeChild(e),i.parentNode&&i.parentNode.removeChild(i),e.style.height=this.props.height+"px",this._repaintLabels(),a?o.insertBefore(e,a):o.appendChild(e),h?this.body.dom.backgroundVertical.insertBefore(i,h):this.body.dom.backgroundVertical.appendChild(i),this._isResized()||n},n.prototype._repaintLabels=function(){var t=this.options.orientation.axis,e=a.convert(this.body.range.start,"Number"),i=a.convert(this.body.range.end,"Number"),o=this.body.util.toTime((this.props.minorCharWidth||10)*this.options.maxMinorChars).valueOf(),n=o-l.getHiddenDurationBefore(this.options.moment,this.body.hiddenDates,this.body.range,o);n-=this.body.util.toTime(0).valueOf();var s=new d(new Date(e),new Date(i),n,this.body.hiddenDates);s.setMoment(this.options.moment),this.options.format&&s.setFormat(this.options.format),this.options.timeAxis&&s.setScale(this.options.timeAxis),this.step=s;var r=this.dom;r.redundant.lines=r.lines,r.redundant.majorTexts=r.majorTexts,r.redundant.minorTexts=r.minorTexts,r.lines=[],r.majorTexts=[],r.minorTexts=[];var h,u,p,f,m,v,g,y,b,_,w=0,x=void 0,k=0,O=1e3;for(s.start(),u=s.getCurrent(),f=this.body.util.toScreen(u);s.hasNext()&&k<O;){k++,m=s.isMajor(),_=s.getClassName(),b=s.getLabelMinor(),h=u,p=f,s.next(),u=s.getCurrent(),v=s.isMajor(),f=this.body.util.toScreen(u),g=w,w=f-p;var D=w>=.4*g;if(this.options.showMinorLabels&&D){var S=this._repaintMinorText(p,b,t,_);S.style.width=w+"px"}m&&this.options.showMajorLabels?(p>0&&(void 0==x&&(x=p),S=this._repaintMajorText(p,s.getLabelMajor(),t,_)),y=this._repaintMajorLine(p,w,t,_)):D?y=this._repaintMinorLine(p,w,t,_):y&&(y.style.width=parseInt(y.style.width)+w+"px")}if(k!==O||c||(console.warn("Something is wrong with the Timeline scale. Limited drawing of grid lines to "+O+" lines."),c=!0),this.options.showMajorLabels){var M=this.body.util.toTime(0),C=s.getLabelMajor(M),T=C.length*(this.props.majorCharWidth||10)+10;(void 0==x||T<x)&&this._repaintMajorText(0,C,t,_)}a.forEach(this.dom.redundant,function(t){
-for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},n.prototype._repaintMinorText=function(t,e,i,o){var n=this.dom.redundant.minorTexts.shift();if(!n){var s=document.createTextNode("");n=document.createElement("div"),n.appendChild(s),this.dom.foreground.appendChild(n)}return this.dom.minorTexts.push(n),n.innerHTML=e,n.style.top="top"==i?this.props.majorLabelHeight+"px":"0",this.options.rtl?(n.style.left="",n.style.right=t+"px"):n.style.left=t+"px",n.className="vis-text vis-minor "+o,n},n.prototype._repaintMajorText=function(t,e,i,o){var n=this.dom.redundant.majorTexts.shift();if(!n){var s=document.createElement("div");n=document.createElement("div"),n.appendChild(s),this.dom.foreground.appendChild(n)}return n.childNodes[0].innerHTML=e,n.className="vis-text vis-major "+o,n.style.top="top"==i?"0":this.props.minorLabelHeight+"px",this.options.rtl?(n.style.left="",n.style.right=t+"px"):n.style.left=t+"px",this.dom.majorTexts.push(n),n},n.prototype._repaintMinorLine=function(t,e,i,o){var n=this.dom.redundant.lines.shift();n||(n=document.createElement("div"),this.dom.background.appendChild(n)),this.dom.lines.push(n);var s=this.props;return"top"==i?n.style.top=s.majorLabelHeight+"px":n.style.top=this.body.domProps.top.height+"px",n.style.height=s.minorLineHeight+"px",this.options.rtl?(n.style.left="",n.style.right=t-s.minorLineWidth/2+"px",n.className="vis-grid vis-vertical-rtl vis-minor "+o):(n.style.left=t-s.minorLineWidth/2+"px",n.className="vis-grid vis-vertical vis-minor "+o),n.style.width=e+"px",n},n.prototype._repaintMajorLine=function(t,e,i,o){var n=this.dom.redundant.lines.shift();n||(n=document.createElement("div"),this.dom.background.appendChild(n)),this.dom.lines.push(n);var s=this.props;return"top"==i?n.style.top="0":n.style.top=this.body.domProps.top.height+"px",this.options.rtl?(n.style.left="",n.style.right=t-s.majorLineWidth/2+"px",n.className="vis-grid vis-vertical-rtl vis-major "+o):(n.style.left=t-s.majorLineWidth/2+"px",n.className="vis-grid vis-vertical vis-major "+o),n.style.height=s.majorLineHeight+"px",n.style.width=e+"px",n},n.prototype._calculateCharSize=function(){this.dom.measureCharMinor||(this.dom.measureCharMinor=document.createElement("DIV"),this.dom.measureCharMinor.className="vis-text vis-minor vis-measure",this.dom.measureCharMinor.style.position="absolute",this.dom.measureCharMinor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMinor)),this.props.minorCharHeight=this.dom.measureCharMinor.clientHeight,this.props.minorCharWidth=this.dom.measureCharMinor.clientWidth,this.dom.measureCharMajor||(this.dom.measureCharMajor=document.createElement("DIV"),this.dom.measureCharMajor.className="vis-text vis-major vis-measure",this.dom.measureCharMajor.style.position="absolute",this.dom.measureCharMajor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMajor)),this.props.majorCharHeight=this.dom.measureCharMajor.clientHeight,this.props.majorCharWidth=this.dom.measureCharMajor.clientWidth};var c=!1;t.exports=n},function(t,e,i){function o(t){this.active=!1,this.dom={container:t},this.dom.overlay=document.createElement("div"),this.dom.overlay.className="vis-overlay",this.dom.container.appendChild(this.dom.overlay),this.hammer=a(this.dom.overlay),this.hammer.on("tap",this._onTapOverlay.bind(this));var e=this,i=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];i.forEach(function(t){e.hammer.on(t,function(t){t.stopPropagation()})}),document&&document.body&&(this.onClick=function(i){n(i.target,t)||e.deactivate()},document.body.addEventListener("click",this.onClick)),void 0!==this.keycharm&&this.keycharm.destroy(),this.keycharm=s(),this.escListener=this.deactivate.bind(this)}function n(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}var s=i(111),r=i(95),a=i(108),h=i(1);r(o.prototype),o.current=null,o.prototype.destroy=function(){this.deactivate(),this.dom.overlay.parentNode.removeChild(this.dom.overlay),this.onClick&&document.body.removeEventListener("click",this.onClick),this.hammer.destroy(),this.hammer=null},o.prototype.activate=function(){o.current&&o.current.deactivate(),o.current=this,this.active=!0,this.dom.overlay.style.display="none",h.addClassName(this.dom.container,"vis-active"),this.emit("change"),this.emit("activate"),this.keycharm.bind("esc",this.escListener)},o.prototype.deactivate=function(){this.active=!1,this.dom.overlay.style.display="",h.removeClassName(this.dom.container,"vis-active"),this.keycharm.unbind("esc",this.escListener),this.emit("change"),this.emit("deactivate")},o.prototype._onTapOverlay=function(t){this.activate(),t.stopPropagation()},t.exports=o},function(t,e,i){function o(t,e){this.body=t,this.defaultOptions={moment:a,locales:h,locale:"en",id:void 0,title:void 0},this.options=s.extend({},this.defaultOptions),e&&e.time?this.customTime=e.time:this.customTime=new Date,this.eventParams={},this.setOptions(e),this._create()}var n=i(108),s=i(1),r=i(124),a=i(84),h=i(141);o.prototype=new r,o.prototype.setOptions=function(t){t&&s.selectiveExtend(["moment","locale","locales","id"],this.options,t)},o.prototype._create=function(){function t(t){this.body.range._onMouseWheel(t)}var e=document.createElement("div");e["custom-time"]=this,e.className="vis-custom-time "+(this.options.id||""),e.style.position="absolute",e.style.top="0px",e.style.height="100%",this.bar=e;var i=document.createElement("div");i.style.position="relative",i.style.top="0px",i.style.left="-10px",i.style.height="100%",i.style.width="20px",i.addEventListener?(i.addEventListener("mousewheel",t.bind(this),!1),i.addEventListener("DOMMouseScroll",t.bind(this),!1)):i.attachEvent("onmousewheel",t.bind(this)),e.appendChild(i),this.hammer=new n(i),this.hammer.on("panstart",this._onDragStart.bind(this)),this.hammer.on("panmove",this._onDrag.bind(this)),this.hammer.on("panend",this._onDragEnd.bind(this)),this.hammer.get("pan").set({threshold:5,direction:n.DIRECTION_HORIZONTAL})},o.prototype.destroy=function(){this.hide(),this.hammer.destroy(),this.hammer=null,this.body=null},o.prototype.redraw=function(){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar));var e=this.body.util.toScreen(this.customTime),i=this.options.locales[this.options.locale];i||(this.warned||(console.log("WARNING: options.locales['"+this.options.locale+"'] not found. See http://visjs.org/docs/timeline/#Localization"),this.warned=!0),i=this.options.locales.en);var o=this.options.title;return void 0===o&&(o=i.time+": "+this.options.moment(this.customTime).format("dddd, MMMM Do YYYY, H:mm:ss"),o=o.charAt(0).toUpperCase()+o.substring(1)),this.bar.style.left=e+"px",this.bar.title=o,!1},o.prototype.hide=function(){this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar)},o.prototype.setCustomTime=function(t){this.customTime=s.convert(t,"Date"),this.redraw()},o.prototype.getCustomTime=function(){return new Date(this.customTime.valueOf())},o.prototype.setCustomTitle=function(t){this.options.title=t},o.prototype._onDragStart=function(t){this.eventParams.dragging=!0,this.eventParams.customTime=this.customTime,t.stopPropagation()},o.prototype._onDrag=function(t){if(this.eventParams.dragging){var e=this.body.util.toScreen(this.eventParams.customTime)+t.deltaX,i=this.body.util.toTime(e);this.setCustomTime(i),this.body.emitter.emit("timechange",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:s.elementsCensor(t)}),t.stopPropagation()}},o.prototype._onDragEnd=function(t){this.eventParams.dragging&&(this.body.emitter.emit("timechanged",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:s.elementsCensor(t)}),t.stopPropagation())},o.customTimeFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("custom-time"))return e["custom-time"];e=e.parentNode}return null},t.exports=o},function(t,e){e.en={current:"current",time:"time"},e.en_EN=e.en,e.en_US=e.en,e.it={current:"attuale",time:"tempo"},e.it_IT=e.it,e.it_CH=e.it,e.nl={current:"huidige",time:"tijd"},e.nl_NL=e.nl,e.nl_BE=e.nl,e.de={current:"Aktuelle",time:"Zeit"},e.de_DE=e.de},function(t,e,i){function o(t,e){this.body=t,this.defaultOptions={rtl:!1,showCurrentTime:!0,moment:r,locales:a,locale:"en"},this.options=n.extend({},this.defaultOptions),this.offset=0,this._create(),this.setOptions(e)}var n=i(1),s=i(124),r=i(84),a=i(141);o.prototype=new s,o.prototype._create=function(){var t=document.createElement("div");t.className="vis-current-time",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t},o.prototype.destroy=function(){this.options.showCurrentTime=!1,this.redraw(),this.body=null},o.prototype.setOptions=function(t){t&&n.selectiveExtend(["rtl","showCurrentTime","moment","locale","locales"],this.options,t)},o.prototype.redraw=function(){if(this.options.showCurrentTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar),this.start());var e=this.options.moment((new Date).valueOf()+this.offset),i=this.body.util.toScreen(e),o=this.options.locales[this.options.locale];o||(this.warned||(console.log("WARNING: options.locales['"+this.options.locale+"'] not found. See http://visjs.org/docs/timeline/#Localization"),this.warned=!0),o=this.options.locales.en);var n=o.current+" "+o.time+": "+e.format("dddd, MMMM Do YYYY, H:mm:ss");n=n.charAt(0).toUpperCase()+n.substring(1),this.options.rtl?this.bar.style.right=i+"px":this.bar.style.left=i+"px",this.bar.title=n}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.stop();return!1},o.prototype.start=function(){function t(){e.stop();var i=e.body.range.conversion(e.body.domProps.center.width).scale,o=1/i/10;o<30&&(o=30),o>1e3&&(o=1e3),e.redraw(),e.body.emitter.emit("currentTimeTick"),e.currentTimeTimer=setTimeout(t,o)}var e=this;t()},o.prototype.stop=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)},o.prototype.setCurrentTime=function(t){var e=n.convert(t,"Date").valueOf(),i=(new Date).valueOf();this.offset=e-i,this.redraw()},o.prototype.getCurrentTime=function(){return new Date((new Date).valueOf()+this.offset)},t.exports=o},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var i="string",o="boolean",n="number",s="array",r="date",a="object",h="dom",d="moment",l="any",u={configure:{enabled:{boolean:o},filter:{boolean:o,function:"function"},container:{dom:h},__type__:{object:a,boolean:o,function:"function"}},align:{string:i},rtl:{boolean:o,undefined:"undefined"},rollingMode:{boolean:o,undefined:"undefined"},verticalScroll:{boolean:o,undefined:"undefined"},horizontalScroll:{boolean:o,undefined:"undefined"},autoResize:{boolean:o},throttleRedraw:{number:n},clickToUse:{boolean:o},dataAttributes:{string:i,array:s},editable:{add:{boolean:o,undefined:"undefined"},remove:{boolean:o,undefined:"undefined"},updateGroup:{boolean:o,undefined:"undefined"},updateTime:{boolean:o,undefined:"undefined"},overrideItems:{boolean:o,undefined:"undefined"},__type__:{boolean:o,object:a}},end:{number:n,date:r,string:i,moment:d},format:{minorLabels:{millisecond:{string:i,undefined:"undefined"},second:{string:i,undefined:"undefined"},minute:{string:i,undefined:"undefined"},hour:{string:i,undefined:"undefined"},weekday:{string:i,undefined:"undefined"},day:{string:i,undefined:"undefined"},month:{string:i,undefined:"undefined"},year:{string:i,undefined:"undefined"},__type__:{object:a,function:"function"}},majorLabels:{millisecond:{string:i,undefined:"undefined"},second:{string:i,undefined:"undefined"},minute:{string:i,undefined:"undefined"},hour:{string:i,undefined:"undefined"},weekday:{string:i,undefined:"undefined"},day:{string:i,undefined:"undefined"},month:{string:i,undefined:"undefined"},year:{string:i,undefined:"undefined"},__type__:{object:a,function:"function"}},__type__:{object:a}},moment:{function:"function"},groupOrder:{string:i,function:"function"},groupEditable:{add:{boolean:o,undefined:"undefined"},remove:{boolean:o,undefined:"undefined"},order:{boolean:o,undefined:"undefined"},__type__:{boolean:o,object:a}},groupOrderSwap:{function:"function"},height:{string:i,number:n},hiddenDates:{start:{date:r,number:n,string:i,moment:d},end:{date:r,number:n,string:i,moment:d},repeat:{string:i},__type__:{object:a,array:s}},itemsAlwaysDraggable:{boolean:o},locale:{string:i},locales:{__any__:{any:l},__type__:{object:a}},margin:{axis:{number:n},item:{horizontal:{number:n,undefined:"undefined"},vertical:{number:n,undefined:"undefined"},__type__:{object:a,number:n}},__type__:{object:a,number:n}},max:{date:r,number:n,string:i,moment:d},maxHeight:{number:n,string:i},maxMinorChars:{number:n},min:{date:r,number:n,string:i,moment:d},minHeight:{number:n,string:i},moveable:{boolean:o},multiselect:{boolean:o},multiselectPerGroup:{boolean:o},onAdd:{function:"function"},onUpdate:{function:"function"},onMove:{function:"function"},onMoving:{function:"function"},onRemove:{function:"function"},onAddGroup:{function:"function"},onMoveGroup:{function:"function"},onRemoveGroup:{function:"function"},order:{function:"function"},orientation:{axis:{string:i,undefined:"undefined"},item:{string:i,undefined:"undefined"},__type__:{string:i,object:a}},selectable:{boolean:o},showCurrentTime:{boolean:o},showMajorLabels:{boolean:o},showMinorLabels:{boolean:o},stack:{boolean:o},stackSubgroups:{boolean:o},snap:{function:"function",null:"null"},start:{date:r,number:n,string:i,moment:d},template:{function:"function"},groupTemplate:{function:"function"},visibleFrameTemplate:{string:i,function:"function"},tooltip:{followMouse:{boolean:o},overflowMethod:{string:["cap","flip"]},__type__:{object:a}},tooltipOnItemUpdateTime:{template:{function:"function"},__type__:{boolean:o,object:a}},timeAxis:{scale:{string:i,undefined:"undefined"},step:{number:n,undefined:"undefined"},__type__:{object:a}},type:{string:i},width:{string:i,number:n},zoomable:{boolean:o},zoomKey:{string:["ctrlKey","altKey","metaKey",""]},zoomMax:{number:n},zoomMin:{number:n},__type__:{object:a}},c={global:{align:["center","left","right"],direction:!1,autoResize:!0,clickToUse:!1,editable:{add:!1,remove:!1,updateGroup:!1,updateTime:!1},end:"",format:{minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",month:"YYYY",year:""}},groupsDraggable:!1,height:"",locale:"",margin:{axis:[20,0,100,1],item:{horizontal:[10,0,100,1],vertical:[10,0,100,1]}},max:"",maxHeight:"",maxMinorChars:[7,0,20,1],min:"",minHeight:"",moveable:!1,multiselect:!1,multiselectPerGroup:!1,orientation:{axis:["both","bottom","top"],item:["bottom","top"]},selectable:!0,showCurrentTime:!1,showMajorLabels:!0,showMinorLabels:!0,stack:!0,stackSubgroups:!0,start:"",tooltip:{followMouse:!1,overflowMethod:"flip"},tooltipOnItemUpdateTime:!1,type:["box","point","range","background"],width:"100%",zoomable:!0,zoomKey:["ctrlKey","altKey","metaKey",""],zoomMax:[31536e10,10,31536e10,1],zoomMin:[10,10,31536e10,1]}};e.allOptions=u,e.configureOptions=c},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i,o){if(!(Array.isArray(i)||i instanceof u||i instanceof c)&&i instanceof Object){var n=o;o=i,i=n}o&&o.throttleRedraw&&console.warn('Graph2d option "throttleRedraw" is DEPRICATED and no longer supported. It will be removed in the next MAJOR release.');var s=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:{axis:"bottom",item:"bottom"},moment:d,width:null,height:null,maxHeight:null,minHeight:null},this.options=l.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{toScreen:s._toScreen.bind(s),toGlobalScreen:s._toGlobalScreen.bind(s),toTime:s._toTime.bind(s),toGlobalTime:s._toGlobalTime.bind(s)}},this.range=new p(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new m(this.body),this.components.push(this.timeAxis),this.currentTime=new v(this.body),this.components.push(this.currentTime),this.linegraph=new y(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,this.on("tap",function(t){s.emit("click",s.getEventProperties(t))}),this.on("doubletap",function(t){s.emit("doubleClick",s.getEventProperties(t))}),this.dom.root.oncontextmenu=function(t){s.emit("contextmenu",s.getEventProperties(t))},o&&this.setOptions(o),i&&this.setGroups(i),e&&this.setItems(e),this._redraw()}var s=i(114),r=o(s),a=i(122),h=o(a),d=(i(95),i(108),i(84)),l=i(1),u=i(91),c=i(93),p=i(123),f=i(126),m=i(138),v=i(142),g=i(140),y=i(145),b=i(122).printStyle,_=i(153).allOptions,w=i(153).configureOptions;n.prototype=new f,n.prototype.setOptions=function(t){var e=h.default.validate(t,_);e===!0&&console.log("%cErrors have been found in the supplied options object.",b),f.prototype.setOptions.call(this,t)},n.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof u||t instanceof c?t:new u(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.linegraph&&this.linegraph.setItems(e),i)if(void 0!=this.options.start||void 0!=this.options.end){var o=void 0!=this.options.start?this.options.start:null,n=void 0!=this.options.end?this.options.end:null;this.setWindow(o,n,{animation:!1})}else this.fit({animation:!1})},n.prototype.setGroups=function(t){var e;e=t?t instanceof u||t instanceof c?t:new u(t):null,this.groupsData=e,this.linegraph.setGroups(e)},n.prototype.getLegend=function(t,e,i){return void 0===e&&(e=15),void 0===i&&(i=15),void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].getLegend(e,i):"cannot find group:'"+t+"'"},n.prototype.isGroupVisible=function(t){return void 0!==this.linegraph.groups[t]&&(this.linegraph.groups[t].visible&&(void 0===this.linegraph.options.groups.visibility[t]||1==this.linegraph.options.groups.visibility[t]))},n.prototype.getDataRange=function(){var t=null,e=null;for(var i in this.linegraph.groups)if(this.linegraph.groups.hasOwnProperty(i)&&1==this.linegraph.groups[i].visible)for(var o=0;o<this.linegraph.groups[i].itemsData.length;o++){var n=this.linegraph.groups[i].itemsData[o],s=l.convert(n.x,"Date").valueOf();t=null==t?s:t>s?s:t,e=null==e?s:e<s?s:e}return{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},n.prototype.getEventProperties=function(t){var e=t.center?t.center.x:t.clientX,i=t.center?t.center.y:t.clientY,o=e-l.getAbsoluteLeft(this.dom.centerContainer),n=i-l.getAbsoluteTop(this.dom.centerContainer),s=this._toTime(o),r=g.customTimeFromTarget(t),a=l.getTarget(t),h=null;l.hasParent(a,this.timeAxis.dom.foreground)?h="axis":this.timeAxis2&&l.hasParent(a,this.timeAxis2.dom.foreground)?h="axis":l.hasParent(a,this.linegraph.yAxisLeft.dom.frame)?h="data-axis":l.hasParent(a,this.linegraph.yAxisRight.dom.frame)?h="data-axis":l.hasParent(a,this.linegraph.legendLeft.dom.frame)?h="legend":l.hasParent(a,this.linegraph.legendRight.dom.frame)?h="legend":null!=r?h="custom-time":l.hasParent(a,this.currentTime.bar)?h="current-time":l.hasParent(a,this.dom.center)&&(h="background");var d=[],u=this.linegraph.yAxisLeft,c=this.linegraph.yAxisRight;return!u.hidden&&this.itemsData.length>0&&d.push(u.screenToValue(n)),!c.hidden&&this.itemsData.length>0&&d.push(c.screenToValue(n)),{event:t,what:h,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:o,y:n,time:s,value:d}},n.prototype._createConfigurator=function(){return new r.default(this,this.dom.container,w)},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){this.id=a.randomUUID(),this.body=t,this.defaultOptions={yAxisOrientation:"left",defaultGroup:"default",sort:!0,sampling:!0,stack:!1,graphHeight:"400px",shaded:{enabled:!1,orientation:"bottom"},style:"line",barChart:{width:50,sideBySide:!1,align:"center"},interpolation:{enabled:!0,parametrization:"centripetal",alpha:.5},drawPoints:{enabled:!0,size:6,style:"square"},dataAxis:{},legend:{},groups:{visibility:{}}},this.options=a.extend({},this.defaultOptions),this.dom={},this.props={},this.hammer=null,this.groups={},this.abortedGraphUpdate=!1,this.updateSVGheight=!1,this.updateSVGheightOnResize=!1,this.forceGraphUpdate=!0;var i=this;this.itemsData=null,this.groupsData=null,this.itemListeners={add:function(t,e,o){i._onAdd(e.items)},update:function(t,e,o){i._onUpdate(e.items)},remove:function(t,e,o){i._onRemove(e.items)}},this.groupListeners={add:function(t,e,o){i._onAddGroups(e.items)},update:function(t,e,o){i._onUpdateGroups(e.items)},remove:function(t,e,o){i._onRemoveGroups(e.items)}},this.items={},this.selection=[],this.lastStart=this.body.range.start,this.touchParams={},this.svgElements={},this.setOptions(e),this.groupsUsingDefaultStyles=[0],this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=a.option.asSize(-i.props.width),i.forceGraphUpdate=!0,i.redraw.call(i)}),this._create(),this.framework={svg:this.svg,svgElements:this.svgElements,options:this.options,groups:this.groups}}var s=i(62),r=o(s),a=i(1),h=i(90),d=i(91),l=i(93),u=i(124),c=i(146),p=i(148),f=i(152),m=i(149),v=i(151),g=i(150),y="__ungrouped__";n.prototype=new u,n.prototype._create=function(){var t=document.createElement("div");t.className="vis-line-graph",this.dom.frame=t,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="relative",this.svg.style.height=(""+this.options.graphHeight).replace("px","")+"px",this.svg.style.display="block",t.appendChild(this.svg),this.options.dataAxis.orientation="left",this.yAxisLeft=new c(this.body,this.options.dataAxis,this.svg,this.options.groups),this.options.dataAxis.orientation="right",this.yAxisRight=new c(this.body,this.options.dataAxis,this.svg,this.options.groups),delete this.options.dataAxis.orientation,this.legendLeft=new f(this.body,this.options.legend,"left",this.options.groups),this.legendRight=new f(this.body,this.options.legend,"right",this.options.groups),this.show()},n.prototype.setOptions=function(t){if(t){var e=["sampling","defaultGroup","stack","height","graphHeight","yAxisOrientation","style","barChart","dataAxis","sort","groups"];void 0===t.graphHeight&&void 0!==t.height?(this.updateSVGheight=!0,this.updateSVGheightOnResize=!0):void 0!==this.body.domProps.centerContainer.height&&void 0!==t.graphHeight&&parseInt((t.graphHeight+"").replace("px",""))<this.body.domProps.centerContainer.height&&(this.updateSVGheight=!0),a.selectiveDeepExtend(e,this.options,t),a.mergeOptions(this.options,t,"interpolation"),a.mergeOptions(this.options,t,"drawPoints"),a.mergeOptions(this.options,t,"shaded"),a.mergeOptions(this.options,t,"legend"),t.interpolation&&"object"==(0,r.default)(t.interpolation)&&t.interpolation.parametrization&&("uniform"==t.interpolation.parametrization?this.options.interpolation.alpha=0:"chordal"==t.interpolation.parametrization?this.options.interpolation.alpha=1:(this.options.interpolation.parametrization="centripetal",this.options.interpolation.alpha=.5)),this.yAxisLeft&&void 0!==t.dataAxis&&(this.yAxisLeft.setOptions(this.options.dataAxis),this.yAxisRight.setOptions(this.options.dataAxis)),this.legendLeft&&void 0!==t.legend&&(this.legendLeft.setOptions(this.options.legend),this.legendRight.setOptions(this.options.legend)),this.groups.hasOwnProperty(y)&&this.groups[y].setOptions(t)}this.dom.frame&&(this.forceGraphUpdate=!0,this.body.emitter.emit("_change",{queue:!0}))},n.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},n.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},n.prototype.setItems=function(t){var e,i=this,o=this.itemsData;if(t){if(!(t instanceof d||t instanceof l))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(o&&(a.forEach(this.itemListeners,function(t,e){o.off(e,t)}),e=o.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;a.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}},n.prototype.setGroups=function(t){var e,i=this;if(this.groupsData){a.forEach(this.groupListeners,function(t,e){i.groupsData.off(e,t)}),e=this.groupsData.getIds(),this.groupsData=null;for(var o=0;o<e.length;o++)this._removeGroup(e[o])}if(t){if(!(t instanceof d||t instanceof l))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var n=this.id;a.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,n)}),e=this.groupsData.getIds(),this._onAddGroups(e)}},n.prototype._onUpdate=function(t){this._updateAllGroupData(t)},n.prototype._onAdd=function(t){this._onUpdate(t)},n.prototype._onRemove=function(t){this._onUpdate(t)},n.prototype._onUpdateGroups=function(t){this._updateAllGroupData(null,t)},n.prototype._onAddGroups=function(t){this._onUpdateGroups(t)},n.prototype._onRemoveGroups=function(t){for(var e=0;e<t.length;e++)this._removeGroup(t[e]);this.forceGraphUpdate=!0,this.body.emitter.emit("_change",{queue:!0})},n.prototype._removeGroup=function(t){this.groups.hasOwnProperty(t)&&("right"==this.groups[t].options.yAxisOrientation?(this.yAxisRight.removeGroup(t),this.legendRight.removeGroup(t),this.legendRight.redraw()):(this.yAxisLeft.removeGroup(t),this.legendLeft.removeGroup(t),this.legendLeft.redraw()),delete this.groups[t])},n.prototype._updateGroup=function(t,e){this.groups.hasOwnProperty(e)?(this.groups[e].update(t),"right"==this.groups[e].options.yAxisOrientation?(this.yAxisRight.updateGroup(e,this.groups[e]),this.legendRight.updateGroup(e,this.groups[e]),this.yAxisLeft.removeGroup(e),this.legendLeft.removeGroup(e)):(this.yAxisLeft.updateGroup(e,this.groups[e]),this.legendLeft.updateGroup(e,this.groups[e]),this.yAxisRight.removeGroup(e),this.legendRight.removeGroup(e))):(this.groups[e]=new p(t,e,this.options,this.groupsUsingDefaultStyles),"right"==this.groups[e].options.yAxisOrientation?(this.yAxisRight.addGroup(e,this.groups[e]),this.legendRight.addGroup(e,this.groups[e])):(this.yAxisLeft.addGroup(e,this.groups[e]),this.legendLeft.addGroup(e,this.groups[e]))),this.legendLeft.redraw(),this.legendRight.redraw()},n.prototype._updateAllGroupData=function(t,e){if(null!=this.itemsData){var i={},o=this.itemsData.get(),n=this.itemsData._fieldId,s={};t&&t.map(function(t){s[t]=t});for(var r={},h=0;h<o.length;h++){var d=o[h],l=d.group;null!==l&&void 0!==l||(l=y),r.hasOwnProperty(l)?r[l]++:r[l]=1}if(!e&&t)for(var l in this.groups)if(this.groups.hasOwnProperty(l)){var u=this.groups[l],c=u.getItems();i[l]=c.filter(function(t){return t[n]!==s[t[n]]});var p=r[l];r[l]-=i[l].length,i[l].length<p&&(i[l][p-1]={})}for(var h=0;h<o.length;h++){var d=o[h],l=d.group;if(null!==l&&void 0!==l||(l=y),e||!t||d[n]===s[d[n]]){i.hasOwnProperty(l)||(i[l]=new Array(r[l]));var f=a.bridgeObject(d);f.x=a.convert(d.x,"Date"),f.orginalY=d.y,f.y=Number(d.y),f[n]=d[n];var m=i[l].length-r[l]--;i[l][m]=f}}for(var l in this.groups)this.groups.hasOwnProperty(l)&&(i.hasOwnProperty(l)||(i[l]=new Array(0)));for(var l in i)if(i.hasOwnProperty(l))if(0==i[l].length)this.groups.hasOwnProperty(l)&&this._removeGroup(l);else{var u=void 0;void 0!=this.groupsData&&(u=this.groupsData.get(l)),void 0==u&&(u={id:l,content:this.options.defaultGroup+l}),this._updateGroup(u,l),this.groups[l].setItems(i[l])}this.forceGraphUpdate=!0,this.body.emitter.emit("_change",{queue:!0})}},n.prototype.redraw=function(){var t=!1;this.props.width=this.dom.frame.offsetWidth,this.props.height=this.body.domProps.centerContainer.height-this.body.domProps.border.top-this.body.domProps.border.bottom,t=this._isResized()||t;var e=this.body.range.end-this.body.range.start,i=e!=this.lastVisibleInterval;if(this.lastVisibleInterval=e,1==t&&(this.svg.style.width=a.option.asSize(3*this.props.width),this.svg.style.left=a.option.asSize(-this.props.width),(this.options.height+"").indexOf("%")==-1&&1!=this.updateSVGheightOnResize||(this.updateSVGheight=!0)),1==this.updateSVGheight?(this.options.graphHeight!=this.props.height+"px"&&(this.options.graphHeight=this.props.height+"px",this.svg.style.height=this.props.height+"px"),this.updateSVGheight=!1):this.svg.style.height=(""+this.options.graphHeight).replace("px","")+"px",1==t||1==i||1==this.abortedGraphUpdate||1==this.forceGraphUpdate)t=this._updateGraph()||t,this.forceGraphUpdate=!1;else if(0!=this.lastStart){var o=this.body.range.start-this.lastStart,n=this.body.range.end-this.body.range.start;if(0!=this.props.width){var s=this.props.width/n,r=o*s;this.svg.style.left=-this.props.width-r+"px"}}return this.legendLeft.redraw(),this.legendRight.redraw(),t},n.prototype._getSortedGroupIds=function(){var t=[];for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];1!=i.visible||void 0!==this.options.groups.visibility[e]&&1!=this.options.groups.visibility[e]||t.push({id:e,zIndex:i.options.zIndex})}a.insertSort(t,function(t,e){var i=t.zIndex,o=e.zIndex;return void 0===i&&(i=0),void 0===o&&(o=0),i==o?0:i<o?-1:1});for(var o=new Array(t.length),n=0;n<t.length;n++)o[n]=t[n].id;return o},n.prototype._updateGraph=function(){if(h.prepareElements(this.svgElements),0!=this.props.width&&null!=this.itemsData){var t,e,i={},o=!1,n=this.body.util.toGlobalTime(-this.body.domProps.root.width),s=this.body.util.toGlobalTime(2*this.body.domProps.root.width),r=this._getSortedGroupIds();if(r.length>0){var a={};for(this._getRelevantData(r,a,n,s),this._applySampling(r,a),e=0;e<r.length;e++)this._convertXcoordinates(a[r[e]]);if(this._getYRanges(r,a,i),o=this._updateYAxis(r,i),1==o)return h.cleanupElements(this.svgElements),this.abortedGraphUpdate=!0,!0;this.abortedGraphUpdate=!1;var d=void 0;for(e=0;e<r.length;e++)t=this.groups[r[e]],this.options.stack===!0&&"line"===this.options.style&&(void 0!=t.options.excludeFromStacking&&t.options.excludeFromStacking||(void 0!=d&&(this._stack(a[t.id],a[d.id]),1==t.options.shaded.enabled&&"group"!==t.options.shaded.orientation&&("top"==t.options.shaded.orientation&&"group"!==d.options.shaded.orientation?(d.options.shaded.orientation="group",d.options.shaded.groupId=t.id):(t.options.shaded.orientation="group",t.options.shaded.groupId=d.id))),d=t)),this._convertYcoordinates(a[r[e]],t);var l={};for(e=0;e<r.length;e++)if(t=this.groups[r[e]],"line"===t.options.style&&1==t.options.shaded.enabled){var u=a[r[e]];if(null==u||0==u.length)continue;if(l.hasOwnProperty(r[e])||(l[r[e]]=v.calcPath(u,t)),"group"===t.options.shaded.orientation){var c=t.options.shaded.groupId;if(r.indexOf(c)===-1){console.log(t.id+": Unknown shading group target given:"+c);continue}l.hasOwnProperty(c)||(l[c]=v.calcPath(a[c],this.groups[c])),v.drawShading(l[r[e]],t,l[c],this.framework)}else v.drawShading(l[r[e]],t,void 0,this.framework)}for(m.draw(r,a,this.framework),e=0;e<r.length;e++)if(t=this.groups[r[e]],a[r[e]].length>0)switch(t.options.style){case"line":l.hasOwnProperty(r[e])||(l[r[e]]=v.calcPath(a[r[e]],t)),v.draw(l[r[e]],t,this.framework);case"point":case"points":"point"!=t.options.style&&"points"!=t.options.style&&1!=t.options.drawPoints.enabled||g.draw(a[r[e]],t,this.framework);break;case"bar":}}}return h.cleanupElements(this.svgElements),!1},n.prototype._stack=function(t,e){var i,o,n,s,r;i=0;for(var a=0;a<t.length;a++){s=void 0,r=void 0;for(var h=i;h<e.length;h++){if(e[h].x===t[a].x){s=e[h],r=e[h],i=h;break}if(e[h].x>t[a].x){r=e[h],s=0==h?r:e[h-1],i=h;break}}void 0===r&&(s=e[e.length-1],r=e[e.length-1]),o=r.x-s.x,n=r.y-s.y,0==o?t[a].y=t[a].orginalY+r.y:t[a].y=t[a].orginalY+n/o*(t[a].x-s.x)+s.y}},n.prototype._getRelevantData=function(t,e,i,o){var n,s,r,h;if(t.length>0)for(s=0;s<t.length;s++){
-n=this.groups[t[s]];var d=n.getItems();if(1==n.options.sort){var l=function(t,e){return t.getTime()==e.getTime()?0:t<e?-1:1},u=Math.max(0,a.binarySearchValue(d,i,"x","before",l)),c=Math.min(d.length,a.binarySearchValue(d,o,"x","after",l)+1);c<=0&&(c=d.length);var p=new Array(c-u);for(r=u;r<c;r++)h=n.itemsData[r],p[r-u]=h;e[t[s]]=p}else e[t[s]]=n.itemsData}},n.prototype._applySampling=function(t,e){var i;if(t.length>0)for(var o=0;o<t.length;o++)if(i=this.groups[t[o]],1==i.options.sampling){var n=e[t[o]];if(n.length>0){var s=1,r=n.length,a=this.body.util.toGlobalScreen(n[n.length-1].x)-this.body.util.toGlobalScreen(n[0].x),h=r/a;s=Math.min(Math.ceil(.2*r),Math.max(1,Math.round(h)));for(var d=new Array(r),l=0;l<r;l+=s){var u=Math.round(l/s);d[u]=n[l]}e[t[o]]=d.splice(0,Math.round(r/s))}}},n.prototype._getYRanges=function(t,e,i){var o,n,s,r,a=[],h=[];if(t.length>0){for(s=0;s<t.length;s++)o=e[t[s]],r=this.groups[t[s]].options,o.length>0&&(n=this.groups[t[s]],r.stack===!0&&"bar"===r.style?"left"===r.yAxisOrientation?a=a.concat(n.getItems()):h=h.concat(n.getItems()):i[t[s]]=n.getYRange(o,t[s]));m.getStackedYRange(a,i,t,"__barStackLeft","left"),m.getStackedYRange(h,i,t,"__barStackRight","right")}},n.prototype._updateYAxis=function(t,e){var i,o,n=!1,s=!1,r=!1,a=1e9,h=1e9,d=-1e9,l=-1e9;if(t.length>0){for(var u=0;u<t.length;u++){var c=this.groups[t[u]];c&&"right"!=c.options.yAxisOrientation?(s=!0,a=1e9,d=-1e9):c&&c.options.yAxisOrientation&&(r=!0,h=1e9,l=-1e9)}for(var u=0;u<t.length;u++)e.hasOwnProperty(t[u])&&e[t[u]].ignore!==!0&&(i=e[t[u]].min,o=e[t[u]].max,"right"!=e[t[u]].yAxisOrientation?(s=!0,a=a>i?i:a,d=d<o?o:d):(r=!0,h=h>i?i:h,l=l<o?o:l));1==s&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}n=this._toggleAxisVisiblity(s,this.yAxisLeft)||n,n=this._toggleAxisVisiblity(r,this.yAxisRight)||n,1==r&&1==s?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!s,this.yAxisRight.masterAxis=this.yAxisLeft,0==this.yAxisRight.master?(1==r?this.yAxisLeft.lineOffset=this.yAxisRight.width:this.yAxisLeft.lineOffset=0,n=this.yAxisLeft.redraw()||n,n=this.yAxisRight.redraw()||n):n=this.yAxisRight.redraw()||n;for(var p=["__barStackLeft","__barStackRight","__lineStackLeft","__lineStackRight"],u=0;u<p.length;u++)t.indexOf(p[u])!=-1&&t.splice(t.indexOf(p[u]),1);return n},n.prototype._toggleAxisVisiblity=function(t,e){var i=!1;return 0==t?e.dom.frame.parentNode&&0==e.hidden&&(e.hide(),i=!0):e.dom.frame.parentNode||1!=e.hidden||(e.show(),i=!0),i},n.prototype._convertXcoordinates=function(t){for(var e=this.body.util.toScreen,i=0;i<t.length;i++)t[i].screen_x=e(t[i].x)+this.props.width,t[i].screen_y=t[i].y},n.prototype._convertYcoordinates=function(t,e){var i=this.yAxisLeft,o=Number(this.svg.style.height.replace("px",""));"right"==e.options.yAxisOrientation&&(i=this.yAxisRight);for(var n=0;n<t.length;n++)t[n].screen_y=Math.round(i.convertValue(t[n].y));e.setZeroPosition(Math.min(o,i.convertValue(0)))},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i,o){this.id=a.randomUUID(),this.body=t,this.defaultOptions={orientation:"left",showMinorLabels:!0,showMajorLabels:!0,icons:!1,majorLinesOffset:7,minorLinesOffset:4,labelOffsetX:10,labelOffsetY:2,iconWidth:20,width:"40px",visible:!0,alignZeros:!0,left:{range:{min:void 0,max:void 0},format:function(t){return""+parseFloat(t.toPrecision(3))},title:{text:void 0,style:void 0}},right:{range:{min:void 0,max:void 0},format:function(t){return""+parseFloat(t.toPrecision(3))},title:{text:void 0,style:void 0}}},this.linegraphOptions=o,this.linegraphSVG=i,this.props={},this.DOMelements={lines:{},labels:{},title:{}},this.dom={},this.scale=void 0,this.range={start:0,end:0},this.options=a.extend({},this.defaultOptions),this.conversionFactor=1,this.setOptions(e),this.width=Number((""+this.options.width).replace("px","")),this.minWidth=this.width,this.height=this.linegraphSVG.getBoundingClientRect().height,this.hidden=!1,this.stepPixels=25,this.zeroCrossing=-1,this.amountOfSteps=-1,this.lineOffset=0,this.master=!0,this.masterAxis=null,this.svgElements={},this.iconsRemoved=!1,this.groups={},this.amountOfGroups=0,this._create(),this.framework={svg:this.svg,svgElements:this.svgElements,options:this.options,groups:this.groups};var n=this;this.body.emitter.on("verticalDrag",function(){n.dom.lineContainer.style.top=n.body.domProps.scrollTop+"px"})}var s=i(58),r=o(s),a=i(1),h=i(90),d=i(124),l=i(147);n.prototype=new d,n.prototype.addGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1},n.prototype.updateGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.amountOfGroups+=1),this.groups[t]=e},n.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},n.prototype.setOptions=function(t){if(t){var e=!1;this.options.orientation!=t.orientation&&void 0!==t.orientation&&(e=!0);var i=["orientation","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","width","visible","left","right","alignZeros"];a.selectiveDeepExtend(i,this.options,t),this.minWidth=Number((""+this.options.width).replace("px","")),e===!0&&this.dom.frame&&(this.hide(),this.show())}},n.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.style.width=this.options.width,this.dom.frame.style.height=this.height,this.dom.lineContainer=document.createElement("div"),this.dom.lineContainer.style.width="100%",this.dom.lineContainer.style.height=this.height,this.dom.lineContainer.style.position="relative",this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.height="100%",this.svg.style.width="100%",this.svg.style.display="block",this.dom.frame.appendChild(this.svg)},n.prototype._redrawGroupIcons=function(){h.prepareElements(this.svgElements);var t,e=this.options.iconWidth,i=15,o=4,n=o+.5*i;t="left"===this.options.orientation?o:this.width-e-o;var s=(0,r.default)(this.groups);s.sort(function(t,e){return t<e?-1:1});for(var a=0;a<s.length;a++){var d=s[a];this.groups[d].visible!==!0||void 0!==this.linegraphOptions.visibility[d]&&this.linegraphOptions.visibility[d]!==!0||(this.groups[d].getLegend(e,i,this.framework,t,n),n+=i+o)}h.cleanupElements(this.svgElements),this.iconsRemoved=!1},n.prototype._cleanupIcons=function(){this.iconsRemoved===!1&&(h.prepareElements(this.svgElements),h.cleanupElements(this.svgElements),this.iconsRemoved=!0)},n.prototype.show=function(){this.hidden=!1,this.dom.frame.parentNode||("left"===this.options.orientation?this.body.dom.left.appendChild(this.dom.frame):this.body.dom.right.appendChild(this.dom.frame)),this.dom.lineContainer.parentNode||this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer)},n.prototype.hide=function(){this.hidden=!0,this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.lineContainer.parentNode&&this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer)},n.prototype.setRange=function(t,e){this.range.start=t,this.range.end=e},n.prototype.redraw=function(){var t=!1,e=0;this.dom.lineContainer.style.top=this.body.domProps.scrollTop+"px";for(var i in this.groups)this.groups.hasOwnProperty(i)&&(this.groups[i].visible!==!0||void 0!==this.linegraphOptions.visibility[i]&&this.linegraphOptions.visibility[i]!==!0||e++);if(0===this.amountOfGroups||0===e)this.hide();else{this.show(),this.height=Number(this.linegraphSVG.style.height.replace("px","")),this.dom.lineContainer.style.height=this.height+"px",this.width=this.options.visible===!0?Number((""+this.options.width).replace("px","")):0;var o=this.props,n=this.dom.frame;n.className="vis-data-axis",this._calculateCharSize();var s=this.options.orientation,r=this.options.showMinorLabels,a=this.options.showMajorLabels;o.minorLabelHeight=r?o.minorCharHeight:0,o.majorLabelHeight=a?o.majorCharHeight:0,o.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,o.minorLineHeight=1,o.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,o.majorLineHeight=1,"left"===s?(n.style.top="0",n.style.left="0",n.style.bottom="",n.style.width=this.width+"px",n.style.height=this.height+"px",this.props.width=this.body.domProps.left.width,this.props.height=this.body.domProps.left.height):(n.style.top="",n.style.bottom="0",n.style.left="0",n.style.width=this.width+"px",n.style.height=this.height+"px",this.props.width=this.body.domProps.right.width,this.props.height=this.body.domProps.right.height),t=this._redrawLabels(),t=this._isResized()||t,this.options.icons===!0?this._redrawGroupIcons():this._cleanupIcons(),this._redrawTitle(s)}return t},n.prototype._redrawLabels=function(){var t=this,e=!1;h.prepareElements(this.DOMelements.lines),h.prepareElements(this.DOMelements.labels);var i=this.options.orientation,o=void 0!=this.options[i].range?this.options[i].range:{},n=!0;void 0!=o.max&&(this.range.end=o.max,n=!1);var s=!0;void 0!=o.min&&(this.range.start=o.min,s=!1),this.scale=new l(this.range.start,this.range.end,s,n,this.dom.frame.offsetHeight,this.props.majorCharHeight,this.options.alignZeros,this.options[i].format),this.master===!1&&void 0!=this.masterAxis&&this.scale.followScale(this.masterAxis.scale),this.maxLabelSize=0;var r=this.scale.getLines();r.forEach(function(e){var o=e.y,n=e.major;t.options.showMinorLabels&&n===!1&&t._redrawLabel(o-2,e.val,i,"vis-y-axis vis-minor",t.props.minorCharHeight),n&&o>=0&&t._redrawLabel(o-2,e.val,i,"vis-y-axis vis-major",t.props.majorCharHeight),t.master===!0&&(n?t._redrawLine(o,i,"vis-grid vis-horizontal vis-major",t.options.majorLinesOffset,t.props.majorLineWidth):t._redrawLine(o,i,"vis-grid vis-horizontal vis-minor",t.options.minorLinesOffset,t.props.minorLineWidth))});var a=0;void 0!==this.options[i].title&&void 0!==this.options[i].title.text&&(a=this.props.titleCharHeight);var d=this.options.icons===!0?Math.max(this.options.iconWidth,a)+this.options.labelOffsetX+15:a+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-d&&this.options.visible===!0?(this.width=this.maxLabelSize+d,this.options.width=this.width+"px",h.cleanupElements(this.DOMelements.lines),h.cleanupElements(this.DOMelements.labels),this.redraw(),e=!0):this.maxLabelSize<this.width-d&&this.options.visible===!0&&this.width>this.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+d),this.options.width=this.width+"px",h.cleanupElements(this.DOMelements.lines),h.cleanupElements(this.DOMelements.labels),this.redraw(),e=!0):(h.cleanupElements(this.DOMelements.lines),h.cleanupElements(this.DOMelements.labels),e=!1),e},n.prototype.convertValue=function(t){return this.scale.convertValue(t)},n.prototype.screenToValue=function(t){return this.scale.screenToValue(t)},n.prototype._redrawLabel=function(t,e,i,o,n){var s=h.getDOMElement("div",this.DOMelements.labels,this.dom.frame);s.className=o,s.innerHTML=e,"left"===i?(s.style.left="-"+this.options.labelOffsetX+"px",s.style.textAlign="right"):(s.style.right="-"+this.options.labelOffsetX+"px",s.style.textAlign="left"),s.style.top=t-.5*n+this.options.labelOffsetY+"px",e+="";var r=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSize<e.length*r&&(this.maxLabelSize=e.length*r)},n.prototype._redrawLine=function(t,e,i,o,n){if(this.master===!0){var s=h.getDOMElement("div",this.DOMelements.lines,this.dom.lineContainer);s.className=i,s.innerHTML="","left"===e?s.style.left=this.width-o+"px":s.style.right=this.width-o+"px",s.style.width=n+"px",s.style.top=t+"px"}},n.prototype._redrawTitle=function(t){if(h.prepareElements(this.DOMelements.title),void 0!==this.options[t].title&&void 0!==this.options[t].title.text){var e=h.getDOMElement("div",this.DOMelements.title,this.dom.frame);e.className="vis-y-axis vis-title vis-"+t,e.innerHTML=this.options[t].title.text,void 0!==this.options[t].title.style&&a.addCssText(e,this.options[t].title.style),"left"===t?e.style.left=this.props.titleCharHeight+"px":e.style.right=this.props.titleCharHeight+"px",e.style.width=this.height+"px"}h.cleanupElements(this.DOMelements.title)},n.prototype._calculateCharSize=function(){if(!("minorCharHeight"in this.props)){var t=document.createTextNode("0"),e=document.createElement("div");e.className="vis-y-axis vis-minor vis-measure",e.appendChild(t),this.dom.frame.appendChild(e),this.props.minorCharHeight=e.clientHeight,this.props.minorCharWidth=e.clientWidth,this.dom.frame.removeChild(e)}if(!("majorCharHeight"in this.props)){var i=document.createTextNode("0"),o=document.createElement("div");o.className="vis-y-axis vis-major vis-measure",o.appendChild(i),this.dom.frame.appendChild(o),this.props.majorCharHeight=o.clientHeight,this.props.majorCharWidth=o.clientWidth,this.dom.frame.removeChild(o)}if(!("titleCharHeight"in this.props)){var n=document.createTextNode("0"),s=document.createElement("div");s.className="vis-y-axis vis-title vis-measure",s.appendChild(n),this.dom.frame.appendChild(s),this.props.titleCharHeight=s.clientHeight,this.props.titleCharWidth=s.clientWidth,this.dom.frame.removeChild(s)}},t.exports=n},function(t,e){function i(t,e,i,o,n,s){var r=arguments.length>6&&void 0!==arguments[6]&&arguments[6],a=arguments.length>7&&void 0!==arguments[7]&&arguments[7];if(this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.customLines=null,this.containerHeight=n,this.majorCharHeight=s,this._start=t,this._end=e,this.scale=1,this.minorStepIdx=-1,this.magnitudefactor=1,this.determineScale(),this.zeroAlign=r,this.autoScaleStart=i,this.autoScaleEnd=o,this.formattingFunction=a,i||o){var h=this,d=function(t){var e=t-t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx]);return t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx])>.5*(h.magnitudefactor*h.minorSteps[h.minorStepIdx])?e+h.magnitudefactor*h.minorSteps[h.minorStepIdx]:e};i&&(this._start-=2*this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._start=d(this._start)),o&&(this._end+=this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._end=d(this._end)),this.determineScale()}}i.prototype.setCharHeight=function(t){this.majorCharHeight=t},i.prototype.setHeight=function(t){this.containerHeight=t},i.prototype.determineScale=function(){var t=this._end-this._start;this.scale=this.containerHeight/t;var e=this.majorCharHeight/this.scale,i=t>0?Math.round(Math.log(t)/Math.LN10):0;this.minorStepIdx=-1,this.magnitudefactor=Math.pow(10,i);var o=0;i<0&&(o=i);for(var n=!1,s=o;Math.abs(s)<=Math.abs(i);s++){this.magnitudefactor=Math.pow(10,s);for(var r=0;r<this.minorSteps.length;r++){var a=this.magnitudefactor*this.minorSteps[r];if(a>=e){n=!0,this.minorStepIdx=r;break}}if(n===!0)break}},i.prototype.is_major=function(t){return t%(this.magnitudefactor*this.majorSteps[this.minorStepIdx])===0},i.prototype.getStep=function(){return this.magnitudefactor*this.minorSteps[this.minorStepIdx]},i.prototype.getFirstMajor=function(){var t=this.magnitudefactor*this.majorSteps[this.minorStepIdx];return this.convertValue(this._start+(t-this._start%t)%t)},i.prototype.formatValue=function(t){var e=t.toPrecision(5);return"function"==typeof this.formattingFunction&&(e=this.formattingFunction(t)),"number"==typeof e?""+e:"string"==typeof e?e:t.toPrecision(5)},i.prototype.getLines=function(){for(var t=[],e=this.getStep(),i=(e-this._start%e)%e,o=this._start+i;this._end-o>1e-5;o+=e)o!=this._start&&t.push({major:this.is_major(o),y:this.convertValue(o),val:this.formatValue(o)});return t},i.prototype.followScale=function(t){var e=this.minorStepIdx,i=this._start,o=this._end,n=this,s=function(){n.magnitudefactor*=2},r=function(){n.magnitudefactor/=2};t.minorStepIdx<=1&&this.minorStepIdx<=1||t.minorStepIdx>1&&this.minorStepIdx>1||(t.minorStepIdx<this.minorStepIdx?(this.minorStepIdx=1,2==e?s():(s(),s())):(this.minorStepIdx=2,1==e?r():(r(),r())));for(var a=(t.getLines(),t.convertValue(0)),h=t.getStep()*t.scale,d=!1,l=0;!d&&l++<5;){this.scale=h/(this.minorSteps[this.minorStepIdx]*this.magnitudefactor);var u=this.containerHeight/this.scale;this._start=i,this._end=this._start+u;var c=this._end*this.scale,p=this.magnitudefactor*this.majorSteps[this.minorStepIdx],f=this.getFirstMajor()-t.getFirstMajor();if(this.zeroAlign){var m=a-c;this._end+=m/this.scale,this._start=this._end-u}else this.autoScaleStart?(this._start-=f/this.scale,this._end=this._start+u):(this._start+=p-f/this.scale,this._end=this._start+u);if(!this.autoScaleEnd&&this._end>o+1e-5)r(),d=!1;else{if(!this.autoScaleStart&&this._start<i-1e-5){if(!(this.zeroAlign&&i>=0)){r(),d=!1;continue}console.warn("Can't adhere to given 'min' range, due to zeroalign")}this.autoScaleStart&&this.autoScaleEnd&&u<o-i?(s(),d=!1):d=!0}}},i.prototype.convertValue=function(t){return this.containerHeight-(t-this._start)*this.scale},i.prototype.screenToValue=function(t){return(this.containerHeight-t)/this.scale+this._start},t.exports=i},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i,o){this.id=e;var n=["sampling","style","sort","yAxisOrientation","barChart","drawPoints","shaded","interpolation","zIndex","excludeFromStacking","excludeFromLegend"];this.options=a.selectiveBridgeObject(n,i),this.usingDefaultStyle=void 0===t.className,this.groupsUsingDefaultStyles=o,this.zeroPosition=0,this.update(t),1==this.usingDefaultStyle&&(this.groupsUsingDefaultStyles[0]+=1),this.itemsData=[],this.visible=void 0===t.visible||t.visible}var s=i(62),r=o(s),a=i(1),h=(i(90),i(149)),d=i(151),l=i(150);n.prototype.setItems=function(t){null!=t?(this.itemsData=t,1==this.options.sort&&a.insertSort(this.itemsData,function(t,e){return t.x>e.x?1:-1})):this.itemsData=[]},n.prototype.getItems=function(){return this.itemsData},n.prototype.setZeroPosition=function(t){this.zeroPosition=t},n.prototype.setOptions=function(t){if(void 0!==t){var e=["sampling","style","sort","yAxisOrientation","barChart","zIndex","excludeFromStacking","excludeFromLegend"];a.selectiveDeepExtend(e,this.options,t),"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),a.mergeOptions(this.options,t,"interpolation"),a.mergeOptions(this.options,t,"drawPoints"),a.mergeOptions(this.options,t,"shaded"),t.interpolation&&"object"==(0,r.default)(t.interpolation)&&t.interpolation.parametrization&&("uniform"==t.interpolation.parametrization?this.options.interpolation.alpha=0:"chordal"==t.interpolation.parametrization?this.options.interpolation.alpha=1:(this.options.interpolation.parametrization="centripetal",this.options.interpolation.alpha=.5))}},n.prototype.update=function(t){this.group=t,this.content=t.content||"graph",this.className=t.className||this.className||"vis-graph-group"+this.groupsUsingDefaultStyles[0]%10,this.visible=void 0===t.visible||t.visible,this.style=t.style,this.setOptions(t.options)},n.prototype.getLegend=function(t,e,i,o,n){if(void 0==i||null==i){var s=document.createElementNS("http://www.w3.org/2000/svg","svg");i={svg:s,svgElements:{},options:this.options,groups:[this]}}switch(void 0!=o&&null!=o||(o=0),void 0!=n&&null!=n||(n=.5*e),this.options.style){case"line":d.drawIcon(this,o,n,t,e,i);break;case"points":case"point":l.drawIcon(this,o,n,t,e,i);break;case"bar":h.drawIcon(this,o,n,t,e,i)}return{icon:i.svg,label:this.content,orientation:this.options.yAxisOrientation}},n.prototype.getYRange=function(t){for(var e=t[0].y,i=t[0].y,o=0;o<t.length;o++)e=e>t[o].y?t[o].y:e,i=i<t[o].y?t[o].y:i;return{min:e,max:i,yAxisOrientation:this.options.yAxisOrientation}},t.exports=n},function(t,e,i){function o(t,e){}var n=i(90),s=i(150);o.drawIcon=function(t,e,i,o,s,r){var a=.5*s,h=n.getSVGElement("rect",r.svgElements,r.svg);h.setAttributeNS(null,"x",e),h.setAttributeNS(null,"y",i-a),h.setAttributeNS(null,"width",o),h.setAttributeNS(null,"height",2*a),h.setAttributeNS(null,"class","vis-outline");var d=Math.round(.3*o),l=t.options.barChart.width,u=l/d,c=Math.round(.4*s),p=Math.round(.75*s),f=Math.round((o-2*d)/3);if(n.drawBar(e+.5*d+f,i+a-c-1,d,c,t.className+" vis-bar",r.svgElements,r.svg,t.style),n.drawBar(e+1.5*d+f+2,i+a-p-1,d,p,t.className+" vis-bar",r.svgElements,r.svg,t.style),1==t.options.drawPoints.enabled){var m={style:t.options.drawPoints.style,styles:t.options.drawPoints.styles,size:t.options.drawPoints.size/u,className:t.className};n.drawPoint(e+.5*d+f,i+a-c-1,m,r.svgElements,r.svg),n.drawPoint(e+1.5*d+f+2,i+a-p-1,m,r.svgElements,r.svg)}},o.draw=function(t,e,i){var r,a,h,d,l,u,c=[],p={},f=0;for(l=0;l<t.length;l++)if(d=i.groups[t[l]],"bar"===d.options.style&&d.visible===!0&&(void 0===i.options.groups.visibility[t[l]]||i.options.groups.visibility[t[l]]===!0))for(u=0;u<e[t[l]].length;u++)c.push({screen_x:e[t[l]][u].screen_x,screen_y:e[t[l]][u].screen_y,x:e[t[l]][u].x,y:e[t[l]][u].y,groupId:t[l],label:e[t[l]][u].label}),f+=1;if(0!==f)for(c.sort(function(t,e){return t.screen_x===e.screen_x?t.groupId<e.groupId?-1:1:t.screen_x-e.screen_x}),o._getDataIntersections(p,c),l=0;l<c.length;l++){d=i.groups[c[l].groupId];var m=void 0!=d.options.barChart.minWidth?d.options.barChart.minWidth:.1*d.options.barChart.width;a=c[l].screen_x;var v=0;if(void 0===p[a])l+1<c.length&&(r=Math.abs(c[l+1].screen_x-a)),h=o._getSafeDrawData(r,d,m);else{var g=l+(p[a].amount-p[a].resolved);l-(p[a].resolved+1);g<c.length&&(r=Math.abs(c[g].screen_x-a)),h=o._getSafeDrawData(r,d,m),p[a].resolved+=1,d.options.stack===!0&&d.options.excludeFromStacking!==!0?c[l].screen_y<d.zeroPosition?(v=p[a].accumulatedNegative,p[a].accumulatedNegative+=d.zeroPosition-c[l].screen_y):(v=p[a].accumulatedPositive,p[a].accumulatedPositive+=d.zeroPosition-c[l].screen_y):d.options.barChart.sideBySide===!0&&(h.width=h.width/p[a].amount,h.offset+=p[a].resolved*h.width-.5*h.width*(p[a].amount+1))}if(n.drawBar(c[l].screen_x+h.offset,c[l].screen_y-v,h.width,d.zeroPosition-c[l].screen_y,d.className+" vis-bar",i.svgElements,i.svg,d.style),d.options.drawPoints.enabled===!0){var y={screen_x:c[l].screen_x,screen_y:c[l].screen_y-v,x:c[l].x,y:c[l].y,groupId:c[l].groupId,label:c[l].label};s.draw([y],d,i,h.offset)}}},o._getDataIntersections=function(t,e){for(var i,o=0;o<e.length;o++)o+1<e.length&&(i=Math.abs(e[o+1].screen_x-e[o].screen_x)),o>0&&(i=Math.min(i,Math.abs(e[o-1].screen_x-e[o].screen_x))),0===i&&(void 0===t[e[o].screen_x]&&(t[e[o].screen_x]={amount:0,resolved:0,accumulatedPositive:0,accumulatedNegative:0}),t[e[o].screen_x].amount+=1)},o._getSafeDrawData=function(t,e,i){var o,n;return t<e.options.barChart.width&&t>0?(o=t<i?i:t,n=0,"left"===e.options.barChart.align?n-=.5*t:"right"===e.options.barChart.align&&(n+=.5*t)):(o=e.options.barChart.width,n=0,"left"===e.options.barChart.align?n-=.5*e.options.barChart.width:"right"===e.options.barChart.align&&(n+=.5*e.options.barChart.width)),{width:o,offset:n}},o.getStackedYRange=function(t,e,i,n,s){if(t.length>0){t.sort(function(t,e){return t.screen_x===e.screen_x?t.groupId<e.groupId?-1:1:t.screen_x-e.screen_x});var r={};o._getDataIntersections(r,t),e[n]=o._getStackedYRange(r,t),e[n].yAxisOrientation=s,i.push(n)}},o._getStackedYRange=function(t,e){for(var i,o=e[0].screen_y,n=e[0].screen_y,s=0;s<e.length;s++)i=e[s].screen_x,void 0===t[i]?(o=o>e[s].screen_y?e[s].screen_y:o,n=n<e[s].screen_y?e[s].screen_y:n):e[s].screen_y<0?t[i].accumulatedNegative+=e[s].screen_y:t[i].accumulatedPositive+=e[s].screen_y;for(var r in t)t.hasOwnProperty(r)&&(o=o>t[r].accumulatedNegative?t[r].accumulatedNegative:o,o=o>t[r].accumulatedPositive?t[r].accumulatedPositive:o,n=n<t[r].accumulatedNegative?t[r].accumulatedNegative:n,n=n<t[r].accumulatedPositive?t[r].accumulatedPositive:n);return{min:o,max:n}},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){}function s(t,e){return e="undefined"==typeof e?{}:e,{style:e.style||t.options.drawPoints.style,styles:e.styles||t.options.drawPoints.styles,size:e.size||t.options.drawPoints.size,className:e.className||t.className}}function r(t,e){var i=void 0;return t.options&&t.options.drawPoints&&t.options.drawPoints.onRender&&"function"==typeof t.options.drawPoints.onRender&&(i=t.options.drawPoints.onRender),e.group.options&&e.group.options.drawPoints&&e.group.options.drawPoints.onRender&&"function"==typeof e.group.options.drawPoints.onRender&&(i=e.group.options.drawPoints.onRender),i}var a=i(62),h=o(a),d=i(90);n.draw=function(t,e,i,o){o=o||0;for(var n=r(i,e),a=0;a<t.length;a++)if(n){var l=n(t[a],e);l!==!0&&"object"!==("undefined"==typeof l?"undefined":(0,h.default)(l))||d.drawPoint(t[a].screen_x+o,t[a].screen_y,s(e,l),i.svgElements,i.svg,t[a].label)}else d.drawPoint(t[a].screen_x+o,t[a].screen_y,s(e),i.svgElements,i.svg,t[a].label)},n.drawIcon=function(t,e,i,o,n,r){var a=.5*n,h=d.getSVGElement("rect",r.svgElements,r.svg);h.setAttributeNS(null,"x",e),h.setAttributeNS(null,"y",i-a),h.setAttributeNS(null,"width",o),h.setAttributeNS(null,"height",2*a),h.setAttributeNS(null,"class","vis-outline"),d.drawPoint(e+.5*o,i,s(t),r.svgElements,r.svg)},t.exports=n},function(t,e,i){function o(t,e){}var n=i(90);o.calcPath=function(t,e){if(null!=t&&t.length>0){var i=[];return i=1==e.options.interpolation.enabled?o._catmullRom(t,e):o._linear(t)}},o.drawIcon=function(t,e,i,o,s,r){var a,h,d=.5*s,l=n.getSVGElement("rect",r.svgElements,r.svg);if(l.setAttributeNS(null,"x",e),l.setAttributeNS(null,"y",i-d),l.setAttributeNS(null,"width",o),l.setAttributeNS(null,"height",2*d),l.setAttributeNS(null,"class","vis-outline"),a=n.getSVGElement("path",r.svgElements,r.svg),a.setAttributeNS(null,"class",t.className),void 0!==t.style&&a.setAttributeNS(null,"style",t.style),a.setAttributeNS(null,"d","M"+e+","+i+" L"+(e+o)+","+i),1==t.options.shaded.enabled&&(h=n.getSVGElement("path",r.svgElements,r.svg),"top"==t.options.shaded.orientation?h.setAttributeNS(null,"d","M"+e+", "+(i-d)+"L"+e+","+i+" L"+(e+o)+","+i+" L"+(e+o)+","+(i-d)):h.setAttributeNS(null,"d","M"+e+","+i+" L"+e+","+(i+d)+" L"+(e+o)+","+(i+d)+"L"+(e+o)+","+i),h.setAttributeNS(null,"class",t.className+" vis-icon-fill"),void 0!==t.options.shaded.style&&""!==t.options.shaded.style&&h.setAttributeNS(null,"style",t.options.shaded.style)),1==t.options.drawPoints.enabled){var u={style:t.options.drawPoints.style,styles:t.options.drawPoints.styles,size:t.options.drawPoints.size,className:t.className};n.drawPoint(e+.5*o,i,u,r.svgElements,r.svg)}},o.drawShading=function(t,e,i,o){if(1==e.options.shaded.enabled){var s=Number(o.svg.style.height.replace("px","")),r=n.getSVGElement("path",o.svgElements,o.svg),a="L";1==e.options.interpolation.enabled&&(a="C");var h,d=0;d="top"==e.options.shaded.orientation?0:"bottom"==e.options.shaded.orientation?s:Math.min(Math.max(0,e.zeroPosition),s),h="group"==e.options.shaded.orientation&&null!=i&&void 0!=i?"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" L"+i[i.length-1][0]+","+i[i.length-1][1]+" "+this.serializePath(i,a,!0)+i[0][0]+","+i[0][1]+" Z":"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" V"+d+" H"+t[0][0]+" Z",r.setAttributeNS(null,"class",e.className+" vis-fill"),void 0!==e.options.shaded.style&&r.setAttributeNS(null,"style",e.options.shaded.style),r.setAttributeNS(null,"d",h)}},o.draw=function(t,e,i){if(null!=t&&void 0!=t){var o=n.getSVGElement("path",i.svgElements,i.svg);o.setAttributeNS(null,"class",e.className),void 0!==e.style&&o.setAttributeNS(null,"style",e.style);var s="L";1==e.options.interpolation.enabled&&(s="C"),o.setAttributeNS(null,"d","M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,s,!1))}},o.serializePath=function(t,e,i){if(t.length<2)return"";var o=e;if(i)for(var n=t.length-2;n>0;n--)o+=t[n][0]+","+t[n][1]+" ";else for(var n=1;n<t.length;n++)o+=t[n][0]+","+t[n][1]+" ";return o},o._catmullRomUniform=function(t){var e,i,o,n,s,r,a=[];a.push([Math.round(t[0].screen_x),Math.round(t[0].screen_y)]);for(var h=1/6,d=t.length,l=0;l<d-1;l++)e=0==l?t[0]:t[l-1],i=t[l],o=t[l+1],n=l+2<d?t[l+2]:o,s={screen_x:(-e.screen_x+6*i.screen_x+o.screen_x)*h,screen_y:(-e.screen_y+6*i.screen_y+o.screen_y)*h},r={screen_x:(i.screen_x+6*o.screen_x-n.screen_x)*h,screen_y:(i.screen_y+6*o.screen_y-n.screen_y)*h},a.push([s.screen_x,s.screen_y]),a.push([r.screen_x,r.screen_y]),a.push([o.screen_x,o.screen_y]);return a},o._catmullRom=function(t,e){var i=e.options.interpolation.alpha;if(0==i||void 0===i)return this._catmullRomUniform(t);var o,n,s,r,a,h,d,l,u,c,p,f,m,v,g,y,b,_,w,x=[];x.push([Math.round(t[0].screen_x),Math.round(t[0].screen_y)]);for(var k=t.length,O=0;O<k-1;O++)o=0==O?t[0]:t[O-1],n=t[O],s=t[O+1],r=O+2<k?t[O+2]:s,d=Math.sqrt(Math.pow(o.screen_x-n.screen_x,2)+Math.pow(o.screen_y-n.screen_y,2)),l=Math.sqrt(Math.pow(n.screen_x-s.screen_x,2)+Math.pow(n.screen_y-s.screen_y,2)),u=Math.sqrt(Math.pow(s.screen_x-r.screen_x,2)+Math.pow(s.screen_y-r.screen_y,2)),v=Math.pow(u,i),y=Math.pow(u,2*i),g=Math.pow(l,i),b=Math.pow(l,2*i),w=Math.pow(d,i),_=Math.pow(d,2*i),c=2*_+3*w*g+b,p=2*y+3*v*g+b,f=3*w*(w+g),f>0&&(f=1/f),m=3*v*(v+g),m>0&&(m=1/m),a={screen_x:(-b*o.screen_x+c*n.screen_x+_*s.screen_x)*f,screen_y:(-b*o.screen_y+c*n.screen_y+_*s.screen_y)*f},h={screen_x:(y*n.screen_x+p*s.screen_x-b*r.screen_x)*m,screen_y:(y*n.screen_y+p*s.screen_y-b*r.screen_y)*m},0==a.screen_x&&0==a.screen_y&&(a=n),0==h.screen_x&&0==h.screen_y&&(h=s),x.push([a.screen_x,a.screen_y]),x.push([h.screen_x,h.screen_y]),x.push([s.screen_x,s.screen_y]);return x},o._linear=function(t){for(var e=[],i=0;i<t.length;i++)e.push([t[i].screen_x,t[i].screen_y]);return e},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i,o){this.body=t,this.defaultOptions={enabled:!1,icons:!0,iconSize:20,iconSpacing:6,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-right"}},this.side=i,this.options=a.extend({},this.defaultOptions),this.linegraphOptions=o,this.svgElements={},this.dom={},this.groups={},this.amountOfGroups=0,this._create(),this.framework={svg:this.svg,svgElements:this.svgElements,options:this.options,groups:this.groups},this.setOptions(e)}var s=i(58),r=o(s),a=i(1),h=i(90),d=i(124);n.prototype=new d,n.prototype.clear=function(){this.groups={},this.amountOfGroups=0},n.prototype.addGroup=function(t,e){1!=e.options.excludeFromLegend&&(this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1)},n.prototype.updateGroup=function(t,e){this.groups[t]=e},n.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},n.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-legend",this.dom.frame.style.position="absolute",this.dom.frame.style.top="10px",this.dom.frame.style.display="block",this.dom.textArea=document.createElement("div"),this.dom.textArea.className="vis-legend-text",this.dom.textArea.style.position="relative",this.dom.textArea.style.top="0px",this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.width=this.options.iconSize+5+"px",this.svg.style.height="100%",this.dom.frame.appendChild(this.svg),this.dom.frame.appendChild(this.dom.textArea)},n.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},n.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},n.prototype.setOptions=function(t){var e=["enabled","orientation","icons","left","right"];a.selectiveDeepExtend(e,this.options,t)},n.prototype.redraw=function(){var t=0,e=(0,r.default)(this.groups);e.sort(function(t,e){return t<e?-1:1});for(var i=0;i<e.length;i++){var o=e[i];1!=this.groups[o].visible||void 0!==this.linegraphOptions.visibility[o]&&1!=this.linegraphOptions.visibility[o]||t++}if(0==this.options[this.side].visible||0==this.amountOfGroups||0==this.options.enabled||0==t)this.hide();else{if(this.show(),"top-left"==this.options[this.side].position||"bottom-left"==this.options[this.side].position?(this.dom.frame.style.left="4px",
-this.dom.frame.style.textAlign="left",this.dom.textArea.style.textAlign="left",this.dom.textArea.style.left=this.options.iconSize+15+"px",this.dom.textArea.style.right="",this.svg.style.left="0px",this.svg.style.right=""):(this.dom.frame.style.right="4px",this.dom.frame.style.textAlign="right",this.dom.textArea.style.textAlign="right",this.dom.textArea.style.right=this.options.iconSize+15+"px",this.dom.textArea.style.left="",this.svg.style.right="0px",this.svg.style.left=""),"top-left"==this.options[this.side].position||"top-right"==this.options[this.side].position)this.dom.frame.style.top=4-Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.bottom="";else{var n=this.body.domProps.center.height-this.body.domProps.centerContainer.height;this.dom.frame.style.bottom=4+n+Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.top=""}0==this.options.icons?(this.dom.frame.style.width=this.dom.textArea.offsetWidth+10+"px",this.dom.textArea.style.right="",this.dom.textArea.style.left="",this.svg.style.width="0px"):(this.dom.frame.style.width=this.options.iconSize+15+this.dom.textArea.offsetWidth+10+"px",this.drawLegendIcons());for(var s="",i=0;i<e.length;i++){var o=e[i];1!=this.groups[o].visible||void 0!==this.linegraphOptions.visibility[o]&&1!=this.linegraphOptions.visibility[o]||(s+=this.groups[o].content+"<br />")}this.dom.textArea.innerHTML=s,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},n.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){var t=(0,r.default)(this.groups);t.sort(function(t,e){return t<e?-1:1}),h.resetElements(this.svgElements);var e=window.getComputedStyle(this.dom.frame).paddingTop,i=Number(e.replace("px","")),o=i,n=this.options.iconSize,s=.75*this.options.iconSize,a=i+.5*s+3;this.svg.style.width=n+5+i+"px";for(var d=0;d<t.length;d++){var l=t[d];1!=this.groups[l].visible||void 0!==this.linegraphOptions.visibility[l]&&1!=this.linegraphOptions.visibility[l]||(this.groups[l].getLegend(n,s,this.framework,o,a),a+=s+this.options.iconSpacing)}}},t.exports=n},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var i="string",o="boolean",n="number",s="array",r="date",a="object",h="dom",d="moment",l="any",u={configure:{enabled:{boolean:o},filter:{boolean:o,function:"function"},container:{dom:h},__type__:{object:a,boolean:o,function:"function"}},yAxisOrientation:{string:["left","right"]},defaultGroup:{string:i},sort:{boolean:o},sampling:{boolean:o},stack:{boolean:o},graphHeight:{string:i,number:n},shaded:{enabled:{boolean:o},orientation:{string:["bottom","top","zero","group"]},groupId:{object:a},__type__:{boolean:o,object:a}},style:{string:["line","bar","points"]},barChart:{width:{number:n},minWidth:{number:n},sideBySide:{boolean:o},align:{string:["left","center","right"]},__type__:{object:a}},interpolation:{enabled:{boolean:o},parametrization:{string:["centripetal","chordal","uniform"]},alpha:{number:n},__type__:{object:a,boolean:o}},drawPoints:{enabled:{boolean:o},onRender:{function:"function"},size:{number:n},style:{string:["square","circle"]},__type__:{object:a,boolean:o,function:"function"}},dataAxis:{showMinorLabels:{boolean:o},showMajorLabels:{boolean:o},icons:{boolean:o},width:{string:i,number:n},visible:{boolean:o},alignZeros:{boolean:o},left:{range:{min:{number:n},max:{number:n},__type__:{object:a}},format:{function:"function"},title:{text:{string:i,number:n},style:{string:i},__type__:{object:a}},__type__:{object:a}},right:{range:{min:{number:n},max:{number:n},__type__:{object:a}},format:{function:"function"},title:{text:{string:i,number:n},style:{string:i},__type__:{object:a}},__type__:{object:a}},__type__:{object:a}},legend:{enabled:{boolean:o},icons:{boolean:o},left:{visible:{boolean:o},position:{string:["top-right","bottom-right","top-left","bottom-left"]},__type__:{object:a}},right:{visible:{boolean:o},position:{string:["top-right","bottom-right","top-left","bottom-left"]},__type__:{object:a}},__type__:{object:a,boolean:o}},groups:{visibility:{any:l},__type__:{object:a}},autoResize:{boolean:o},throttleRedraw:{number:n},clickToUse:{boolean:o},end:{number:n,date:r,string:i,moment:d},format:{minorLabels:{millisecond:{string:i,undefined:"undefined"},second:{string:i,undefined:"undefined"},minute:{string:i,undefined:"undefined"},hour:{string:i,undefined:"undefined"},weekday:{string:i,undefined:"undefined"},day:{string:i,undefined:"undefined"},month:{string:i,undefined:"undefined"},year:{string:i,undefined:"undefined"},__type__:{object:a}},majorLabels:{millisecond:{string:i,undefined:"undefined"},second:{string:i,undefined:"undefined"},minute:{string:i,undefined:"undefined"},hour:{string:i,undefined:"undefined"},weekday:{string:i,undefined:"undefined"},day:{string:i,undefined:"undefined"},month:{string:i,undefined:"undefined"},year:{string:i,undefined:"undefined"},__type__:{object:a}},__type__:{object:a}},moment:{function:"function"},height:{string:i,number:n},hiddenDates:{start:{date:r,number:n,string:i,moment:d},end:{date:r,number:n,string:i,moment:d},repeat:{string:i},__type__:{object:a,array:s}},locale:{string:i},locales:{__any__:{any:l},__type__:{object:a}},max:{date:r,number:n,string:i,moment:d},maxHeight:{number:n,string:i},maxMinorChars:{number:n},min:{date:r,number:n,string:i,moment:d},minHeight:{number:n,string:i},moveable:{boolean:o},multiselect:{boolean:o},orientation:{string:i},showCurrentTime:{boolean:o},showMajorLabels:{boolean:o},showMinorLabels:{boolean:o},start:{date:r,number:n,string:i,moment:d},timeAxis:{scale:{string:i,undefined:"undefined"},step:{number:n,undefined:"undefined"},__type__:{object:a}},width:{string:i,number:n},zoomable:{boolean:o},zoomKey:{string:["ctrlKey","altKey","metaKey",""]},zoomMax:{number:n},zoomMin:{number:n},zIndex:{number:n},__type__:{object:a}},c={global:{sort:!0,sampling:!0,stack:!1,shaded:{enabled:!1,orientation:["zero","top","bottom","group"]},style:["line","bar","points"],barChart:{width:[50,5,100,5],minWidth:[50,5,100,5],sideBySide:!1,align:["left","center","right"]},interpolation:{enabled:!0,parametrization:["centripetal","chordal","uniform"]},drawPoints:{enabled:!0,size:[6,2,30,1],style:["square","circle"]},dataAxis:{showMinorLabels:!0,showMajorLabels:!0,icons:!1,width:[40,0,200,1],visible:!0,alignZeros:!0,left:{title:{text:"",style:""}},right:{title:{text:"",style:""}}},legend:{enabled:!1,icons:!0,left:{visible:!0,position:["top-right","bottom-right","top-left","bottom-left"]},right:{visible:!0,position:["top-right","bottom-right","top-left","bottom-left"]}},autoResize:!0,clickToUse:!1,end:"",format:{minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",month:"YYYY",year:""}},height:"",locale:"",max:"",maxHeight:"",maxMinorChars:[7,0,20,1],min:"",minHeight:"",moveable:!0,orientation:["both","bottom","top"],showCurrentTime:!1,showMajorLabels:!0,showMinorLabels:!0,start:"",width:"100%",zoomable:!0,zoomKey:["ctrlKey","altKey","metaKey",""],zoomMax:[31536e10,10,31536e10,1],zoomMin:[10,10,31536e10,1],zIndex:0}};e.allOptions=u,e.configureOptions=c},function(t,e,i){e.util=i(1),e.DOMutil=i(90),e.DataSet=i(91),e.DataView=i(93),e.Queue=i(92),e.Network=i(155),e.network={Images:i(156),dotparser:i(224),gephiParser:i(225),allOptions:i(220)},e.network.convertDot=function(t){return e.network.dotparser.DOTToGraph(t)},e.network.convertGephi=function(t,i){return e.network.gephiParser.parseGephi(t,i)},e.moment=i(84),e.Hammer=i(108),e.keycharm=i(111)},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i){var o=this;if(!(this instanceof n))throw new SyntaxError("Constructor must be called with the new operator");this.options={},this.defaultOptions={locale:"en",locales:Y,clickToUse:!1},F.extend(this.options,this.defaultOptions),this.body={container:t,nodes:{},nodeIndices:[],edges:{},edgeIndices:[],emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this),once:this.once.bind(this)},eventListeners:{onTap:function(){},onTouch:function(){},onDoubleTap:function(){},onHold:function(){},onDragStart:function(){},onDrag:function(){},onDragEnd:function(){},onMouseWheel:function(){},onPinch:function(){},onMouseMove:function(){},onRelease:function(){},onContext:function(){}},data:{nodes:null,edges:null},functions:{createNode:function(){},createEdge:function(){},getPointer:function(){}},modules:{},view:{scale:1,translation:{x:0,y:0}}},this.bindEventListeners(),this.images=new r.default(function(){return o.body.emitter.emit("_requestRedraw")}),this.groups=new h.default,this.canvas=new _.default(this.body),this.selectionHandler=new S.default(this.body,this.canvas),this.interactionHandler=new O.default(this.body,this.canvas,this.selectionHandler),this.view=new x.default(this.body,this.canvas),this.renderer=new y.default(this.body,this.canvas),this.physics=new f.default(this.body),this.layoutEngine=new C.default(this.body),this.clustering=new v.default(this.body),this.manipulation=new E.default(this.body,this.canvas,this.selectionHandler),this.nodesHandler=new l.default(this.body,this.images,this.groups,this.layoutEngine),this.edgesHandler=new c.default(this.body,this.images,this.groups),this.body.modules.kamadaKawai=new A.default(this.body,150,.05),this.body.modules.clustering=this.clustering,this.canvas._create(),this.setOptions(i),this.setData(e)}var s=i(156),r=o(s),a=i(157),h=o(a),d=i(158),l=o(d),u=i(191),c=o(u),p=i(200),f=o(p),m=i(209),v=o(m),g=i(212),y=o(g),b=i(213),_=o(b),w=i(214),x=o(w),k=i(215),O=o(k),D=i(217),S=o(D),M=i(218),C=o(M),T=i(219),E=o(T),P=i(114),I=o(P),N=i(122),z=o(N),R=i(220),L=i(221),A=o(L);i(223);var B=i(95),F=i(1),H=(i(91),i(93),i(224)),j=i(225),W=i(139),Y=i(226);B(n.prototype),n.prototype.setOptions=function(t){var e=this;if(void 0!==t){var i=z.default.validate(t,R.allOptions);i===!0&&console.log("%cErrors have been found in the supplied options object.",N.printStyle);var o=["locale","locales","clickToUse"];if(F.selectiveDeepExtend(o,this.options,t),t=this.layoutEngine.setOptions(t.layout,t),this.canvas.setOptions(t),this.groups.setOptions(t.groups),this.nodesHandler.setOptions(t.nodes),this.edgesHandler.setOptions(t.edges),this.physics.setOptions(t.physics),this.manipulation.setOptions(t.manipulation,t,this.options),this.interactionHandler.setOptions(t.interaction),this.renderer.setOptions(t.interaction),this.selectionHandler.setOptions(t.interaction),void 0!==t.groups&&this.body.emitter.emit("refreshNodes"),"configure"in t&&(this.configurator||(this.configurator=new I.default(this,this.body.container,R.configureOptions,this.canvas.pixelRatio)),this.configurator.setOptions(t.configure)),this.configurator&&this.configurator.options.enabled===!0){var n={nodes:{},edges:{},layout:{},interaction:{},manipulation:{},physics:{},global:{}};F.deepExtend(n.nodes,this.nodesHandler.options),F.deepExtend(n.edges,this.edgesHandler.options),F.deepExtend(n.layout,this.layoutEngine.options),F.deepExtend(n.interaction,this.selectionHandler.options),F.deepExtend(n.interaction,this.renderer.options),F.deepExtend(n.interaction,this.interactionHandler.options),F.deepExtend(n.manipulation,this.manipulation.options),F.deepExtend(n.physics,this.physics.options),F.deepExtend(n.global,this.canvas.options),F.deepExtend(n.global,this.options),this.configurator.setModuleOptions(n)}void 0!==t.clickToUse?t.clickToUse===!0?void 0===this.activator&&(this.activator=new W(this.canvas.frame),this.activator.on("change",function(){e.body.emitter.emit("activate")})):(void 0!==this.activator&&(this.activator.destroy(),delete this.activator),this.body.emitter.emit("activate")):this.body.emitter.emit("activate"),this.canvas.setSize(),this.body.emitter.emit("startSimulation")}},n.prototype._updateVisibleIndices=function(){var t=this.body.nodes,e=this.body.edges;this.body.nodeIndices=[],this.body.edgeIndices=[];for(var i in t)t.hasOwnProperty(i)&&t[i].options.hidden===!1&&this.body.nodeIndices.push(t[i].id);for(var o in e)e.hasOwnProperty(o)&&e[o].options.hidden===!1&&this.body.edgeIndices.push(e[o].id)},n.prototype.bindEventListeners=function(){var t=this;this.body.emitter.on("_dataChanged",function(){t._updateVisibleIndices(),t.body.emitter.emit("_requestRedraw"),t.body.emitter.emit("_dataUpdated")}),this.body.emitter.on("_dataUpdated",function(){t._updateValueRange(t.body.nodes),t._updateValueRange(t.body.edges),t.body.emitter.emit("startSimulation"),t.body.emitter.emit("_requestRedraw")})},n.prototype.setData=function(t){if(this.body.emitter.emit("resetPhysics"),this.body.emitter.emit("_resetData"),this.selectionHandler.unselectAll(),t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or  parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){console.log("The dot property has been deprecated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);");var e=H.DOTToGraph(t.dot);return void this.setData(e)}if(t&&t.gephi){console.log("The gephi property has been deprecated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);");var i=j.parseGephi(t.gephi);return void this.setData(i)}this.nodesHandler.setData(t&&t.nodes,!0),this.edgesHandler.setData(t&&t.edges,!0),this.body.emitter.emit("_dataChanged"),this.body.emitter.emit("_dataLoaded"),this.body.emitter.emit("initPhysics")},n.prototype.destroy=function(){this.body.emitter.emit("destroy"),this.body.emitter.off(),this.off(),delete this.groups,delete this.canvas,delete this.selectionHandler,delete this.interactionHandler,delete this.view,delete this.renderer,delete this.physics,delete this.layoutEngine,delete this.clustering,delete this.manipulation,delete this.nodesHandler,delete this.edgesHandler,delete this.configurator,delete this.images;for(var t in this.body.nodes)delete this.body.nodes[t];for(var e in this.body.edges)delete this.body.edges[e];F.recursiveDOMDelete(this.body.container)},n.prototype._updateValueRange=function(t){var e,i=void 0,o=void 0,n=0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),o=void 0===o?s:Math.max(s,o),n+=s)}if(void 0!==i&&void 0!==o)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,o,n)},n.prototype.isActive=function(){return!this.activator||this.activator.active},n.prototype.setSize=function(){return this.canvas.setSize.apply(this.canvas,arguments)},n.prototype.canvasToDOM=function(){return this.canvas.canvasToDOM.apply(this.canvas,arguments)},n.prototype.DOMtoCanvas=function(){return this.canvas.DOMtoCanvas.apply(this.canvas,arguments)},n.prototype.findNode=function(){return this.clustering.findNode.apply(this.clustering,arguments)},n.prototype.isCluster=function(){return this.clustering.isCluster.apply(this.clustering,arguments)},n.prototype.openCluster=function(){return this.clustering.openCluster.apply(this.clustering,arguments)},n.prototype.cluster=function(){return this.clustering.cluster.apply(this.clustering,arguments)},n.prototype.getNodesInCluster=function(){return this.clustering.getNodesInCluster.apply(this.clustering,arguments)},n.prototype.clusterByConnection=function(){return this.clustering.clusterByConnection.apply(this.clustering,arguments)},n.prototype.clusterByHubsize=function(){return this.clustering.clusterByHubsize.apply(this.clustering,arguments)},n.prototype.clusterOutliers=function(){return this.clustering.clusterOutliers.apply(this.clustering,arguments)},n.prototype.getSeed=function(){return this.layoutEngine.getSeed.apply(this.layoutEngine,arguments)},n.prototype.enableEditMode=function(){return this.manipulation.enableEditMode.apply(this.manipulation,arguments)},n.prototype.disableEditMode=function(){return this.manipulation.disableEditMode.apply(this.manipulation,arguments)},n.prototype.addNodeMode=function(){return this.manipulation.addNodeMode.apply(this.manipulation,arguments)},n.prototype.editNode=function(){return this.manipulation.editNode.apply(this.manipulation,arguments)},n.prototype.editNodeMode=function(){return console.log("Deprecated: Please use editNode instead of editNodeMode."),this.manipulation.editNode.apply(this.manipulation,arguments)},n.prototype.addEdgeMode=function(){return this.manipulation.addEdgeMode.apply(this.manipulation,arguments)},n.prototype.editEdgeMode=function(){return this.manipulation.editEdgeMode.apply(this.manipulation,arguments)},n.prototype.deleteSelected=function(){return this.manipulation.deleteSelected.apply(this.manipulation,arguments)},n.prototype.getPositions=function(){return this.nodesHandler.getPositions.apply(this.nodesHandler,arguments)},n.prototype.storePositions=function(){return this.nodesHandler.storePositions.apply(this.nodesHandler,arguments)},n.prototype.moveNode=function(){return this.nodesHandler.moveNode.apply(this.nodesHandler,arguments)},n.prototype.getBoundingBox=function(){return this.nodesHandler.getBoundingBox.apply(this.nodesHandler,arguments)},n.prototype.getConnectedNodes=function(t){return void 0!==this.body.nodes[t]?this.nodesHandler.getConnectedNodes.apply(this.nodesHandler,arguments):this.edgesHandler.getConnectedNodes.apply(this.edgesHandler,arguments)},n.prototype.getConnectedEdges=function(){return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler,arguments)},n.prototype.startSimulation=function(){return this.physics.startSimulation.apply(this.physics,arguments)},n.prototype.stopSimulation=function(){return this.physics.stopSimulation.apply(this.physics,arguments)},n.prototype.stabilize=function(){return this.physics.stabilize.apply(this.physics,arguments)},n.prototype.getSelection=function(){return this.selectionHandler.getSelection.apply(this.selectionHandler,arguments)},n.prototype.setSelection=function(){return this.selectionHandler.setSelection.apply(this.selectionHandler,arguments)},n.prototype.getSelectedNodes=function(){return this.selectionHandler.getSelectedNodes.apply(this.selectionHandler,arguments)},n.prototype.getSelectedEdges=function(){return this.selectionHandler.getSelectedEdges.apply(this.selectionHandler,arguments)},n.prototype.getNodeAt=function(){var t=this.selectionHandler.getNodeAt.apply(this.selectionHandler,arguments);return void 0!==t&&void 0!==t.id?t.id:t},n.prototype.getEdgeAt=function(){var t=this.selectionHandler.getEdgeAt.apply(this.selectionHandler,arguments);return void 0!==t&&void 0!==t.id?t.id:t},n.prototype.selectNodes=function(){return this.selectionHandler.selectNodes.apply(this.selectionHandler,arguments)},n.prototype.selectEdges=function(){return this.selectionHandler.selectEdges.apply(this.selectionHandler,arguments)},n.prototype.unselectAll=function(){this.selectionHandler.unselectAll.apply(this.selectionHandler,arguments),this.redraw()},n.prototype.redraw=function(){return this.renderer.redraw.apply(this.renderer,arguments)},n.prototype.getScale=function(){return this.view.getScale.apply(this.view,arguments)},n.prototype.getViewPosition=function(){return this.view.getViewPosition.apply(this.view,arguments)},n.prototype.fit=function(){return this.view.fit.apply(this.view,arguments)},n.prototype.moveTo=function(){return this.view.moveTo.apply(this.view,arguments)},n.prototype.focus=function(){return this.view.focus.apply(this.view,arguments)},n.prototype.releaseNode=function(){return this.view.releaseNode.apply(this.view,arguments)},n.prototype.getOptionsFromConfigurator=function(){var t={};return this.configurator&&(t=this.configurator.getOptions.apply(this.configurator)),t},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e){(0,s.default)(this,t),this.images={},this.imageBroken={},this.callback=e}return(0,a.default)(t,[{key:"_addImageToCache",value:function(t,e){0===e.width&&(document.body.appendChild(e),e.width=e.offsetWidth,e.height=e.offsetHeight,document.body.removeChild(e)),this.images[t]=e}},{key:"_tryloadBrokenUrl",value:function(t,e,i){var o=this;void 0!==t&&void 0!==e&&void 0!==i&&(i.onerror=function(){console.error("Could not load brokenImage:",e),o._addImageToCache(t,new Image)},i.src=e)}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e,i){var o=this,n=this.images[t];if(n)return n;var s=new Image;return s.onload=function(){o._addImageToCache(t,s),o._redrawWithImage(s)},s.onerror=function(){console.error("Could not load image:",t),o._tryloadBrokenUrl(t,e,s)},s.src=t,s}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(1),d=function(){function t(){(0,s.default)(this,t),this.clear(),this.defaultIndex=0,this.groupsArray=[],this.groupIndex=0,this.defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},h.extend(this.options,this.defaultOptions)}return(0,a.default)(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(t.hasOwnProperty(i)&&e.indexOf(i)===-1){var o=t[i];this.add(i,o)}}},{key:"clear",value:function(){this.groups={},this.groupsArray=[]}},{key:"get",value:function(t){var e=this.groups[t];if(void 0===e)if(this.options.useDefaultGroups===!1&&this.groupsArray.length>0){var i=this.groupIndex%this.groupsArray.length;this.groupIndex++,e={},e.color=this.groups[this.groupsArray[i]],this.groups[t]=e}else{var o=this.defaultIndex%this.defaultGroups.length;this.defaultIndex++,e={},e.color=this.defaultGroups[o],this.groups[t]=e}return e}},{key:"add",value:function(t,e){return this.groups[t]=e,this.groupsArray.push(t),e}}]),t}();e.default=d},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(159),d=o(h),l=i(160),u=o(l),c=i(1),p=i(91),f=i(93),m=function(){function t(e,i,o,n){var r=this;(0,s.default)(this,t),this.body=e,this.images=i,this.groups=o,this.layoutEngine=n,this.body.functions.createNode=this.create.bind(this),this.nodesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items,e.data)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={borderWidth:1,borderWidthSelected:2,brokenImage:void 0,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},fixed:{x:!1,y:!1},font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:0,strokeColor:"#ffffff",align:"center",vadjust:0,multi:!1,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},group:void 0,hidden:!1,icon:{face:"FontAwesome",code:void 0,size:50,color:"#2B7CE9"},image:void 0,label:void 0,labelHighlightBold:!0,level:void 0,margin:{top:5,right:5,bottom:5,left:5},mass:1,physics:!0,scaling:{min:10,max:30,label:{enabled:!1,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},shape:"ellipse",shapeProperties:{borderDashes:!1,borderRadius:6,interpolation:!0,useImageSize:!1,useBorderWithImage:!1},size:25,title:void 0,value:void 0,x:void 0,y:void 0},c.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("refreshNodes",this.refresh.bind(this)),this.body.emitter.on("refresh",this.refresh.bind(this)),this.body.emitter.on("destroy",function(){c.forEach(t.nodesListeners,function(e,i){t.body.data.nodes&&t.body.data.nodes.off(i,e)}),delete t.body.functions.createNode,delete t.nodesListeners.add,delete t.nodesListeners.update,delete t.nodesListeners.remove,delete t.nodesListeners})}},{key:"setOptions",value:function(t){if(this.nodeOptions=t,void 0!==t){if(d.default.parseOptions(this.options,t),void 0!==t.shape)for(var e in this.body.nodes)this.body.nodes.hasOwnProperty(e)&&this.body.nodes[e].updateShape();if(void 0!==t.font){u.default.parseOptions(this.options.font,t);for(var i in this.body.nodes)this.body.nodes.hasOwnProperty(i)&&(this.body.nodes[i].updateLabelModule(),this.body.nodes[i]._reset())}if(void 0!==t.size)for(var o in this.body.nodes)this.body.nodes.hasOwnProperty(o)&&this.body.nodes[o]._reset();void 0===t.hidden&&void 0===t.physics||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.data.nodes;if(t instanceof p||t instanceof f)this.body.data.nodes=t;else if(Array.isArray(t))this.body.data.nodes=new p,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new p}o&&c.forEach(this.nodesListeners,function(t,e){o.off(e,t)}),this.body.nodes={},this.body.data.nodes&&!function(){var t=e;c.forEach(e.nodesListeners,function(e,i){t.body.data.nodes.on(i,e)});var i=e.body.data.nodes.getIds();e.add(i,!0)}(),i===!1&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=void 0,o=[],n=0;n<t.length;n++){i=t[n];var s=this.body.data.nodes.get(i),r=this.create(s);o.push(r),this.body.nodes[i]=r}this.layoutEngine.positionInitially(o),e===!1&&this.body.emitter.emit("_dataChanged")}},{key:"update",value:function(t,e){for(var i=this.body.nodes,o=!1,n=0;n<t.length;n++){var s=t[n],r=i[s],a=e[n];void 0!==r?o=r.setOptions(a):(o=!0,r=this.create(a),i[s]=r)}o===!0?this.body.emitter.emit("_dataChanged"):this.body.emitter.emit("_dataUpdated")}},{key:"remove",value:function(t){for(var e=this.body.nodes,i=0;i<t.length;i++){var o=t[i];delete e[o]}this.body.emitter.emit("_dataChanged")}},{key:"create",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:d.default;return new e(t,this.body,this.images,this.groups,this.options,this.defaultOptions,this.nodeOptions)}},{key:"refresh",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],e=this.body.nodes;for(var i in e){var o=void 0;e.hasOwnProperty(i)&&(o=e[i]);var n=this.body.data.nodes._data[i];void 0!==o&&void 0!==n&&(t===!0&&o.setOptions({x:null,y:null}),o.setOptions({fixed:!1}),o.setOptions(n))}}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(Array.isArray(t)===!0){for(var i=0;i<t.length;i++)if(void 0!==this.body.nodes[t[i]]){var o=this.body.nodes[t[i]];e[t[i]]={x:Math.round(o.x),y:Math.round(o.y)}}}else if(void 0!==this.body.nodes[t]){var n=this.body.nodes[t];e[t]={x:Math.round(n.x),y:Math.round(n.y)}}}else for(var s=0;s<this.body.nodeIndices.length;s++){var r=this.body.nodes[this.body.nodeIndices[s]];e[this.body.nodeIndices[s]]={x:Math.round(r.x),y:Math.round(r.y)}}return e}},{key:"storePositions",value:function(){var t=[],e=this.body.data.nodes.getDataSet();for(var i in e._data)if(e._data.hasOwnProperty(i)){var o=this.body.nodes[i];e._data[i].x==Math.round(o.x)&&e._data[i].y==Math.round(o.y)||t.push({id:o.id,x:Math.round(o.x),y:Math.round(o.y)})}e.update(t)}},{key:"getBoundingBox",value:function(t){if(void 0!==this.body.nodes[t])return this.body.nodes[t].shape.boundingBox}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.nodes[t])for(var i=this.body.nodes[t],o={},n=0;n<i.edges.length;n++){var s=i.edges[n];s.toId==i.id?void 0===o[s.fromId]&&(e.push(s.fromId),o[s.fromId]=!0):s.fromId==i.id&&void 0===o[s.toId]&&(e.push(s.toId),o[s.toId]=!0)}return e}},{key:"getConnectedEdges",value:function(t){var e=[];if(void 0!==this.body.nodes[t])for(var i=this.body.nodes[t],o=0;o<i.edges.length;o++)e.push(i.edges[o].id);else console.log("NodeId provided for getConnectedEdges does not exist. Provided: ",t);return e}},{key:"moveNode",value:function(t,e,i){var o=this;void 0!==this.body.nodes[t]?(this.body.nodes[t].x=Number(e),this.body.nodes[t].y=Number(i),setTimeout(function(){o.body.emitter.emit("startSimulation")},0)):console.log("Node id supplied to moveNode does not exist. Provided: ",t)}}]),t}();e.default=m},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(62),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(160),u=o(l),c=i(165),p=o(c),f=i(176),m=o(f),v=i(178),g=o(v),y=i(179),b=o(y),_=i(180),w=o(_),x=i(182),k=o(x),O=i(183),D=o(O),S=i(184),M=o(S),C=i(185),T=o(C),E=i(186),P=o(E),I=i(187),N=o(I),z=i(188),R=o(z),L=i(189),A=o(L),B=i(190),F=o(B),H=i(122),j=(o(H),i(1)),W=function(){function t(e,i,o,n,s,r,h){(0,a.default)(this,t),this.options=j.bridgeObject(s),this.globalOptions=s,this.defaultOptions=r,this.nodeOptions=h,this.body=i,this.edges=[],this.id=void 0,this.imagelist=o,this.grouplist=n,this.x=void 0,this.y=void 0,this.baseSize=this.options.size,
-this.baseFontSize=this.options.font.size,this.predefinedPosition=!1,this.selected=!1,this.hover=!1,this.labelModule=new u.default(this.body,this.options,!1),this.setOptions(e)}return(0,d.default)(t,[{key:"attachEdge",value:function(t){this.edges.indexOf(t)===-1&&this.edges.push(t)}},{key:"detachEdge",value:function(t){var e=this.edges.indexOf(t);e!=-1&&this.edges.splice(e,1)}},{key:"setOptions",value:function(e){var i=this.options.shape;if(e){if(void 0!==e.id&&(this.id=e.id),void 0===this.id)throw"Node must have an id";if(void 0!==e.x&&(null===e.x?(this.x=void 0,this.predefinedPosition=!1):(this.x=parseInt(e.x),this.predefinedPosition=!0)),void 0!==e.y&&(null===e.y?(this.y=void 0,this.predefinedPosition=!1):(this.y=parseInt(e.y),this.predefinedPosition=!0)),void 0!==e.size&&(this.baseSize=e.size),void 0!==e.value&&(e.value=parseFloat(e.value)),"number"==typeof e.group||"string"==typeof e.group&&""!=e.group){var o=this.grouplist.get(e.group);j.deepExtend(this.options,o),this.options.color=j.parseColor(this.options.color)}if(t.parseOptions(this.options,e,!0,this.globalOptions),this.choosify(e),void 0!==this.options.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.options.image,this.options.brokenImage,this.id)}return this.updateLabelModule(e),this.updateShape(i),this.labelModule.propagateFonts(this.nodeOptions,e,this.defaultOptions),void 0!==e.hidden||void 0!==e.physics}}},{key:"choosify",value:function(t){this.chooser=!0;var e=[t,this.options,this.defaultOptions],i=j.topMost(e,"chosen");if("boolean"==typeof i)this.chooser=i;else if("object"===("undefined"==typeof i?"undefined":(0,s.default)(i))){var o=j.topMost(e,["chosen","node"]);"boolean"!=typeof o&&"function"!=typeof o||(this.chooser=o)}}},{key:"getFormattingValues",value:function(){var t={color:this.options.color.background,borderWidth:this.options.borderWidth,borderColor:this.options.color.border,size:this.options.size,borderDashes:this.options.shapeProperties.borderDashes,borderRadius:this.options.shapeProperties.borderRadius,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y};return this.selected||this.hover?this.chooser===!0?this.selected?(t.borderWidth*=2,t.color=this.options.color.highlight.background,t.borderColor=this.options.color.highlight.border,t.shadow=this.options.shadow.enabled):this.hover&&(t.color=this.options.color.hover.background,t.borderColor=this.options.color.hover.border,t.shadow=this.options.shadow.enabled):"function"==typeof this.chooser&&(this.chooser(t,this.options.id,this.selected,this.hover),t.shadow===!1&&(t.shadowColor===this.options.shadow.color&&t.shadowSize===this.options.shadow.size&&t.shadowX===this.options.shadow.x&&t.shadowY===this.options.shadow.y||(t.shadow=!0))):t.shadow=this.options.shadow.enabled,t}},{key:"updateLabelModule",value:function(t){void 0!==this.options.label&&null!==this.options.label||(this.options.label=""),this.labelModule.setOptions(this.options,!0),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize),this.labelModule.constrain(this.nodeOptions,t,this.defaultOptions),this.labelModule.choosify(this.nodeOptions,t,this.defaultOptions)}},{key:"updateShape",value:function(t){if(t===this.options.shape&&this.shape)this.shape.setOptions(this.options,this.imageObj);else switch(this.options.shape){case"box":this.shape=new p.default(this.options,this.body,this.labelModule);break;case"circle":this.shape=new m.default(this.options,this.body,this.labelModule);break;case"circularImage":this.shape=new g.default(this.options,this.body,this.labelModule,this.imageObj);break;case"database":this.shape=new b.default(this.options,this.body,this.labelModule);break;case"diamond":this.shape=new w.default(this.options,this.body,this.labelModule);break;case"dot":this.shape=new k.default(this.options,this.body,this.labelModule);break;case"ellipse":this.shape=new D.default(this.options,this.body,this.labelModule);break;case"icon":this.shape=new M.default(this.options,this.body,this.labelModule);break;case"image":this.shape=new T.default(this.options,this.body,this.labelModule,this.imageObj);break;case"square":this.shape=new P.default(this.options,this.body,this.labelModule);break;case"star":this.shape=new N.default(this.options,this.body,this.labelModule);break;case"text":this.shape=new R.default(this.options,this.body,this.labelModule);break;case"triangle":this.shape=new A.default(this.options,this.body,this.labelModule);break;case"triangleDown":this.shape=new F.default(this.options,this.body,this.labelModule);break;default:this.shape=new D.default(this.options,this.body,this.labelModule)}this._reset()}},{key:"select",value:function(){this.selected=!0,this._reset()}},{key:"unselect",value:function(){this.selected=!1,this._reset()}},{key:"_reset",value:function(){this.shape.width=void 0,this.shape.height=void 0}},{key:"getTitle",value:function(){return this.options.title}},{key:"distanceToBorder",value:function(t,e){return this.shape.distanceToBorder(t,e)}},{key:"isFixed",value:function(){return this.options.fixed.x&&this.options.fixed.y}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var o=this.options.scaling.customScalingFunction(t,e,i,this.options.value),n=this.options.scaling.max-this.options.scaling.min;if(this.options.scaling.label.enabled===!0){var s=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+o*s}this.options.size=this.options.scaling.min+o*n}else this.options.size=this.baseSize,this.options.font.size=this.baseFontSize;this.updateLabelModule()}},{key:"draw",value:function(t){var e=this.getFormattingValues();this.shape.draw(t,this.x,this.y,this.selected,this.hover,e)}},{key:"updateBoundingBox",value:function(t){this.shape.updateBoundingBox(this.x,this.y,t)}},{key:"resize",value:function(t){var e=this.getFormattingValues();this.shape.resize(t,this.selected,this.hover,e)}},{key:"isOverlappingWith",value:function(t){return this.shape.left<t.right&&this.shape.left+this.shape.width>t.left&&this.shape.top<t.bottom&&this.shape.top+this.shape.height>t.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.left<t.right&&this.shape.boundingBox.right>t.left&&this.shape.boundingBox.top<t.bottom&&this.shape.boundingBox.bottom>t.top}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=["color","font","fixed","shadow"];if(j.selectiveNotDeepExtend(n,t,e,i),j.mergeOptions(t,e,"shadow",i,o),void 0!==e.color&&null!==e.color){var s=j.parseColor(e.color);j.fillIfDefined(t.color,s)}else i===!0&&null===e.color&&(t.color=j.bridgeObject(o.color));void 0!==e.fixed&&null!==e.fixed&&("boolean"==typeof e.fixed?(t.fixed.x=e.fixed,t.fixed.y=e.fixed):(void 0!==e.fixed.x&&"boolean"==typeof e.fixed.x&&(t.fixed.x=e.fixed.x),void 0!==e.fixed.y&&"boolean"==typeof e.fixed.y&&(t.fixed.y=e.fixed.y))),void 0!==e.font&&null!==e.font?u.default.parseOptions(t.font,e):i===!0&&null===e.font&&(t.font=j.bridgeObject(o.font)),void 0!==e.scaling&&j.mergeOptions(t.scaling,e.scaling,"label",i,o.scaling)}}]),t}();e.default=W},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(161),s=o(n),r=i(2),a=o(r),h=i(62),d=o(h),l=i(115),u=o(l),c=i(116),p=o(c),f=i(1),m=function(){function t(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2];(0,u.default)(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=o}return(0,p.default)(t,[{key:"setOptions",value:function(e){var i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];this.elementOptions=e,this.fontOptions=f.deepExtend({},e.font,!0),void 0!==e.label&&(this.labelDirty=!0),void 0!==e.font&&(t.parseOptions(this.fontOptions,e,i),"string"==typeof e.font?this.baseSize=this.fontOptions.size:"object"===(0,d.default)(e.font)&&void 0!==e.font.size&&(this.baseSize=e.font.size))}},{key:"constrain",value:function(t,e,i){this.fontOptions.constrainWidth=!1,this.fontOptions.maxWdt=-1,this.fontOptions.minWdt=-1;var o=[e,t,i],n=f.topMost(o,"widthConstraint");if("number"==typeof n)this.fontOptions.maxWdt=Number(n),this.fontOptions.minWdt=Number(n);else if("object"===("undefined"==typeof n?"undefined":(0,d.default)(n))){var s=f.topMost(o,["widthConstraint","maximum"]);"number"==typeof s&&(this.fontOptions.maxWdt=Number(s));var r=f.topMost(o,["widthConstraint","minimum"]);"number"==typeof r&&(this.fontOptions.minWdt=Number(r))}this.fontOptions.constrainHeight=!1,this.fontOptions.minHgt=-1,this.fontOptions.valign="middle";var a=f.topMost(o,"heightConstraint");if("number"==typeof a)this.fontOptions.minHgt=Number(a);else if("object"===("undefined"==typeof a?"undefined":(0,d.default)(a))){var h=f.topMost(o,["heightConstraint","minimum"]);"number"==typeof h&&(this.fontOptions.minHgt=Number(h));var l=f.topMost(o,["heightConstraint","valign"]);"string"==typeof l&&("top"!==l&&"bottom"!==l||(this.fontOptions.valign=l))}}},{key:"choosify",value:function(t,e,i){this.fontOptions.chooser=!0;var o=[e,t,i],n=f.topMost(o,"chosen");if("boolean"==typeof n)this.fontOptions.chooser=n;else if("object"===("undefined"==typeof n?"undefined":(0,d.default)(n))){var s=f.topMost(o,["chosen","label"]);"boolean"!=typeof s&&"function"!=typeof s||(this.fontOptions.chooser=s)}}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"propagateFonts",value:function(t,e,i){if(this.fontOptions.multi){var o=["bold","ital","boldital","mono"],n=!0,s=!1,r=void 0;try{for(var h,d=(0,a.default)(o);!(n=(h=d.next()).done);n=!0){var l=h.value,u=void 0;if(t.font&&(u=t.font[l]),"string"==typeof u){var c=u.split(" ");this.fontOptions[l].size=c[0].replace("px",""),this.fontOptions[l].face=c[1],this.fontOptions[l].color=c[2],this.fontOptions[l].vadjust=this.fontOptions.vadjust,this.fontOptions[l].mod=i.font[l].mod}else{if(u&&u.hasOwnProperty("face")?this.fontOptions[l].face=u.face:e.font&&e.font[l]&&e.font[l].hasOwnProperty("face")?this.fontOptions[l].face=e.font[l].face:"mono"===l?this.fontOptions[l].face=i.font[l].face:e.font&&e.font.hasOwnProperty("face")?this.fontOptions[l].face=e.font.face:this.fontOptions[l].face=this.fontOptions.face,u&&u.hasOwnProperty("color")?this.fontOptions[l].color=u.color:e.font&&e.font[l]&&e.font[l].hasOwnProperty("color")?this.fontOptions[l].color=e.font[l].color:e.font&&e.font.hasOwnProperty("color")?this.fontOptions[l].color=e.font.color:this.fontOptions[l].color=this.fontOptions.color,u&&u.hasOwnProperty("mod")?this.fontOptions[l].mod=u.mod:e.font&&e.font[l]&&e.font[l].hasOwnProperty("mod")?this.fontOptions[l].mod=e.font[l].mod:e.font&&e.font.hasOwnProperty("mod")?this.fontOptions[l].mod=e.font.mod:this.fontOptions[l].mod=i.font[l].mod,u&&u.hasOwnProperty("size"))this.fontOptions[l].size=u.size;else if(e.font&&e.font[l]&&e.font[l].hasOwnProperty("size"))this.fontOptions[l].size=e.font[l].size;else if(this.fontOptions[l].face===i.font[l].face&&this.fontOptions.face===i.font.face){var p=this.fontOptions.size/Number(i.font.size);this.fontOptions[l].size=i.font[l].size*p}else e.font&&e.font.hasOwnProperty("size")?this.fontOptions[l].size=e.font.size:this.fontOptions[l].size=this.fontOptions.size;if(u&&u.hasOwnProperty("vadjust"))this.fontOptions[l].vadjust=u.vadjust;else if(e.font&&e.font[l]&&e.font[l].hasOwnProperty("vadjust"))this.fontOptions[l].vadjust=e.font[l].vadjust;else if(this.fontOptions[l].face===i.font[l].face&&this.fontOptions.face===i.font.face){var f=this.fontOptions.size/Number(i.font.size);this.fontOptions[l].vadjust=i.font[l].vadjust*Math.round(f)}else e.font&&e.font.hasOwnProperty("vadjust")?this.fontOptions[l].vadjust=e.font.vadjust:this.fontOptions[l].vadjust=this.fontOptions.vadjust}this.fontOptions[l].size=Number(this.fontOptions[l].size),this.fontOptions[l].vadjust=Number(this.fontOptions[l].vadjust)}}catch(t){s=!0,r=t}finally{try{!n&&d.return&&d.return()}finally{if(s)throw r}}}}},{key:"draw",value:function(t,e,i,o,n){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var r=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&r<this.elementOptions.scaling.label.drawThreshold-1||(this.calculateLabelSize(t,o,n,e,i,s),this._drawBackground(t),this._drawText(t,o,n,e,i,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=2;if(this.isEdgeLabel)switch(this.fontOptions.align){case"middle":t.fillRect(.5*-this.size.width,.5*-this.size.height,this.size.width,this.size.height);break;case"top":t.fillRect(.5*-this.size.width,-(this.size.height+e),this.size.width,this.size.height);break;case"bottom":t.fillRect(.5*-this.size.width,e,this.size.width,this.size.height);break;default:t.fillRect(this.size.left,this.size.top-.5*e,this.size.width,this.size.height)}else t.fillRect(this.size.left,this.size.top-.5*e,this.size.width,this.size.height)}}},{key:"_drawText",value:function(t,e,i,o,n){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle",a=this.fontOptions.size,h=a*this.body.view.scale;h>=this.elementOptions.scaling.label.maxVisible&&(a=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale);var d=this.size.yLine,l=this._setAlignment(t,o,d,r),u=(0,s.default)(l,2);o=u[0],d=u[1],t.textAlign="left",o-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(d-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(d+=(this.size.height-this.size.labelHeight)/2));for(var c=0;c<this.lineCount;c++)if(this.lines[c]&&this.lines[c].blocks){var p=0;this.isEdgeLabel||"center"===this.fontOptions.align?p+=(this.size.width-this.lines[c].width)/2:"right"===this.fontOptions.align&&(p+=this.size.width-this.lines[c].width);for(var f=0;f<this.lines[c].blocks.length;f++){var m=this.lines[c].blocks[f];t.font=m.font;var v=this._getColor(m.color,h,m.strokeColor),g=(0,s.default)(v,2),y=g[0],b=g[1];m.strokeWidth>0&&(t.lineWidth=m.strokeWidth,t.strokeStyle=b,t.lineJoin="round"),t.fillStyle=y,m.strokeWidth>0&&t.strokeText(m.text,o+p,d+m.vadjust),t.fillText(m.text,o+p,d+m.vadjust),p+=m.width}d+=this.lines[c].height}}},{key:"_setAlignment",value:function(t,e,i,o){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&this.pointToSelf===!1){e=0,i=0;var n=2;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=2*n):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=2*n):t.textBaseline="middle"}else t.textBaseline=o;return[e,i]}},{key:"_getColor",value:function(t,e,i){var o=t||"#000000",n=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var s=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));o=f.overrideOpacity(o,s),n=f.overrideOpacity(n,s)}return[o,n]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"calculateLabelSize",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this.labelDirty===!0&&this._processLabel(t,e,i),this.size.left=o-.5*this.size.width,this.size.top=n-.5*this.size.height,this.size.yLine=n+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===s&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4),this.labelDirty=!1}},{key:"decodeMarkupSystem",value:function(t){var e="none";return"markdown"===t||"md"===t?e="markdown":t!==!0&&"html"!==t||(e="html"),e}},{key:"splitBlocks",value:function(t,e){var i=this.decodeMarkupSystem(e);return"none"===i?[{text:t,mod:"normal"}]:"markdown"===i?this.splitMarkdownBlocks(t):"html"===i?this.splitHtmlBlocks(t):void 0}},{key:"splitMarkdownBlocks",value:function(t){var e=[],i={bold:!1,ital:!1,mono:!1,beginable:!0,spacing:!1,position:0,buffer:"",modStack:[]};for(i.mod=function(){return 0===this.modStack.length?"normal":this.modStack[0]},i.modName=function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":i.bold&&i.ital?"boldital":i.bold?"bold":i.ital?"ital":void 0},i.emitBlock=function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(e.push({text:this.buffer,mod:this.modName()}),this.buffer="")},i.add=function(t){" "===t&&(i.spacing=!0),i.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)};i.position<t.length;){var o=t.charAt(i.position);/[ \t]/.test(o)?(i.mono?i.add(o):i.spacing=!0,i.beginable=!0):/\\/.test(o)?i.position<t.length+1&&(i.position++,o=t.charAt(i.position),/ \t/.test(o)?i.spacing=!0:(i.add(o),i.beginable=!1)):i.mono||i.bold||!i.beginable&&!i.spacing||!/\*/.test(o)?i.mono||i.ital||!i.beginable&&!i.spacing||!/\_/.test(o)?!i.mono&&(i.beginable||i.spacing)&&/`/.test(o)?(i.emitBlock(),i.mono=!0,i.modStack.unshift("mono")):!i.mono&&"bold"===i.mod()&&/\*/.test(o)?i.position===t.length-1||/[.,_` \t\n]/.test(t.charAt(i.position+1))?(i.emitBlock(),i.bold=!1,i.modStack.shift()):i.add(o):!i.mono&&"ital"===i.mod()&&/\_/.test(o)?i.position===t.length-1||/[.,*` \t\n]/.test(t.charAt(i.position+1))?(i.emitBlock(),i.ital=!1,i.modStack.shift()):i.add(o):i.mono&&"mono"===i.mod()&&/`/.test(o)?i.position===t.length-1||/[.,*_ \t\n]/.test(t.charAt(i.position+1))?(i.emitBlock(),i.mono=!1,i.modStack.shift()):i.add(o):(i.add(o),i.beginable=!1):(i.emitBlock(),i.ital=!0,i.modStack.unshift("ital")):(i.emitBlock(),i.bold=!0,i.modStack.unshift("bold")),i.position++}return i.emitBlock(),e}},{key:"splitHtmlBlocks",value:function(t){var e=[],i={bold:!1,ital:!1,mono:!1,spacing:!1,position:0,buffer:"",modStack:[]};for(i.mod=function(){return 0===this.modStack.length?"normal":this.modStack[0]},i.modName=function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":i.bold&&i.ital?"boldital":i.bold?"bold":i.ital?"ital":void 0},i.emitBlock=function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(e.push({text:this.buffer,mod:this.modName()}),this.buffer="")},i.add=function(t){" "===t&&(i.spacing=!0),i.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)};i.position<t.length;){var o=t.charAt(i.position);/[ \t]/.test(o)?i.mono?i.add(o):i.spacing=!0:/</.test(o)?i.mono||i.bold||!/<b>/.test(t.substr(i.position,3))?i.mono||i.ital||!/<i>/.test(t.substr(i.position,3))?!i.mono&&/<code>/.test(t.substr(i.position,6))?(i.emitBlock(),i.mono=!0,i.modStack.unshift("mono"),i.position+=5):!i.mono&&"bold"===i.mod()&&/<\/b>/.test(t.substr(i.position,4))?(i.emitBlock(),i.bold=!1,i.modStack.shift(),i.position+=3):!i.mono&&"ital"===i.mod()&&/<\/i>/.test(t.substr(i.position,4))?(i.emitBlock(),i.ital=!1,i.modStack.shift(),i.position+=3):"mono"===i.mod()&&/<\/code>/.test(t.substr(i.position,7))?(i.emitBlock(),i.mono=!1,i.modStack.shift(),i.position+=6):i.add(o):(i.emitBlock(),i.ital=!0,i.modStack.unshift("ital"),i.position+=2):(i.emitBlock(),i.bold=!0,i.modStack.unshift("bold"),i.position+=2):/&/.test(o)?/&lt;/.test(t.substr(i.position,4))?(i.add("<"),i.position+=3):/&amp;/.test(t.substr(i.position,5))?(i.add("&"),i.position+=4):i.add("&"):i.add(o),i.position++}return i.emitBlock(),e}},{key:"getFormattingValues",value:function(t,e,i,o){var n={color:"normal"===o?this.fontOptions.color:this.fontOptions[o].color,size:"normal"===o?this.fontOptions.size:this.fontOptions[o].size,face:"normal"===o?this.fontOptions.face:this.fontOptions[o].face,mod:"normal"===o?"":this.fontOptions[o].mod,vadjust:"normal"===o?this.fontOptions.vadjust:this.fontOptions[o].vadjust,strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};return"normal"===o?(e||i)&&(this.fontOptions.chooser===!0&&this.elementOptions.labelHighlightBold?n.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(t,n,this.elementOptions.id,e,i)):(e||i)&&"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(t,n,this.elementOptions.id,e,i),t.font=(n.mod+" "+n.size+"px "+n.face).replace(/"/g,""),n.font=t.font,n.height=n.size,n}},{key:"differentState",value:function(t,e){return t!==this.fontOptions.selectedState&&e!==this.fontOptions.hoverState}},{key:"_processLabel",value:function(t,e,i){var o=0,n=0,s=[],r=0;if(s.add=function(t,e,i,o,n,s,r,a,h,d){this.length==t&&(this[t]={width:0,height:0,blocks:[]}),this[t].blocks.push({text:e,font:i,color:o,width:n,height:s,vadjust:r,mod:a,strokeWidth:h,strokeColor:d})},s.accumulate=function(t,e,i){this[t].width+=e,this[t].height=i>this[t].height?i:this[t].height},s.addAndAccumulate=function(t,e,i,o,n,s,r,a,h,d){this.add(t,e,i,o,n,s,r,a,h,d),this.accumulate(t,n,s)},void 0!==this.elementOptions.label){var a=String(this.elementOptions.label).split("\n"),h=a.length;if(this.elementOptions.font.multi)for(var d=0;d<h;d++){var l=this.splitBlocks(a[d],this.elementOptions.font.multi),u=0,c=0;if(l){if(0==l.length){var p=this.getFormattingValues(t,e,i,"normal");s.addAndAccumulate(r,"",p.font,p.color,0,p.size,p.vadjust,"normal",p.strokeWidth,p.strokeColor),n+=s[r].height,r++;continue}for(var f=0;f<l.length;f++)if(this.fontOptions.maxWdt>0)for(var m=this.getFormattingValues(t,e,i,l[f].mod),v=l[f].text.split(" "),g=!0,y="",b=void 0,_=void 0,w=0;w<v.length;){var x=g?"":" ";_=b,b=t.measureText(y+x+v[w]),u+b.width>this.fontOptions.maxWdt?(c=m.height>c?m.height:c,s.add(r,y,m.font,m.color,_.width,m.height,m.vadjust,l[f].mod,m.strokeWidth,m.strokeColor),s.accumulate(r,_.width,c),y="",g=!0,u=0,o=s[r].width>o?s[r].width:o,n+=s[r].height,r++):(y=y+x+v[w],w===v.length-1&&(c=m.height>c?m.height:c,u+=b.width,s.add(r,y,m.font,m.color,b.width,m.height,m.vadjust,l[f].mod,m.strokeWidth,m.strokeColor),s.accumulate(r,b.width,c),f===l.length-1&&(o=s[r].width>o?s[r].width:o,n+=s[r].height,r++)),w++,g=!1)}else{var k=this.getFormattingValues(t,e,i,l[f].mod),O=t.measureText(l[f].text);s.addAndAccumulate(r,l[f].text,k.font,k.color,O.width,k.height,k.vadjust,l[f].mod,k.strokeWidth,k.strokeColor),o=s[r].width>o?s[r].width:o,l.length-1===f&&(n+=s[r].height,r++)}}}else for(var D=0;D<h;D++){var S=this.getFormattingValues(t,e,i,"normal");if(this.fontOptions.maxWdt>0)for(var M=a[D].split(" "),C="",T=void 0,E=void 0,P=0;P<M.length;){var I=""===C?"":" ";E=T,T=t.measureText(C+I+M[P]),T.width>this.fontOptions.maxWdt?(s.addAndAccumulate(r,C,S.font,S.color,E.width,S.size,S.vadjust,"normal",S.strokeWidth,S.strokeColor),o=s[r].width>o?s[r].width:o,n+=s[r].height,C="",r++):(C=C+I+M[P],P===M.length-1&&(s.addAndAccumulate(r,C,S.font,S.color,T.width,S.size,S.vadjust,"normal",S.strokeWidth,S.strokeColor),o=s[r].width>o?s[r].width:o,n+=s[r].height,r++),P++)}else{var N=a[D],z=t.measureText(N);s.addAndAccumulate(r,N,S.font,S.color,z.width,S.size,S.vadjust,"normal",S.strokeWidth,S.strokeColor),o=s[r].width>o?s[r].width:o,n+=s[r].height,r++}}}this.fontOptions.minWdt>0&&o<this.fontOptions.minWdt&&(o=this.fontOptions.minWdt),this.size.labelHeight=n,this.fontOptions.minHgt>0&&n<this.fontOptions.minHgt&&(n=this.fontOptions.minHgt),this.lines=s,this.lineCount=s.length,this.size.width=o,this.size.height=n,this.selectedState=e,this.hoverState=i}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if("string"==typeof e.font){var o=e.font.split(" ");t.size=o[0].replace("px",""),t.face=o[1],t.color=o[2],t.vadjust=0}else"object"===(0,d.default)(e.font)&&f.fillIfDefined(t,e.font,i);t.size=Number(t.size),t.vadjust=Number(t.vadjust)}}]),t}();e.default=m},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(162),s=o(n),r=i(2),a=o(r);e.default=function(){function t(t,e){var i=[],o=!0,n=!1,s=void 0;try{for(var r,h=(0,a.default)(t);!(o=(r=h.next()).done)&&(i.push(r.value),!e||i.length!==e);o=!0);}catch(t){n=!0,s=t}finally{try{!o&&h.return&&h.return()}finally{if(n)throw s}}return i}return function(e,i){if(Array.isArray(e))return e;if((0,s.default)(Object(e)))return t(e,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}()},function(t,e,i){t.exports={default:i(163),__esModule:!0}},function(t,e,i){i(4),i(50),t.exports=i(164)},function(t,e,i){var o=i(54),n=i(47)("iterator"),s=i(8);t.exports=i(17).isIterable=function(t){var e=Object(t);return void 0!==e[n]||"@@iterator"in e||s.hasOwnProperty(o(e))}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;(void 0===this.width||this.labelModule.differentState(e,i))&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=this.width/2)}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,t.strokeStyle=s.borderColor,t.lineWidth=s.borderWidth,t.lineWidth/=this.body.view.scale,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=s.color,t.roundRect(this.left,this.top,this.width,this.height,s.borderRadius),this.enableShadow(t,s),t.fill(),this.disableShadow(t,s),t.save(),s.borderWidth>0&&(this.enableBorderDashes(t,s),t.stroke(),this.disableBorderDashes(t,s)),t.restore(),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this.resize(i,o,n),this.left=t-this.width/2,this.top=e-this.height/2;var s=this.options.shapeProperties.borderRadius;this.boundingBox.left=this.left-s,this.boundingBox.top=this.top-s,this.boundingBox.bottom=this.top+this.height+s,this.boundingBox.right=this.left+this.width+s}},{key:"distanceToBorder",value:function(t,e){this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),e}(m.default);e.default=v},function(t,e,i){t.exports={default:i(167),__esModule:!0}},function(t,e,i){i(168),t.exports=i(17).Object.getPrototypeOf},function(t,e,i){var o=i(49),n=i(48);i(61)("getPrototypeOf",function(){return function(t){return n(o(t))}})},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(62),s=o(n);e.default=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!==("undefined"==typeof e?"undefined":(0,s.default)(e))&&"function"!=typeof e?t:e}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(171),s=o(n),r=i(55),a=o(r),h=i(62),d=o(h);e.default=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+("undefined"==typeof e?"undefined":(0,d.default)(e)));t.prototype=(0,a.default)(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(s.default?(0,s.default)(t,e):t.__proto__=e)}},function(t,e,i){t.exports={default:i(172),__esModule:!0}},function(t,e,i){i(173),t.exports=i(17).Object.setPrototypeOf},function(t,e,i){var o=i(15);o(o.S,"Object",{setPrototypeOf:i(174).set})},function(t,e,i){var o=i(23),n=i(22),s=function(t,e){if(n(t),!o(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,e,o){try{o=i(18)(Function.call,i(78).f(Object.prototype,"__proto__").set,2),o(t,[]),e=!(t instanceof Array)}catch(t){e=!0}return function(t,i){return s(t,i),e?t.__proto__=i:o(t,i),t}}({},!1):void 0),check:s}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(62),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=function(){function t(e,i,o){(0,a.default)(this,t),this.body=i,this.labelModule=o,this.setOptions(e),this.top=void 0,this.left=void 0,this.height=void 0,this.width=void 0,this.radius=void 0,this.margin=void 0,this.boundingBox={top:0,left:0,right:0,bottom:0}}return(0,d.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"_setMargins",value:function(t){this.margin={},this.options.margin&&("object"==(0,s.default)(this.options.margin)?(this.margin.top=this.options.margin.top,this.margin.right=this.options.margin.right,this.margin.bottom=this.options.margin.bottom,this.margin.left=this.options.margin.left):(this.margin.top=this.options.margin,this.margin.right=this.options.margin,this.margin.bottom=this.options.margin,this.margin.left=this.options.margin)),t.adjustSizes(this.margin)}},{key:"_distanceToBorder",value:function(t,e){var i=this.options.borderWidth;return this.resize(t),Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}},{key:"enableShadow",value:function(t,e){e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"enableBorderDashes",value:function(t,e){if(e.borderDashes!==!1)if(void 0!==t.setLineDash){var i=e.borderDashes;i===!0&&(i=[5,15]),t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used."),this.options.shapeProperties.borderDashes=!1,e.borderDashes=!1}},{key:"disableBorderDashes",value:function(t,e){e.borderDashes!==!1&&(void 0!==t.setLineDash?t.setLineDash([0]):(console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used."),this.options.shapeProperties.borderDashes=!1,e.borderDashes=!1))}}]),t}();e.default=l},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(177),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(void 0===this.width||this.labelModule.differentState(e,i)){this.textSize=this.labelModule.getTextSize(t,e,i);var o=Math.max(this.textSize.width+this.margin.right+this.margin.left,this.textSize.height+this.margin.top+this.margin.bottom);this.options.size=o/2,this.width=o,this.height=o,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,s){
-this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,o,n,s),this.boundingBox.top=i-s.size,this.boundingBox.left=e-s.size,this.boundingBox.right=e+s.size,this.boundingBox.bottom=i+s.size,this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),.5*this.width}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n.labelOffset=0,n.imageLoaded=!1,n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"setOptions",value:function(t,e){this.options=t,e&&(this.imageObj=e)}},{key:"_resizeImage",value:function(){var t=!1;if(this.imageObj.width&&this.imageObj.height?this.imageLoaded===!1&&(this.imageLoaded=!0,t=!0):this.imageLoaded=!1,!this.width||!this.height||t===!0){var e,i,o;this.imageObj.width&&this.imageObj.height&&(e=0,i=0),this.options.shapeProperties.useImageSize===!1?this.imageObj.width>this.imageObj.height?(o=this.imageObj.width/this.imageObj.height,e=2*this.options.size*o||this.imageObj.width,i=2*this.options.size||this.imageObj.height):(o=this.imageObj.width&&this.imageObj.height?this.imageObj.height/this.imageObj.width:1,e=2*this.options.size,i=2*this.options.size*o):(e=this.imageObj.width,i=this.imageObj.height),this.width=e,this.height=i,this.radius=.5*this.width}}},{key:"_drawRawCircle",value:function(t,e,i,o,n,s){var r=s.borderWidth/this.body.view.scale;t.lineWidth=Math.min(this.width,r),t.strokeStyle=s.borderColor,t.fillStyle=s.color,t.circle(e,i,s.size),this.enableShadow(t,s),t.fill(),this.disableShadow(t,s),t.save(),r>0&&(this.enableBorderDashes(t,s),t.stroke(),this.disableBorderDashes(t,s)),t.restore()}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=1,this.enableShadow(t,e);var i=this.imageObj.width/this.width/this.body.view.scale;if(i>2&&this.options.shapeProperties.interpolation===!0){var o=this.imageObj.width,n=this.imageObj.height,s=document.createElement("canvas");s.width=o,s.height=o;var r=s.getContext("2d");i*=.5,o*=.5,n*=.5,r.drawImage(this.imageObj,0,0,o,n);for(var a=0,h=1;i>2&&h<4;)r.drawImage(s,a,0,o,n,a+o,0,o/2,n/2),a+=o,i*=.5,o*=.5,n*=.5,h+=1;t.drawImage(s,a,0,o,n,this.left,this.top,this.width,this.height)}else t.drawImage(this.imageObj,this.left,this.top,this.width,this.height);this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,o,n){var s,r=0;if(void 0!==this.height){r=.5*this.height;var a=this.labelModule.getTextSize(t,o,n);a.lineCount>=1&&(r+=a.height/2)}s=i+r,this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,s,o,n,"hanging")}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(177),m=o(f),v=function(t){function e(t,i,o,n){(0,a.default)(this,e);var r=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return r.imageObj=n,r._swapToImageResizeWhenImageLoaded=!0,r}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height||this.labelModule.differentState(e,i)){var o=2*this.options.size;this.width=o,this.height=o,this._swapToImageResizeWhenImageLoaded=!0,this.radius=.5*this.width}else this._swapToImageResizeWhenImageLoaded&&(this.width=void 0,this.height=void 0,this._swapToImageResizeWhenImageLoaded=!1),this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(),this.left=e-this.width/2,this.top=i-this.height/2;Math.min(.5*this.height,.5*this.width);this._drawRawCircle(t,e,i,o,n,s),t.save(),t.clip(),this._drawImageAtPosition(t,s),t.restore(),this._drawImageLabel(t,e,i,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size,this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),.5*this.width}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){if(void 0===this.width||this.labelModule.differentState(e,i)){this.textSize=this.labelModule.getTextSize(t,e,i);var o=this.textSize.width+this.margin.right+this.margin.left;this.width=o,this.height=o,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2;var r=s.borderWidth/this.body.view.scale;t.lineWidth=Math.min(this.width,r),t.strokeStyle=s.borderColor,t.fillStyle=s.color,t.database(e-this.width/2,i-this.height/2,this.width,this.height),this.enableShadow(t,s),t.fill(),this.disableShadow(t,s),t.save(),r>0&&(this.enableBorderDashes(t,s),t.stroke(),this.disableBorderDashes(t,s)),t.restore(),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this.resize(i,o,n),this.left=t-.5*this.width,this.top=e-.5*this.height,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.selected,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:this.hover;this._resizeShape(i,o,e)}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"diamond",4,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_resizeShape",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.selected,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.hover,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{size:this.options.size};if(void 0===this.width||this.labelModule.differentState(t,e)){var o=2*i.size;this.width=o,this.height=o,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,o,n,s,r,a){this._resizeShape(s,r,a),this.left=o-this.width/2,this.top=n-this.height/2;var h=a.borderWidth/this.body.view.scale;if(t.lineWidth=Math.min(this.width,h),t.strokeStyle=a.borderColor,t.fillStyle=a.color,t[e](o,n,a.size),this.enableShadow(t,a),t.fill(),this.disableShadow(t,a),t.save(),h>0&&(this.enableBorderDashes(t,a),t.stroke(),this.disableBorderDashes(t,a)),t.restore(),void 0!==this.options.label){var d=n+.5*this.height+3;this.labelModule.draw(t,o,d,s,r,"hanging")}this.updateBoundingBox(o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+3))}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.selected,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:this.hover;this._resizeShape(i,o,e)}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"circle",2,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),this.options.size}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.width||this.labelModule.differentState(e,i)){var o=this.labelModule.getTextSize(t,e,i);this.height=2*o.height,this.width=o.width+this.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-.5*this.width,this.top=i-.5*this.height;var r=s.borderWidth/this.body.view.scale;t.lineWidth=Math.min(this.width,r),t.strokeStyle=s.borderColor,t.fillStyle=s.color,t.ellipse(this.left,this.top,this.width,this.height),this.enableShadow(t,s),t.fill(),this.disableShadow(t,s),t.save(),r>0&&(this.enableBorderDashes(t,s),t.stroke(),this.disableBorderDashes(t,s)),t.restore(),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,e,i,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this.resize(i,o,n),this.left=t-.5*this.width,this.top=e-.5*this.height,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"distanceToBorder",value:function(t,e){this.resize(t);var i=.5*this.width,o=.5*this.height,n=Math.sin(e)*i,s=Math.cos(e)*o;return i*o/Math.sqrt(n*n+s*s)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){(void 0===this.width||this.labelModule.differentState(e,i))&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,s){if(this.resize(t,o,n),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,o,n,s),void 0!==this.options.label){var r=5;this.labelModule.draw(t,this.left+this.iconSize.width/2+this.margin.left,i+this.height/2+r,o)}this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){var i=5;this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+i)}}},{key:"_icon",value:function(t,e,i,o,n,s){var r=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=(o?"bold ":"")+r+"px "+this.options.icon.face,t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,s),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,s)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(177),m=o(f),v=function(t){function e(t,i,o,n){(0,a.default)(this,e);var r=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return r.imageObj=n,r}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(){this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,s){if(this.resize(),this.left=e-this.width/2,this.top=i-this.height/2,this.options.shapeProperties.useBorderWithImage===!0){var r=this.options.borderWidth,a=this.options.borderWidthSelected||2*this.options.borderWidth,h=(o?a:r)/this.body.view.scale;t.lineWidth=Math.min(this.width,h),t.beginPath(),t.strokeStyle=o?this.options.color.highlight.border:n?this.options.color.hover.border:this.options.color.border,t.fillStyle=o?this.options.color.highlight.background:n?this.options.color.hover.background:this.options.color.background,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),t.fill(),t.save(),h>0&&(this.enableBorderDashes(t),t.stroke(),this.disableBorderDashes(t)),t.restore(),t.closePath()}this._drawImageAtPosition(t,s),this._drawImageLabel(t,e,i,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){this.resize(),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(){this._resizeShape()}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"square",2,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i,o){this._resizeShape(i,o,e)}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"star",4,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(175),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){(void 0===this.width||this.labelModule.differentState(e,i))&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,s),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n),this.disableShadow(t,s),this.updateBoundingBox(e,i,t,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this.resize(i,o,n),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){this._resizeShape()}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"triangle",3,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(181),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){this._resizeShape()}},{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"triangleDown",3,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(192),d=o(h),l=i(160),u=o(l),c=i(1),p=i(91),f=i(93),m=function(){function t(e,i,o){var n=this;(0,s.default)(this,t),this.body=e,this.images=i,this.groups=o,this.body.functions.createEdge=this.create.bind(this),this.edgesListeners={add:function(t,e){n.add(e.items)},update:function(t,e){n.update(e.items)},remove:function(t,e){n.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},selectionWidth:1.5,selfReferenceSize:20,shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},c.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("_forceDisableDynamicCurves",function(e){"dynamic"===e&&(e="continuous");var i=!1;for(var o in t.body.edges)if(t.body.edges.hasOwnProperty(o)){var n=t.body.edges[o],s=t.body.data.edges._data[o];if(void 0!==s){var r=s.smooth;void 0!==r&&r.enabled===!0&&"dynamic"===r.type&&(void 0===e?n.setOptions({smooth:!1}):n.setOptions({smooth:{type:e}}),i=!0)}}i===!0&&t.body.emitter.emit("_dataChanged")}),this.body.emitter.on("_dataUpdated",function(){t.reconnectEdges()}),this.body.emitter.on("refreshEdges",this.refresh.bind(this)),this.body.emitter.on("refresh",this.refresh.bind(this)),this.body.emitter.on("destroy",function(){c.forEach(t.edgesListeners,function(e,i){t.body.data.edges&&t.body.data.edges.off(i,e)}),delete t.body.functions.createEdge,delete t.edgesListeners.add,delete t.edgesListeners.update,delete t.edgesListeners.remove,delete t.edgesListeners})}},{key:"setOptions",value:function(t){if(this.edgeOptions=t,void 0!==t){d.default.parseOptions(this.options,t);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)this.body.edges.hasOwnProperty(i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font){u.default.parseOptions(this.options.font,t);for(var o in this.body.edges)this.body.edges.hasOwnProperty(o)&&this.body.edges[o].updateLabelModule()}void 0===t.hidden&&void 0===t.physics&&e!==!0||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.data.edges;if(t instanceof p||t instanceof f)this.body.data.edges=t;else if(Array.isArray(t))this.body.data.edges=new p,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new p}if(o&&c.forEach(this.edgesListeners,function(t,e){o.off(e,t)}),this.body.edges={},this.body.data.edges){c.forEach(this.edgesListeners,function(t,i){e.body.data.edges.on(i,t)});var n=this.body.data.edges.getIds();this.add(n,!0)}i===!1&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,o=this.body.data.edges,n=0;n<t.length;n++){var s=t[n],r=i[s];r&&r.disconnect();var a=o.get(s,{showInternalIds:!0});i[s]=this.create(a)}e===!1&&this.body.emitter.emit("_dataChanged")}},{key:"update",value:function(t){for(var e=this.body.edges,i=this.body.data.edges,o=!1,n=0;n<t.length;n++){var s=t[n],r=i.get(s),a=e[s];void 0!==a?(a.disconnect(),o=a.setOptions(r)||o,a.connect()):(this.body.edges[s]=this.create(r),o=!0)}o===!0?this.body.emitter.emit("_dataChanged"):this.body.emitter.emit("_dataUpdated")}},{key:"remove",value:function(t){for(var e=this.body.edges,i=0;i<t.length;i++){var o=t[i],n=e[o];void 0!==n&&(n.cleanup(),n.disconnect(),delete e[o])}this.body.emitter.emit("_dataChanged")}},{key:"refresh",value:function(){var t=this.body.edges;for(var e in t){var i=void 0;t.hasOwnProperty(e)&&(i=t[e]);var o=this.body.data.edges._data[e];void 0!==i&&void 0!==o&&i.setOptions(o)}}},{key:"create",value:function(t){return new d.default(t,this.body,this.options,this.defaultOptions,this.edgeOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var o=i[t];o.from=null,o.to=null,o.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];i.fromId&&e.push(i.fromId),i.toId&&e.push(i.toId)}return e}}]),t}();e.default=m},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(82),s=o(n),r=i(55),a=o(r),h=i(62),d=o(h),l=i(115),u=o(l),c=i(116),p=o(c),f=i(160),m=o(f),v=i(193),g=o(v),y=i(197),b=o(y),_=i(198),w=o(_),x=i(199),k=o(x),O=i(1),D=function(){function t(e,i,o,n,s){if((0,u.default)(this,t),void 0===i)throw"No body provided";this.options=O.bridgeObject(o),this.globalOptions=o,this.defaultOptions=n,this.edgeOptions=s,this.body=i,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new m.default(this.body,this.options,!0),this.setOptions(e)}return(0,p.default)(t,[{key:"setOptions",value:function(e){if(e){t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=parseFloat(e.value)),this.choosify(e),this.updateLabelModule(e),this.labelModule.propagateFonts(this.edgeOptions,e,this.defaultOptions);var i=this.updateEdgeType();return this._setInteractionWidths(),this.connect(),void 0===e.hidden&&void 0===e.physics||(i=!0),i}}},{key:"choosify",value:function(t){this.chooser=!0;var e=[t,this.options,this.defaultOptions],i=O.topMost(e,"chosen");if("boolean"==typeof i)this.chooser=i;else if("object"===("undefined"==typeof i?"undefined":(0,d.default)(i))){var o=O.topMost(e,["chosen","edge"]);"boolean"!=typeof o&&"function"!=typeof o||(this.chooser=o)}}},{key:"getFormattingValues",value:function(){var t=this.options.arrows.to===!0||this.options.arrows.to.enabled===!0,e=this.options.arrows.from===!0||this.options.arrows.from.enabled===!0,i=this.options.arrows.middle===!0||this.options.arrows.middle.enabled===!0,o=this.options.color.inherit,n={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,arrowStrikethrough:this.options.arrowStrikethrough,color:o?void 0:this.options.color.color,inheritsColor:o,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width};if(this.selected||this.hover)if(this.chooser===!0){if(this.selected){var s=this.options.selectionWidth;"function"==typeof s?n.width=s(n.width):"number"==typeof s&&(n.width+=s),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.highlight,n.shadow=this.options.shadow.enabled}else if(this.hover){var r=this.options.hoverWidth;"function"==typeof r?n.width=r(n.width):"number"==typeof r&&(n.width+=r),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.hover,n.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(n,this.options.id,this.selected,this.hover),void 0!==n.color&&(n.inheritsColor=!1),n.shadow===!1&&(n.shadowColor===this.options.shadow.color&&n.shadowSize===this.options.shadow.size&&n.shadowX===this.options.shadow.x&&n.shadowY===this.options.shadow.y||(n.shadow=!0)));else n.shadow=this.options.shadow.enabled,n.width=Math.max(n.width,.3/this.body.view.scale);return n}},{key:"updateLabelModule",value:function(t){this.labelModule.setOptions(this.options,!0),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize),this.labelModule.constrain(this.edgeOptions,t,this.defaultOptions),this.labelModule.choosify(this.edgeOptions,t,this.defaultOptions)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof b.default&&t.enabled===!0&&"dynamic"===t.type||this.edgeType instanceof g.default&&t.enabled===!0&&"cubicBezier"===t.type||this.edgeType instanceof w.default&&t.enabled===!0&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof k.default&&t.type.enabled===!1)&&(i=!1),i===!0&&(e=this.cleanup())),i===!0?t.enabled===!0?"dynamic"===t.type?(e=!0,this.edgeType=new b.default(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new g.default(this.options,this.body,this.labelModule):this.edgeType=new w.default(this.options,this.body,this.labelModule):this.edgeType=new k.default(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,this.connected===!0?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var o=this.options.scaling.customScalingFunction(t,e,i,this.options.value),n=this.options.scaling.max-this.options.scaling.min;if(this.options.scaling.label.enabled===!0){var s=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+o*s}this.options.width=this.options.scaling.min+o*n}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,
-"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),o={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(o.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),e.arrowStrikethrough===!1&&(this.edgeType.fromPoint=o.from.core)),e.toArrow&&(o.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),e.arrowStrikethrough===!1&&(this.edgeType.toPoint=o.to.core)),e.middleArrow&&(o.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e)),this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawArrows(t,o,e),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t,e,i){i.fromArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.from),i.middleArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.middle),i.toArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.to)}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i=this.from,o=this.to,n=this.from.selected||this.to.selected||this.selected;if(i.id!=o.id){this.labelModule.pointToSelf=!1;var s=this.edgeType.getPoint(.5,e);t.save(),"horizontal"!==this.options.font.align&&(this.labelModule.calculateLabelSize(t,n,this.hover,s.x,s.y),t.translate(s.x,this.labelModule.size.yLine),this._rotateForLabelAlignment(t)),this.labelModule.draw(t,s.x,s.y,n,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var r,a,h=this.options.selfReferenceSize;i.shape.width>i.shape.height?(r=i.x+.5*i.shape.width,a=i.y-h):(r=i.x+h,a=i.y-.5*i.shape.height),s=this._pointOnCircle(r,a,h,.125),this.labelModule.draw(t,s.x,s.y,n,this.hover)}}}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=10,i=this.from.x,o=this.from.y,n=this.to.x,s=this.to.y,r=t.left,a=t.top,h=this.edgeType.getDistanceToEdge(i,o,n,s,r,a);return h<e}return!1}},{key:"_rotateForLabelAlignment",value:function(t){var e=this.from.y-this.to.y,i=this.from.x-this.to.x,o=Math.atan2(e,i);(o<-1&&i<0||o>0&&i<0)&&(o+=Math.PI),t.rotate(o)}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=["arrowStrikethrough","id","from","hidden","hoverWidth","label","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","to","title","value","width"];if(O.selectiveDeepExtend(n,t,e,i),O.mergeOptions(t,e,"smooth",i,o),O.mergeOptions(t,e,"shadow",i,o),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:i===!0&&null===e.dashes&&(t.dashes=(0,a.default)(o.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),O.mergeOptions(t.scaling,e.scaling,"label",i,o.scaling)):i===!0&&null===e.scaling&&(t.scaling=(0,a.default)(o.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=r.indexOf("to")!=-1,t.arrows.middle.enabled=r.indexOf("middle")!=-1,t.arrows.from.enabled=r.indexOf("from")!=-1}else{if("object"!==(0,d.default)(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+(0,s.default)(e.arrows));O.mergeOptions(t.arrows,e.arrows,"to",i,o.arrows),O.mergeOptions(t.arrows,e.arrows,"middle",i,o.arrows),O.mergeOptions(t.arrows,e.arrows,"from",i,o.arrows)}else i===!0&&null===e.arrows&&(t.arrows=(0,a.default)(o.arrows));if(void 0!==e.color&&null!==e.color)if(t.color=O.deepExtend({},t.color,!0),O.isString(e.color))t.color.color=e.color,t.color.highlight=e.color,t.color.hover=e.color,t.color.inherit=!1;else{var h=!1;void 0!==e.color.color&&(t.color.color=e.color.color,h=!0),void 0!==e.color.highlight&&(t.color.highlight=e.color.highlight,h=!0),void 0!==e.color.hover&&(t.color.hover=e.color.hover,h=!0),void 0!==e.color.inherit&&(t.color.inherit=e.color.inherit),void 0!==e.color.opacity&&(t.color.opacity=Math.min(1,Math.max(0,e.color.opacity))),void 0===e.color.inherit&&h===!0&&(t.color.inherit=!1)}else i===!0&&null===e.color&&(t.color=O.bridgeObject(o.color));void 0!==e.font&&null!==e.font?m.default.parseOptions(t.font,e):i===!0&&null===e.font&&(t.font=O.bridgeObject(o.font))}}]),t}();e.default=D},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(161),s=o(n),r=i(166),a=o(r),h=i(115),d=o(h),l=i(116),u=o(l),c=i(169),p=o(c),f=i(170),m=o(f),v=i(194),g=o(v),y=function(t){function e(t,i,o){return(0,d.default)(this,e),(0,p.default)(this,(e.__proto__||(0,a.default)(e)).call(this,t,i,o))}return(0,m.default)(e,t),(0,u.default)(e,[{key:"_line",value:function(t,e,i){var o=i[0],n=i[1];t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),void 0===i||void 0===o.x?t.lineTo(this.toPoint.x,this.toPoint.y):t.bezierCurveTo(o.x,o.y,n.x,n.y,this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"_getViaCoordinates",value:function(){var t=this.from.x-this.to.x,e=this.from.y-this.to.y,i=void 0,o=void 0,n=void 0,s=void 0,r=this.options.smooth.roundness;return(Math.abs(t)>Math.abs(e)||this.options.smooth.forceDirection===!0||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(o=this.from.y,s=this.to.y,i=this.from.x-r*t,n=this.to.x+r*t):(o=this.from.y-r*e,s=this.to.y+r*e,i=this.from.x,n=this.to.x),[{x:i,y:o},{x:n,y:s}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),h=(0,s.default)(a,2),d=h[0],l=h[1];return this._getDistanceToBezierEdge(t,e,i,o,n,r,d,l)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=(0,s.default)(e,2),o=i[0],n=i[1],r=t,a=[];a[0]=Math.pow(1-r,3),a[1]=3*r*Math.pow(1-r,2),a[2]=3*Math.pow(r,2)*(1-r),a[3]=Math.pow(r,3);var h=a[0]*this.fromPoint.x+a[1]*o.x+a[2]*n.x+a[3]*this.toPoint.x,d=a[0]*this.fromPoint.y+a[1]*o.y+a[2]*n.y+a[3]*this.toPoint.y;return{x:h,y:d}}}]),e}(g.default);e.default=y},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(195),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,s,r,a){var h=1e9,d=void 0,l=void 0,u=void 0,c=void 0,p=void 0,f=t,m=e,v=[0,0,0,0];for(l=1;l<10;l++)u=.1*l,v[0]=Math.pow(1-u,3),v[1]=3*u*Math.pow(1-u,2),v[2]=3*Math.pow(u,2)*(1-u),v[3]=Math.pow(u,3),c=v[0]*t+v[1]*r.x+v[2]*a.x+v[3]*i,p=v[0]*e+v[1]*r.y+v[2]*a.y+v[3]*o,l>0&&(d=this._getDistanceToLine(f,m,c,p,n,s),h=d<h?d:h),f=c,m=p;return h}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(196),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_findBorderPositionBezier",value:function(t,e){var i,o,n,s,r,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),h=10,d=0,l=0,u=1,c=.2,p=this.to,f=!1;for(t.id===this.from.id&&(p=this.from,f=!0);l<=u&&d<h;){var m=.5*(l+u);if(i=this.getPoint(m,a),o=Math.atan2(p.y-i.y,p.x-i.x),n=p.distanceToBorder(e,o),s=Math.sqrt(Math.pow(i.x-p.x,2)+Math.pow(i.y-p.y,2)),r=n-s,Math.abs(r)<c)break;r<0?f===!1?l=m:u=m:f===!1?u=m:l=m,d++}return i.t=m,i}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,s,r){var a=1e9,h=void 0,d=void 0,l=void 0,u=void 0,c=void 0,p=t,f=e;for(d=1;d<10;d++)l=.1*d,u=Math.pow(1-l,2)*t+2*l*(1-l)*r.x+Math.pow(l,2)*i,c=Math.pow(1-l,2)*e+2*l*(1-l)*r.y+Math.pow(l,2)*o,d>0&&(h=this._getDistanceToLine(p,f,u,c,n,s),a=h<a?h:a),p=u,f=c;return a}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(161),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(1),u=function(){function t(e,i,o){(0,a.default)(this,t),this.body=i,this.labelModule=o,this.options={},this.setOptions(e),this.colorDirty=!0,this.color={},this.selectionWidth=2,this.hoverWidth=1.5,this.fromPoint=this.from,this.toPoint=this.to}return(0,d.default)(t,[{key:"connect",value:function(){this.from=this.body.nodes[this.options.from],this.to=this.body.nodes[this.options.to]}},{key:"cleanup",value:function(){return!1}},{key:"setOptions",value:function(t){this.options=t,this.from=this.body.nodes[this.options.from],this.to=this.body.nodes[this.options.to],this.id=this.options.id}},{key:"drawLine",value:function(t,e,i,o,n){t.strokeStyle=this.getColor(t,e,i,o),t.lineWidth=e.width,e.dashes!==!1?this._drawDashedLine(t,e,n):this._drawLine(t,e,n)}},{key:"_drawLine",value:function(t,e,i,o,n){if(this.from!=this.to)this._line(t,e,i,o,n);else{var r=this._getCircleData(t,e),a=(0,s.default)(r,3),h=a[0],d=a[1],l=a[2];this._circle(t,e,h,d,l)}}},{key:"_drawDashedLine",value:function(t,e,i,o,n){t.lineCap="round";var r=[5,5];if(Array.isArray(e.dashes)===!0&&(r=e.dashes),void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var a=this._getCircleData(t,e),h=(0,s.default)(a,3),d=h[0],l=h[1],u=h[2];this._circle(t,e,d,l,u)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=this._getCircleData(t,e),p=(0,s.default)(c,3),f=p[0],m=p[1],v=p[2];this._circle(t,e,f,m,v)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){var e={},i={};if(this.from!=this.to)e=this._findBorderPosition(this.from,t),i=this._findBorderPosition(this.to,t);else{var o=this._getCircleData(t),n=(0,s.default)(o,3),r=n[0],a=n[1];n[2];e=this._findBorderPositionCircle(this.from,t,{x:r,y:a,low:.25,high:.6,direction:-1}),i=this._findBorderPositionCircle(this.from,t,{x:r,y:a,low:.6,high:.8,direction:1})}return{from:e,to:i}}},{key:"_getCircleData",value:function(t){var e=void 0,i=void 0,o=this.from,n=this.options.selfReferenceSize;return void 0!==t&&void 0===o.shape.width&&o.shape.resize(t),o.shape.width>o.shape.height?(e=o.x+.5*o.shape.width,i=o.y-n):(e=o.x+n,i=o.y-.5*o.shape.height),[e,i,n]}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){for(var o=i.x,n=i.y,s=i.low,r=i.high,a=i.direction,h=10,d=0,l=this.options.selfReferenceSize,u=void 0,c=void 0,p=void 0,f=void 0,m=void 0,v=.05,g=.5*(s+r);s<=r&&d<h&&(g=.5*(s+r),u=this._pointOnCircle(o,n,l,g),c=Math.atan2(t.y-u.y,t.x-u.x),p=t.distanceToBorder(e,c),f=Math.sqrt(Math.pow(u.x-t.x,2)+Math.pow(u.y-t.y,2)),m=p-f,!(Math.abs(m)<v));)m>0?a>0?s=g:r=g:a>0?r=g:s=g,d++;return u.t=g,u}},{key:"getLineWidth",value:function(t,e){return t===!0?Math.max(this.selectionWidth,.3/this.body.view.scale):e===!0?Math.max(this.hoverWidth,.3/this.body.view.scale):Math.max(this.options.width,.3/this.body.view.scale)}},{key:"getColor",value:function(t,e,i,o){if(e.inheritsColor!==!1){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var n=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),s=void 0,r=void 0;return s=this.from.options.color.highlight.border,r=this.to.options.color.highlight.border,this.from.selected===!1&&this.to.selected===!1?(s=l.overrideOpacity(this.from.options.color.border,e.opacity),r=l.overrideOpacity(this.to.options.color.border,e.opacity)):this.from.selected===!0&&this.to.selected===!1?r=this.to.options.color.border:this.from.selected===!1&&this.to.selected===!0&&(s=this.from.options.color.border),n.addColorStop(0,s),n.addColorStop(1,r),n}return"to"===e.inheritsColor?l.overrideOpacity(this.to.options.color.border,e.opacity):l.overrideOpacity(this.from.options.color.border,e.opacity)}return l.overrideOpacity(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,o,n){this.enableShadow(t,e),t.beginPath(),t.arc(i,o,n,0,2*Math.PI,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,o,n,r,a,h){var d=0;if(this.from!=this.to)d=this._getDistanceToEdge(t,e,i,o,n,r,a);else{var l=this._getCircleData(void 0,h),u=(0,s.default)(l,3),c=u[0],p=u[1],f=u[2],m=c-n,v=p-r;d=Math.abs(Math.sqrt(m*m+v*v)-f)}return this.labelModule.size.left<n&&this.labelModule.size.left+this.labelModule.size.width>n&&this.labelModule.size.top<r&&this.labelModule.size.top+this.labelModule.size.height>r?0:d}},{key:"_getDistanceToLine",value:function(t,e,i,o,n,s){var r=i-t,a=o-e,h=r*r+a*a,d=((n-t)*r+(s-e)*a)/h;d>1?d=1:d<0&&(d=0);var l=t+d*r,u=e+d*a,c=l-n,p=u-s;return Math.sqrt(c*c+p*p)}},{key:"getArrowData",value:function(t,e,i,o,n,r){var a=void 0,h=void 0,d=void 0,l=void 0,u=void 0,c=void 0,p=void 0,f=r.width;if("from"===e?(d=this.from,l=this.to,u=.1,c=r.fromArrowScale,p=r.fromArrowType):"to"===e?(d=this.to,l=this.from,u=-.1,c=r.toArrowScale,p=r.toArrowType):(d=this.to,l=this.from,c=r.middleArrowScale,p=r.middleArrowType),d!=l)if("middle"!==e)if(this.options.smooth.enabled===!0){h=this.findBorderPosition(d,t,{via:i});var m=this.getPoint(Math.max(0,Math.min(1,h.t+u)),i);a=Math.atan2(h.y-m.y,h.x-m.x)}else a=Math.atan2(d.y-l.y,d.x-l.x),h=this.findBorderPosition(d,t);else a=Math.atan2(d.y-l.y,d.x-l.x),h=this.getPoint(.5,i);else{var v=this._getCircleData(t),g=(0,s.default)(v,3),y=g[0],b=g[1],_=g[2];"from"===e?(h=this.findBorderPosition(this.from,t,{x:y,y:b,low:.25,high:.6,direction:-1}),a=h.t*-2*Math.PI+1.5*Math.PI+.1*Math.PI):"to"===e?(h=this.findBorderPosition(this.from,t,{x:y,y:b,low:.6,high:1,direction:1}),a=h.t*-2*Math.PI+1.5*Math.PI-1.1*Math.PI):(h=this._pointOnCircle(y,b,_,.175),a=3.9269908169872414)}var w=15*c+3*f,x=h.x-.9*w*Math.cos(a),k=h.y-.9*w*Math.sin(a),O={x:x,y:k};return{point:h,core:O,angle:a,length:w,type:p}}},{key:"drawArrowHead",value:function(t,e,i,o,n){t.strokeStyle=this.getColor(t,e,i,o),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,n.type&&"circle"===n.type.toLowerCase()?t.circleEndpoint(n.point.x,n.point.y,n.angle,n.length):t.arrowEndpoint(n.point.x,n.point.y,n.angle,n.length),this.enableShadow(t,e),t.fill(),this.disableShadow(t,e)}},{key:"enableShadow",value:function(t,e){e.shadow===!0&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){e.shadow===!0&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(161),s=o(n),r=i(166),a=o(r),h=i(115),d=o(h),l=i(116),u=o(l),c=i(169),p=o(c),f=i(170),m=o(f),v=i(195),g=o(v),y=function(t){function e(t,i,o){(0,d.default)(this,e);var n=(0,p.default)(this,(e.__proto__||(0,a.default)(e)).call(this,t,i,o));return n._boundFunction=function(){n.positionBezierNode()},n.body.emitter.on("_repositionBezierNodes",n._boundFunction),n}return(0,m.default)(e,t),(0,u.default)(e,[{key:"setOptions",value:function(t){var e=!1;this.options.physics!==t.physics&&(e=!0),this.options=t,this.id=this.options.id,this.from=this.body.nodes[this.options.from],this.to=this.body.nodes[this.options.to],this.setupSupportNode(),this.connect(),e===!0&&(this.via.setOptions({physics:this.options.physics}),this.positionBezierNode())}},{key:"connect",value:function(){this.from=this.body.nodes[this.options.from],this.to=this.body.nodes[this.options.to],void 0===this.from||void 0===this.to||this.options.physics===!1?this.via.setOptions({physics:!1}):this.from.id===this.to.id?this.via.setOptions({physics:!1}):this.via.setOptions({physics:!0})}},{key:"cleanup",value:function(){return this.body.emitter.off("_repositionBezierNodes",this._boundFunction),void 0!==this.via&&(delete this.body.nodes[this.via.id],this.via=void 0,!0)}},{key:"setupSupportNode",value:function(){if(void 0===this.via){var t="edgeId:"+this.id,e=this.body.functions.createNode({id:t,shape:"circle",physics:!0,hidden:!0});this.body.nodes[t]=e,this.via=e,this.via.parentEdgeId=this.id,this.positionBezierNode()}}},{key:"positionBezierNode",value:function(){void 0!==this.via&&void 0!==this.from&&void 0!==this.to?(this.via.x=.5*(this.from.x+this.to.x),this.via.y=.5*(this.from.y+this.to.y)):void 0!==this.via&&(this.via.x=0,this.via.y=0)}},{key:"_line",value:function(t,e,i){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),void 0===i.x?t.lineTo(this.toPoint.x,this.toPoint.y):t.quadraticCurveTo(i.x,i.y,this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){return this.via}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.via,i=t,o=void 0,n=void 0;if(this.from===this.to){var r=this._getCircleData(this.from),a=(0,s.default)(r,3),h=a[0],d=a[1],l=a[2],u=2*Math.PI*(1-i);o=h+l*Math.sin(u),n=d+l-l*(1-Math.cos(u))}else o=Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,n=Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y;return{x:o,y:n}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){return this._getDistanceToBezierEdge(t,e,i,o,n,s,this.via)}}]),e}(g.default);e.default=y},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(195),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_line",value:function(t,e,i){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),void 0===i.x?t.lineTo(this.toPoint.x,this.toPoint.y):t.quadraticCurveTo(i.x,i.y,this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t=void 0,e=void 0,i=this.options.smooth.roundness,o=this.options.smooth.type,n=Math.abs(this.from.x-this.to.x),s=Math.abs(this.from.y-this.to.y);if("discrete"===o||"diagonalCross"===o)Math.abs(this.from.x-this.to.x)<=Math.abs(this.from.y-this.to.y)?(this.from.y>=this.to.y?this.from.x<=this.to.x?(t=this.from.x+i*s,e=this.from.y-i*s):this.from.x>this.to.x&&(t=this.from.x-i*s,e=this.from.y-i*s):this.from.y<this.to.y&&(this.from.x<=this.to.x?(t=this.from.x+i*s,e=this.from.y+i*s):this.from.x>this.to.x&&(t=this.from.x-i*s,e=this.from.y+i*s)),"discrete"===o&&(t=n<i*s?this.from.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>=this.to.y?this.from.x<=this.to.x?(t=this.from.x+i*n,e=this.from.y-i*n):this.from.x>this.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n):this.from.y<this.to.y&&(this.from.x<=this.to.x?(t=this.from.x+i*n,e=this.from.y+i*n):this.from.x>this.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n)),"discrete"===o&&(e=s<i*n?this.from.y:e));else if("straightCross"===o)Math.abs(this.from.x-this.to.x)<=Math.abs(this.from.y-this.to.y)?(t=this.from.x,e=this.from.y<this.to.y?this.to.y-(1-i)*s:this.to.y+(1-i)*s):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(t=this.from.x<this.to.x?this.to.x-(1-i)*n:this.to.x+(1-i)*n,e=this.from.y);else if("horizontal"===o)t=this.from.x<this.to.x?this.to.x-(1-i)*n:this.to.x+(1-i)*n,e=this.from.y;else if("vertical"===o)t=this.from.x,e=this.from.y<this.to.y?this.to.y-(1-i)*s:this.to.y+(1-i)*s;else if("curvedCW"===o){n=this.to.x-this.from.x,s=this.from.y-this.to.y;var r=Math.sqrt(n*n+s*s),a=Math.PI,h=Math.atan2(s,n),d=(h+(.5*i+.5)*a)%(2*a);t=this.from.x+(.5*i+.5)*r*Math.sin(d),e=this.from.y+(.5*i+.5)*r*Math.cos(d)}else if("curvedCCW"===o){n=this.to.x-this.from.x,s=this.from.y-this.to.y;var l=Math.sqrt(n*n+s*s),u=Math.PI,c=Math.atan2(s,n),p=(c+(.5*-i+.5)*u)%(2*u);t=this.from.x+(.5*i+.5)*l*Math.sin(p),e=this.from.y+(.5*i+.5)*l*Math.cos(p)}else Math.abs(this.from.x-this.to.x)<=Math.abs(this.from.y-this.to.y)?this.from.y>=this.to.y?this.from.x<=this.to.x?(t=this.from.x+i*s,e=this.from.y-i*s,t=this.to.x<t?this.to.x:t):this.from.x>this.to.x&&(t=this.from.x-i*s,e=this.from.y-i*s,t=this.to.x>t?this.to.x:t):this.from.y<this.to.y&&(this.from.x<=this.to.x?(t=this.from.x+i*s,e=this.from.y+i*s,t=this.to.x<t?this.to.x:t):this.from.x>this.to.x&&(t=this.from.x-i*s,e=this.from.y+i*s,t=this.to.x>t?this.to.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>=this.to.y?this.from.x<=this.to.x?(t=this.from.x+i*n,e=this.from.y-i*n,e=this.to.y>e?this.to.y:e):this.from.x>this.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n,e=this.to.y>e?this.to.y:e):this.from.y<this.to.y&&(this.from.x<=this.to.x?(t=this.from.x+i*n,e=this.from.y+i*n,e=this.to.y<e?this.to.y:e):this.from.x>this.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n,e=this.to.y<e?this.to.y:e)));return{x:t,y:e}}},{key:"_findBorderPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){var r=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,o,n,s,r)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t,o=Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,n=Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y;return{x:o,y:n}}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(196),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,o=this.from;t.id===this.from.id&&(i=this.from,o=this.to);var n=Math.atan2(i.y-o.y,i.x-o.x),s=i.x-o.x,r=i.y-o.y,a=Math.sqrt(s*s+r*r),h=t.distanceToBorder(e,n),d=(a-h)/a,l={};return l.x=(1-d)*o.x+d*i.x,l.y=(1-d)*o.y+d*i.y,l}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){return this._getDistanceToLine(t,e,i,o,n,s)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(58),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(201),u=o(l),c=i(202),p=o(c),f=i(203),m=o(f),v=i(204),g=o(v),y=i(205),b=o(y),_=i(206),w=o(_),x=i(207),k=o(x),O=i(208),D=o(O),S=i(1),M=function(){function t(e){(0,a.default)(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0},S.extend(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return(0,d.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",function(){t.initPhysics()}),this.body.emitter.on("_layoutFailed",function(){t.layoutFailed=!0}),this.body.emitter.on("resetPhysics",function(){t.stopSimulation(),t.ready=!1}),this.body.emitter.on("disablePhysics",function(){t.physicsEnabled=!1,t.stopSimulation()}),this.body.emitter.on("restorePhysics",function(){t.setOptions(t.options),t.ready===!0&&t.startSimulation()}),this.body.emitter.on("startSimulation",function(){t.ready===!0&&t.startSimulation()}),this.body.emitter.on("stopSimulation",function(){t.stopSimulation()}),this.body.emitter.on("destroy",function(){t.stopSimulation(!1),t.body.emitter.off()}),this.body.emitter.on("_dataChanged",function(){t.updatePhysicsData()})}},{key:"setOptions",value:function(t){void 0!==t&&(t===!1?(this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation()):(this.physicsEnabled=!0,S.selectiveNotDeepExtend(["stabilization"],this.options,t),S.mergeOptions(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),this.options.enabled===!1&&(this.physicsEnabled=!1,this.stopSimulation()),this.timestep=this.options.timestep)),this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new k.default(this.body,this.physicsBody,t),this.edgesSolver=new g.default(this.body,this.physicsBody,t),this.gravitySolver=new D.default(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new p.default(this.body,this.physicsBody,t),this.edgesSolver=new g.default(this.body,this.physicsBody,t),this.gravitySolver=new w.default(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new m.default(this.body,this.physicsBody,t),this.edgesSolver=new b.default(this.body,this.physicsBody,t),this.gravitySolver=new w.default(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new u.default(this.body,this.physicsBody,t),this.edgesSolver=new g.default(this.body,this.physicsBody,t),this.gravitySolver=new w.default(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){this.physicsEnabled===!0&&this.options.enabled===!0?this.options.stabilization.enabled===!0?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){this.physicsEnabled===!0&&this.options.enabled===!0?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=this.simulationStep.bind(this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,t===!0&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,t===!0&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=Date.now();this.physicsTick();var e=Date.now()-t;(e<.4*this.simulationInterval||this.runDoubleSpeed===!0)&&this.stabilized===!1&&(this.physicsTick(),this.runDoubleSpeed=!0),this.stabilized===!0&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||this.startedStabilization===!0)&&setTimeout(function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0},0)}},{key:"physicsTick",value:function(){if(this.startedStabilization===!1&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0),this.stabilized===!1){if(this.adaptiveTimestep===!0&&this.adaptiveTimestepEnabled===!0){var t=1.2;this.adaptiveCounter%this.adaptiveInterval===0?(this.timestep=2*this.timestep,this.calculateForces(),this.moveNodes(),this.revert(),this.timestep=.5*this.timestep,this.calculateForces(),this.moveNodes(),this.calculateForces(),this.moveNodes(),this._evaluateStepQuality()===!0?this.timestep=t*this.timestep:this.timestep/t<this.options.timestep?this.timestep=this.options.timestep:(this.adaptiveCounter=-1,this.timestep=Math.max(this.options.timestep,this.timestep/t))):(this.calculateForces(),this.moveNodes()),this.adaptiveCounter+=1}else this.timestep=this.options.timestep,this.calculateForces(),this.moveNodes();this.stabilized===!0&&this.revert(),this.stabilizationIterations++}}},{key:"updatePhysicsData",value:function(){this.physicsBody.forces={},this.physicsBody.physicsNodeIndices=[],this.physicsBody.physicsEdgeIndices=[];var t=this.body.nodes,e=this.body.edges;for(var i in t)t.hasOwnProperty(i)&&t[i].options.physics===!0&&this.physicsBody.physicsNodeIndices.push(t[i].id);for(var o in e)e.hasOwnProperty(o)&&e[o].options.physics===!0&&this.physicsBody.physicsEdgeIndices.push(e[o].id);for(var n=0;n<this.physicsBody.physicsNodeIndices.length;n++){var s=this.physicsBody.physicsNodeIndices[n];this.physicsBody.forces[s]={x:0,y:0},void 0===this.physicsBody.velocities[s]&&(this.physicsBody.velocities[s]={x:0,y:0})}for(var r in this.physicsBody.velocities)void 0===t[r]&&delete this.physicsBody.velocities[r]}},{key:"revert",value:function(){var t=(0,s.default)(this.previousStates),e=this.body.nodes,i=this.physicsBody.velocities;this.referenceState={};for(var o=0;o<t.length;o++){var n=t[o];void 0!==e[n]?e[n].options.physics===!0&&(this.referenceState[n]={positions:{x:e[n].x,y:e[n].y}},i[n].x=this.previousStates[n].vx,i[n].y=this.previousStates[n].vy,e[n].x=this.previousStates[n].x,e[n].y=this.previousStates[n].y):delete this.previousStates[n]}}},{key:"_evaluateStepQuality",value:function(){var t=void 0,e=void 0,i=void 0,o=this.body.nodes,n=this.referenceState,s=.3;for(var r in this.referenceState)if(this.referenceState.hasOwnProperty(r)&&void 0!==o[r]&&(t=o[r].x-n[r].positions.x,e=o[r].y-n[r].positions.y,i=Math.sqrt(Math.pow(t,2)+Math.pow(e,2)),i>s))return!1;return!0}},{key:"moveNodes",
-value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=this.options.maxVelocity?this.options.maxVelocity:1e9,i=0,o=0,n=5,s=0;s<t.length;s++){var r=t[s],a=this._performStep(r,e);i=Math.max(i,a),o+=a}this.adaptiveTimestepEnabled=o/t.length<n,this.stabilized=i<this.options.minVelocity}},{key:"_performStep",value:function(t,e){var i=this.body.nodes[t],o=this.timestep,n=this.physicsBody.forces,s=this.physicsBody.velocities;if(this.previousStates[t]={x:i.x,y:i.y,vx:s[t].x,vy:s[t].y},i.options.fixed.x===!1){var r=this.modelOptions.damping*s[t].x,a=(n[t].x-r)/i.options.mass;s[t].x+=a*o,s[t].x=Math.abs(s[t].x)>e?s[t].x>0?e:-e:s[t].x,i.x+=s[t].x*o}else n[t].x=0,s[t].x=0;if(i.options.fixed.y===!1){var h=this.modelOptions.damping*s[t].y,d=(n[t].y-h)/i.options.mass;s[t].y+=d*o,s[t].y=Math.abs(s[t].y)>e?s[t].y>0?e:-e:s[t].y,i.y+=s[t].y*o}else n[t].y=0,s[t].y=0;var l=Math.sqrt(Math.pow(s[t].x,2)+Math.pow(s[t].y,2));return l}},{key:"calculateForces",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve()}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)t.hasOwnProperty(e)&&t[e].x&&t[e].y&&(this.freezeCache[e]={x:t[e].options.fixed.x,y:t[e].options.fixed.y},t[e].options.fixed.x=!0,t[e].options.fixed.y=!0)}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)t.hasOwnProperty(e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;return"number"!=typeof e&&(console.log("The stabilize method needs a numeric amount of iterations. Switching to default: ",this.options.stabilization.iterations),e=this.options.stabilization.iterations),0===this.physicsBody.physicsNodeIndices.length?void(this.ready=!0):(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,this.options.stabilization.onlyDynamicEdges===!0&&this._freezeNodes(),this.stabilizationIterations=0,void setTimeout(function(){return t._stabilizationBatch()},0))}},{key:"_stabilizationBatch",value:function(){this.startedStabilization===!1&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0);for(var t=0;this.stabilized===!1&&t<this.options.stabilization.updateInterval&&this.stabilizationIterations<this.targetIterations;)this.physicsTick(),t++;this.stabilized===!1&&this.stabilizationIterations<this.targetIterations?(this.body.emitter.emit("stabilizationProgress",{iterations:this.stabilizationIterations,total:this.targetIterations}),setTimeout(this._stabilizationBatch.bind(this),0)):this._finalizeStabilization()}},{key:"_finalizeStabilization",value:function(){this.body.emitter.emit("_allowRedraw"),this.options.stabilization.fit===!0&&this.body.emitter.emit("fit"),this.options.stabilization.onlyDynamicEdges===!0&&this._restoreFrozenNodes(),this.body.emitter.emit("stabilizationIterationsDone"),this.body.emitter.emit("_requestRedraw"),this.stabilized===!0?this._emitStabilized():this.startSimulation(),this.ready=!0}},{key:"_drawForces",value:function(t){for(var e=0;e<this.physicsBody.physicsNodeIndices.length;e++){var i=this.body.nodes[this.physicsBody.physicsNodeIndices[e]],o=this.physicsBody.forces[this.physicsBody.physicsNodeIndices[e]],n=20,s=.03,r=Math.sqrt(Math.pow(o.x,2)+Math.pow(o.x,2)),a=Math.min(Math.max(5,r),15),h=3*a,d=S.HSVToHex((180-180*Math.min(1,Math.max(0,s*r)))/360,1,1);t.lineWidth=a,t.strokeStyle=d,t.beginPath(),t.moveTo(i.x,i.y),t.lineTo(i.x+n*o.x,i.y+n*o.y),t.stroke();var l=Math.atan2(o.y,o.x);t.fillStyle=d,t.arrowEndpoint(i.x+n*o.x+Math.cos(l)*h,i.y+n*o.y+Math.sin(l)*h,l,h),t.fill()}}}]),t}();e.default=M},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(o),this.randomSeed=5}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"seededRandom",value:function(){var t=1e4*Math.sin(this.randomSeed++);return t-Math.floor(t)}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t=void 0,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,o=i.length,n=this._formBarnesHutTree(e,i);this.barnesHutTree=n;for(var s=0;s<o;s++)t=e[i[s]],t.options.mass>0&&(this._getForceContribution(n.root.children.NW,t),this._getForceContribution(n.root.children.NE,t),this._getForceContribution(n.root.children.SW,t),this._getForceContribution(n.root.children.SE,t))}}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=void 0,o=void 0,n=void 0;i=t.centerOfMass.x-e.x,o=t.centerOfMass.y-e.y,n=Math.sqrt(i*i+o*o),n*t.calcSize>this.thetaInversed?this._calculateForces(n,i,o,e,t):4===t.childrenCount?(this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)):t.children.data.id!=e.id&&this._calculateForces(n,i,o,e,t)}}},{key:"_calculateForces",value:function(t,e,i,o,n){0===t&&(t=.1,e=t),this.overlapAvoidanceFactor<1&&o.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*o.shape.radius,t-o.shape.radius));var s=this.options.gravitationalConstant*n.mass*o.options.mass/Math.pow(t,3),r=e*s,a=i*s;this.physicsBody.forces[o.id].x+=r,this.physicsBody.forces[o.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i=void 0,o=e.length,n=t[e[0]].x,s=t[e[0]].y,r=t[e[0]].x,a=t[e[0]].y,h=1;h<o;h++){var d=t[e[h]].x,l=t[e[h]].y;t[e[h]].options.mass>0&&(d<n&&(n=d),d>r&&(r=d),l<s&&(s=l),l>a&&(a=l))}var u=Math.abs(r-n)-Math.abs(a-s);u>0?(s-=.5*u,a+=.5*u):(n+=.5*u,r-=.5*u);var c=1e-5,p=Math.max(c,Math.abs(r-n)),f=.5*p,m=.5*(n+r),v=.5*(s+a),g={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:m-f,maxX:m+f,minY:v-f,maxY:v+f},size:p,calcSize:1/p,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(g.root);for(var y=0;y<o;y++)i=t[e[y]],i.options.mass>0&&this._placeInTree(g.root,i);return g}},{key:"_updateBranchMass",value:function(t,e){var i=t.mass+e.options.mass,o=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.options.mass,t.centerOfMass.x*=o,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.options.mass,t.centerOfMass.y*=o,t.mass=i;var n=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidth<n?n:t.maxWidth}},{key:"_placeInTree",value:function(t,e,i){1==i&&void 0!==i||this._updateBranchMass(t,e),t.children.NW.range.maxX>e.x?t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NW"):this._placeInRegion(t,e,"SW"):t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NE"):this._placeInRegion(t,e,"SE")}},{key:"_placeInRegion",value:function(t,e,i){switch(t.children[i].childrenCount){case 0:t.children[i].children.data=e,t.children[i].childrenCount=1,this._updateBranchMass(t.children[i],e);break;case 1:t.children[i].children.data.x===e.x&&t.children[i].children.data.y===e.y?(e.x+=this.seededRandom(),e.y+=this.seededRandom()):(this._splitBranch(t.children[i]),this._placeInTree(t.children[i],e));break;case 4:this._placeInTree(t.children[i],e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i=void 0,o=void 0,n=void 0,s=void 0,r=.5*t.size;switch(e){case"NW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY,s=t.range.minY+r;break;case"NE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY,s=t.range.minY+r;break;case"SW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY+r,s=t.range.maxY;break;case"SE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY+r,s=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:o,minY:n,maxY:s},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,o,n,s,r,a,h=this.body.nodes,d=this.physicsBody.physicsNodeIndices,l=this.physicsBody.forces,u=this.options.nodeDistance,c=-2/3/u,p=4/3,f=0;f<d.length-1;f++){r=h[d[f]];for(var m=f+1;m<d.length;m++)a=h[d[m]],t=a.x-r.x,e=a.y-r.y,i=Math.sqrt(t*t+e*e),0===i&&(i=.1*Math.random(),t=i),i<2*u&&(s=i<.5*u?1:c*i+p,s/=i,o=t*s,n=e*s,l[r.id].x-=o,l[r.id].y-=n,l[a.id].x+=o,l[a.id].y+=n)}}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){var t,e,i,o,n,s,r,a,h,d,l=this.body.nodes,u=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,p=this.options.nodeDistance;for(h=0;h<u.length-1;h++)for(r=l[u[h]],d=h+1;d<u.length;d++)if(a=l[u[d]],r.level===a.level){t=a.x-r.x,e=a.y-r.y,i=Math.sqrt(t*t+e*e);var f=.05;s=i<p?-Math.pow(f*i,2)+Math.pow(f*p,2):0,0===i?i=.01:s/=i,o=t*s,n=e*s,c[r.id].x-=o,c[r.id].y-=n,c[a.id].x+=o,c[a.id].y+=n}}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t=void 0,e=void 0,i=this.physicsBody.physicsEdgeIndices,o=this.body.edges,n=void 0,s=void 0,r=void 0,a=0;a<i.length;a++)e=o[i[a]],e.connected===!0&&e.toId!==e.fromId&&void 0!==this.body.nodes[e.toId]&&void 0!==this.body.nodes[e.fromId]&&(void 0!==e.edgeType.via?(t=void 0===e.options.length?this.options.springLength:e.options.length,n=e.to,s=e.edgeType.via,r=e.from,this._calculateSpringForce(n,s,.5*t),this._calculateSpringForce(s,r,.5*t)):(t=void 0===e.options.length?1.5*this.options.springLength:e.options.length,this._calculateSpringForce(e.from,e.to,t)))}},{key:"_calculateSpringForce",value:function(t,e,i){var o=t.x-e.x,n=t.y-e.y,s=Math.max(Math.sqrt(o*o+n*n),.01),r=this.options.springConstant*(i-s)/s,a=o*r,h=n*r;void 0!==this.physicsBody.forces[t.id]&&(this.physicsBody.forces[t.id].x+=a,this.physicsBody.forces[t.id].y+=h),void 0!==this.physicsBody.forces[e.id]&&(this.physicsBody.forces[e.id].x-=a,this.physicsBody.forces[e.id].y-=h)}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,o,n,s,r,a,h=this.body.edges,d=.5,l=this.physicsBody.physicsEdgeIndices,u=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,p=0;p<u.length;p++){var f=u[p];c[f].springFx=0,c[f].springFy=0}for(var m=0;m<l.length;m++)e=h[l[m]],e.connected===!0&&(t=void 0===e.options.length?this.options.springLength:e.options.length,i=e.from.x-e.to.x,o=e.from.y-e.to.y,a=Math.sqrt(i*i+o*o),a=0===a?.01:a,r=this.options.springConstant*(t-a)/a,n=i*r,s=o*r,e.to.level!=e.from.level?(void 0!==c[e.toId]&&(c[e.toId].springFx-=n,c[e.toId].springFy-=s),void 0!==c[e.fromId]&&(c[e.fromId].springFx+=n,c[e.fromId].springFy+=s)):(void 0!==c[e.toId]&&(c[e.toId].x-=d*n,c[e.toId].y-=d*s),void 0!==c[e.fromId]&&(c[e.fromId].x+=d*n,c[e.fromId].y+=d*s)));for(var v,g,r=1,y=0;y<u.length;y++){var b=u[y];v=Math.min(r,Math.max(-r,c[b].springFx)),g=Math.min(r,Math.max(-r,c[b].springFy)),c[b].x+=v,c[b].y+=g}for(var _=0,w=0,x=0;x<u.length;x++){var k=u[x];_+=c[k].x,w+=c[k].y}for(var O=_/u.length,D=w/u.length,S=0;S<u.length;S++){var M=u[S];c[M].x-=O,c[M].y-=D}}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t=void 0,e=void 0,i=void 0,o=void 0,n=this.body.nodes,s=this.physicsBody.physicsNodeIndices,r=this.physicsBody.forces,a=0;a<s.length;a++){var h=s[a];o=n[h],t=-o.x,e=-o.y,i=Math.sqrt(t*t+e*e),this._calculateForces(i,t,e,r,o)}}},{key:"_calculateForces",value:function(t,e,i,o,n){var s=0===t?0:this.options.centralGravity/t;o[n.id].x=e*s,o[n.id].y=i*s}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(201),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_calculateForces",value:function(t,e,i,o,n){0===t&&(t=.1*Math.random(),e=t),this.overlapAvoidanceFactor<1&&o.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*o.shape.radius,t-o.shape.radius));var s=o.edges.length+1,r=this.options.gravitationalConstant*n.mass*o.options.mass*s/Math.pow(t,2),a=e*r,h=i*r;this.physicsBody.forces[o.id].x+=a,this.physicsBody.forces[o.id].y+=h}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(169),u=o(l),c=i(170),p=o(c),f=i(206),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_calculateForces",value:function(t,e,i,o,n){if(t>0){var s=n.edges.length+1,r=this.options.centralGravity*s*n.options.mass;o[n.id].x=e*r,o[n.id].y=i*r}}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(58),s=o(n),r=i(62),a=o(r),h=i(115),d=o(h),l=i(116),u=o(l),c=i(210),p=o(c),f=i(211),m=o(f),v=i(1),g=function(){function t(e){var i=this;(0,d.default)(this,t),this.body=e,this.clusteredNodes={},this.clusteredEdges={},this.options={},this.defaultOptions={},v.extend(this.options,this.defaultOptions),this.body.emitter.on("_resetData",function(){i.clusteredNodes={},i.clusteredEdges={}})}return(0,u.default)(t,[{key:"clusterByHubsize",value:function(t,e){void 0===t?t=this._getHubSize():"object"===("undefined"==typeof t?"undefined":(0,a.default)(t))&&(e=this._checkOptions(t),t=this._getHubSize());for(var i=[],o=0;o<this.body.nodeIndices.length;o++){var n=this.body.nodes[this.body.nodeIndices[o]];n.edges.length>=t&&i.push(n.id)}for(var s=0;s<i.length;s++)this.clusterByConnection(i[s],e,!0);this.body.emitter.emit("_dataChanged")}},{key:"cluster",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===t.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");t=this._checkOptions(t);for(var i={},o={},n=0;n<this.body.nodeIndices.length;n++){var s=this.body.nodeIndices[n],r=this.body.nodes[s],a=p.default.cloneOptions(r);if(t.joinCondition(a)===!0){i[s]=this.body.nodes[s];for(var h=0;h<r.edges.length;h++){var d=r.edges[h];void 0===this.clusteredEdges[d.id]&&(o[d.id]=d)}}}this._cluster(i,o,t,e)}},{key:"clusterByEdgeCount",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var o=[],n={},r=void 0,a=void 0,h=void 0,d=void 0,l=void 0,u=0;u<this.body.nodeIndices.length;u++){var c={},f={};if(d=this.body.nodeIndices[u],void 0===n[d]){l=0,h=this.body.nodes[d],a=[];for(var m=0;m<h.edges.length;m++)r=h.edges[m],void 0===this.clusteredEdges[r.id]&&(r.toId!==r.fromId&&l++,a.push(r));if(l===t){for(var v=!0,g=0;g<a.length;g++){r=a[g];var y=this._getConnectedId(r,d);if(void 0===e.joinCondition)f[r.id]=r,c[d]=this.body.nodes[d],c[y]=this.body.nodes[y],n[d]=!0;else{var b=p.default.cloneOptions(this.body.nodes[d]);if(e.joinCondition(b)!==!0){v=!1;break}f[r.id]=r,c[d]=this.body.nodes[d],n[d]=!0}}(0,s.default)(c).length>0&&(0,s.default)(f).length>0&&v===!0&&o.push({nodes:c,edges:f})}}}for(var _=0;_<o.length;_++)this._cluster(o[_].nodes,o[_].edges,e,!1);i===!0&&this.body.emitter.emit("_dataChanged")}},{key:"clusterOutliers",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var o=this.body.nodes[t];e=this._checkOptions(e,o),void 0===e.clusterNodeProperties.x&&(e.clusterNodeProperties.x=o.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=o.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=o.options.fixed.x,e.clusterNodeProperties.fixed.y=o.options.fixed.y);var n={},r={},a=o.id,h=p.default.cloneOptions(o);n[a]=o;for(var d=0;d<o.edges.length;d++){var l=o.edges[d];if(void 0===this.clusteredEdges[l.id]){var u=this._getConnectedId(l,a);if(void 0===this.clusteredNodes[u])if(u!==a)if(void 0===e.joinCondition)r[l.id]=l,n[u]=this.body.nodes[u];else{var c=p.default.cloneOptions(this.body.nodes[u]);e.joinCondition(h,c)===!0&&(r[l.id]=l,n[u]=this.body.nodes[u])}else r[l.id]=l}}var f=(0,s.default)(n).map(function(t){return n[t].id});for(m in n)for(var m=n[m],v=0;v<m.edges.length;v++){var g=m.edges[v];f.indexOf(this._getConnectedId(g,m.id))>-1&&(r[g.id]=g)}this._cluster(n,r,e,i)}},{key:"_createClusterEdges",value:function(t,e,i,o){for(var n=void 0,r=void 0,a=void 0,h=void 0,d=void 0,l=void 0,u=(0,s.default)(t),c=[],f=0;f<u.length;f++){r=u[f],a=t[r];for(var m=0;m<a.edges.length;m++)n=a.edges[m],void 0===this.clusteredEdges[n.id]&&(n.toId==n.fromId?e[n.id]=n:n.toId==r?(h=i.id,d=n.fromId,l=d):(h=n.toId,d=i.id,l=h),void 0===t[l]&&c.push({edge:n,fromId:d,toId:h}))}for(var g=0;g<c.length;g++){var y=c[g].edge,b=p.default.cloneOptions(y,"edge");v.deepExtend(b,o),b.from=c[g].fromId,b.to=c[g].toId,b.id="clusterEdge:"+v.randomUUID();var _=this.body.functions.createEdge(b);_.clusteringEdgeReplacingId=y.id,this.body.edges[y.id].edgeReplacedById=_.id,this.body.edges[_.id]=_,_.connect(),this._backupEdgeOptions(y),y.setOptions({physics:!1,hidden:!0})}}},{key:"_checkOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];if(0!=(0,s.default)(t).length&&(1!=(0,s.default)(t).length||1==i.clusterNodeProperties.allowSingleNodeCluster)){for(var n in t)if(t.hasOwnProperty(n)&&void 0!==this.clusteredNodes[n])return;var r=v.deepExtend({},i.clusterNodeProperties);if(void 0!==i.processProperties){var a=[];for(var h in t)if(t.hasOwnProperty(h)){var d=p.default.cloneOptions(t[h]);a.push(d)}var l=[];for(var u in e)if(e.hasOwnProperty(u)&&"clusterEdge:"!==u.substr(0,12)){var c=p.default.cloneOptions(e[u],"edge");l.push(c)}if(r=i.processProperties(r,a,l),!r)throw new Error("The processProperties function does not return properties!")}void 0===r.id&&(r.id="cluster:"+v.randomUUID());var f=r.id;void 0===r.label&&(r.label="cluster");var g=void 0;void 0===r.x&&(g=this._getClusterPosition(t),r.x=g.x),void 0===r.y&&(void 0===g&&(g=this._getClusterPosition(t)),r.y=g.y),r.id=f;var y=this.body.functions.createNode(r,m.default);y.isCluster=!0,y.containedNodes=t,y.containedEdges=e,y.clusterEdgeProperties=i.clusterEdgeProperties,this.body.nodes[r.id]=y,this._createClusterEdges(t,e,r,i.clusterEdgeProperties);for(var b in e)if(e.hasOwnProperty(b)&&void 0!==this.body.edges[b]){var _=this.body.edges[b];this._backupEdgeOptions(_),_.setOptions({physics:!1,hidden:!0})}for(var w in t)t.hasOwnProperty(w)&&(this.clusteredNodes[w]={clusterId:r.id,node:this.body.nodes[w]},this.body.nodes[w].setOptions({hidden:!0,physics:!1}));r.id=void 0,o===!0&&this.body.emitter.emit("_dataChanged")}}},{key:"_backupEdgeOptions",value:function(t){void 0===this.clusteredEdges[t.id]&&(this.clusteredEdges[t.id]={physics:t.options.physics,hidden:t.options.hidden})}},{key:"_restoreEdge",value:function(t){var e=this.clusteredEdges[t.id];void 0!==e&&(t.setOptions({physics:e.physics,hidden:e.hidden}),delete this.clusteredEdges[t.id])}},{key:"isCluster",value:function(t){return void 0!==this.body.nodes[t]?this.body.nodes[t].isCluster===!0:(console.log("Node does not exist."),!1)}},{key:"_getClusterPosition",value:function(t){for(var e=(0,s.default)(t),i=t[e[0]].x,o=t[e[0]].x,n=t[e[0]].y,r=t[e[0]].y,a=void 0,h=1;h<e.length;h++)a=t[e[h]],i=a.x<i?a.x:i,o=a.x>o?a.x:o,n=a.y<n?a.y:n,r=a.y>r?a.y:r;return{x:.5*(i+o),y:.5*(n+r)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");if(void 0===this.body.nodes[t])throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(void 0===this.body.nodes[t].containedNodes)return void console.log("The node:"+t+" is not a cluster.");var o=this.body.nodes[t],n=o.containedNodes,s=o.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var r={},a={x:o.x,y:o.y};for(var h in n)if(n.hasOwnProperty(h)){var d=this.body.nodes[h];r[h]={x:d.x,y:d.y}}var l=e.releaseFunction(a,r);for(var u in n)if(n.hasOwnProperty(u)){var c=this.body.nodes[u];void 0!==l[u]&&(c.x=void 0===l[u].x?o.x:l[u].x,c.y=void 0===l[u].y?o.y:l[u].y)}}else for(var f in n)if(n.hasOwnProperty(f)){var m=this.body.nodes[f];m=n[f],m.options.fixed.x===!1&&(m.x=o.x),m.options.fixed.y===!1&&(m.y=o.y)}for(var g in n)if(n.hasOwnProperty(g)){var y=this.body.nodes[g];y.vx=o.vx,y.vy=o.vy,y.setOptions({hidden:!1,physics:!0}),delete this.clusteredNodes[g]}for(var b=[],_=0;_<o.edges.length;_++)b.push(o.edges[_]);for(var w=0;w<b.length;w++){var x=b[w],k=this._getConnectedId(x,t);if(void 0!==this.clusteredNodes[k]){var O=this.body.nodes[this.clusteredNodes[k].clusterId],D=this.body.edges[x.clusteringEdgeReplacingId];if(void 0!==D){O.containedEdges[D.id]=D,delete s[D.id];var S=D.fromId,M=D.toId;D.toId==k?M=this.clusteredNodes[k].clusterId:S=this.clusteredNodes[k].clusterId;var C=p.default.cloneOptions(D,"edge");v.deepExtend(C,O.clusterEdgeProperties);var T="clusterEdge:"+v.randomUUID();v.deepExtend(C,{from:S,to:M,hidden:!1,physics:!0,id:T});var E=this.body.functions.createEdge(C);E.clusteringEdgeReplacingId=D.id,this.body.edges[T]=E,this.body.edges[T].connect()}}else{var P=this.body.edges[x.clusteringEdgeReplacingId];void 0!==P&&this._restoreEdge(P)}x.cleanup(),x.disconnect(),delete this.body.edges[x.id]}for(var I in s)s.hasOwnProperty(I)&&this._restoreEdge(s[I]);delete this.body.nodes[t],i===!0&&this.body.emitter.emit("_dataChanged")}},{key:"getNodesInCluster",value:function(t){var e=[];if(this.isCluster(t)===!0){var i=this.body.nodes[t].containedNodes;for(var o in i)i.hasOwnProperty(o)&&e.push(this.body.nodes[o].id)}return e}},{key:"findNode",value:function(t){for(var e=[],i=100,o=0;void 0!==this.clusteredNodes[t]&&o<i;)e.push(this.body.nodes[t].id),t=this.clusteredNodes[t].clusterId,o++;return e.push(this.body.nodes[t].id),e.reverse(),e}},{key:"updateClusteredNode",value:function(t,e){if(void 0===t)throw new Error("No clusteredNodeId supplied to updateClusteredNode.");if(void 0===e)throw new Error("No newOptions supplied to updateClusteredNode.");if(void 0===this.body.nodes[t])throw new Error("The clusteredNodeId supplied to updateClusteredNode does not exist.");this.body.nodes[t].setOptions(e),this.body.emitter.emit("_dataChanged")}},{key:"updateEdge",value:function(t,e){if(void 0===t)throw new Error("No startEdgeId supplied to updateEdge.");if(void 0===e)throw new Error("No newOptions supplied to updateEdge.");if(void 0===this.body.edges[t])throw new Error("The startEdgeId supplied to updateEdge does not exist.");for(var i=this.getClusteredEdges(t),o=0;o<i.length;o++){var n=this.body.edges[i[o]];n.setOptions(e)}this.body.emitter.emit("_dataChanged")}},{key:"getClusteredEdges",value:function(t){for(var e=[],i=100,o=0;void 0!==t&&void 0!==this.body.edges[t]&&o<i;)e.push(this.body.edges[t].id),t=this.body.edges[t].edgeReplacedById,o++;return e.reverse(),e}},{key:"getBaseEdge",value:function(t){for(var e=t,i=100,o=0;void 0!==t&&void 0!==this.body.edges[t]&&o<i;)t=this.body.edges[t].clusteringEdgeReplacingId,o++,void 0!==t&&(e=t);return e}},{key:"_getConnectedId",value:function(t,e){return t.toId!=e?t.toId:t.fromId!=e?t.fromId:t.fromId}},{key:"_getHubSize",value:function(){for(var t=0,e=0,i=0,o=0,n=0;n<this.body.nodeIndices.length;n++){var s=this.body.nodes[this.body.nodeIndices[n]];s.edges.length>o&&(o=s.edges.length),t+=s.edges.length,e+=Math.pow(s.edges.length,2),i+=1}t/=i,e/=i;var r=e-Math.pow(t,2),a=Math.sqrt(r),h=Math.floor(t+2*a);return h>o&&(h=o),h}}]),t}();e.default=g},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(1),d=function(){function t(){(0,s.default)(this,t)}return(0,a.default)(t,null,[{key:"getRange",value:function(t){var e,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,s=1e9,r=-1e9;if(i.length>0)for(var a=0;a<i.length;a++)e=t[i[a]],s>e.shape.boundingBox.left&&(s=e.shape.boundingBox.left),r<e.shape.boundingBox.right&&(r=e.shape.boundingBox.right),o>e.shape.boundingBox.top&&(o=e.shape.boundingBox.top),n<e.shape.boundingBox.bottom&&(n=e.shape.boundingBox.bottom);return 1e9===s&&r===-1e9&&1e9===o&&n===-1e9&&(o=0,n=0,s=0,r=0),{minX:s,maxX:r,minY:o,maxY:n}}},{key:"getRangeCore",value:function(t){var e,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,s=1e9,r=-1e9;if(i.length>0)for(var a=0;a<i.length;a++)e=t[i[a]],s>e.x&&(s=e.x),r<e.x&&(r=e.x),o>e.y&&(o=e.y),n<e.y&&(n=e.y);return 1e9===s&&r===-1e9&&1e9===o&&n===-1e9&&(o=0,n=0,s=0,r=0),{minX:s,maxX:r,minY:o,maxY:n}}},{key:"findCenter",value:function(t){return{x:.5*(t.maxX+t.minX),y:.5*(t.maxY+t.minY)}}},{key:"cloneOptions",value:function(t,e){var i={};return void 0===e||"node"===e?(h.deepExtend(i,t.options,!0),i.x=t.x,i.y=t.y,i.amountOfConnections=t.edges.length):h.deepExtend(i,t.options,!0),i}}]),t}();e.default=d},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(166),s=o(n),r=i(115),a=o(r),h=i(169),d=o(h),l=i(170),u=o(l),c=i(159),p=o(c),f=function(t){function e(t,i,o,n,r){(0,a.default)(this,e);var h=(0,d.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o,n,r));return h.isCluster=!0,h.containedNodes={},h.containedEdges={},h}return(0,u.default)(e,t),e}(p.default);e.default=f},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r);"undefined"!=typeof window&&(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame);var h=i(1),d=function(){function t(e,i){(0,s.default)(this,t),this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.pixelRatio=void 0,this.allowRedraw=!0,this.dragging=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideNodesOnDrag:!1},h.extend(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("dragStart",function(){t.dragging=!0}),this.body.emitter.on("dragEnd",function(){t.dragging=!1}),this.body.emitter.on("_resizeNodes",function(){t._resizeNodes()}),this.body.emitter.on("_redraw",function(){t.renderingActive===!1&&t._redraw()}),this.body.emitter.on("_blockRedraw",function(){t.allowRedraw=!1}),this.body.emitter.on("_allowRedraw",function(){t.allowRedraw=!0,t.redrawRequested=!1}),this.body.emitter.on("_requestRedraw",this._requestRedraw.bind(this)),this.body.emitter.on("_startRendering",function(){t.renderRequests+=1,t.renderingActive=!0,t._startRendering()}),this.body.emitter.on("_stopRendering",function(){t.renderRequests-=1,t.renderingActive=t.renderRequests>0,t.renderTimer=void 0}),this.body.emitter.on("destroy",function(){t.renderRequests=0,t.allowRedraw=!1,t.renderingActive=!1,t.requiresTimeout===!0?clearTimeout(t.renderTimer):cancelAnimationFrame(t.renderTimer),t.body.emitter.off()})}},{key:"setOptions",value:function(t){if(void 0!==t){var e=["hideEdgesOnDrag","hideNodesOnDrag"];h.selectiveDeepExtend(e,this.options,t)}}},{key:"_startRendering",value:function(){this.renderingActive===!0&&void 0===this.renderTimer&&(this.requiresTimeout===!0?this.renderTimer=window.setTimeout(this._renderStep.bind(this),this.simulationInterval):this.renderTimer=window.requestAnimationFrame(this._renderStep.bind(this)))}},{key:"_renderStep",value:function(){this.renderingActive===!0&&(this.renderTimer=void 0,this.requiresTimeout===!0&&this._startRendering(),this._redraw(),this.requiresTimeout===!1&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;this.redrawRequested!==!0&&this.renderingActive===!1&&this.allowRedraw===!0&&(this.redrawRequested=!0,this.requiresTimeout===!0?window.setTimeout(function(){t._redraw(!1)},0):window.requestAnimationFrame(function(){t._redraw(!1)}))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];
-if(this.allowRedraw===!0){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e=this.canvas.frame.canvas.getContext("2d");0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.pixelRatio=(window.devicePixelRatio||1)/(e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1),e.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var i=this.canvas.frame.canvas.clientWidth,o=this.canvas.frame.canvas.clientHeight;if(e.clearRect(0,0,i,o),0===this.canvas.frame.clientWidth)return;e.save(),e.translate(this.body.view.translation.x,this.body.view.translation.y),e.scale(this.body.view.scale,this.body.view.scale),e.beginPath(),this.body.emitter.emit("beforeDrawing",e),e.closePath(),t===!1&&(this.dragging===!1||this.dragging===!0&&this.options.hideEdgesOnDrag===!1)&&this._drawEdges(e),(this.dragging===!1||this.dragging===!0&&this.options.hideNodesOnDrag===!1)&&this._drawNodes(e,t),e.beginPath(),this.body.emitter.emit("afterDrawing",e),e.closePath(),e.restore(),t===!0&&e.clearRect(0,0,i,o)}}},{key:"_resizeNodes",value:function(){var t=this.canvas.frame.canvas.getContext("2d");void 0===this.pixelRatio&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0),t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e=this.body.nodes,i=void 0;for(var o in e)e.hasOwnProperty(o)&&(i=e[o],i.resize(t),i.updateBoundingBox(t,i.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.nodes,o=this.body.nodeIndices,n=void 0,s=[],r=20,a=this.canvas.DOMtoCanvas({x:-r,y:-r}),h=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+r,y:this.canvas.frame.canvas.clientHeight+r}),d={top:a.y,left:a.x,bottom:h.y,right:h.x},l=0;l<o.length;l++)n=i[o[l]],n.isSelected()?s.push(o[l]):e===!0?n.draw(t):n.isBoundingBoxOverlappingWith(d)===!0?n.draw(t):n.updateBoundingBox(t,n.selected);for(var u=0;u<s.length;u++)n=i[s[u]],n.draw(t)}},{key:"_drawEdges",value:function(t){for(var e=this.body.edges,i=this.body.edgeIndices,o=void 0,n=0;n<i.length;n++)o=e[i[n]],o.connected===!0&&o.draw(t)}},{key:"_determineBrowserMethod",value:function(){if("undefined"!=typeof window){var t=navigator.userAgent.toLowerCase();this.requiresTimeout=!1,t.indexOf("msie 9.0")!=-1?this.requiresTimeout=!0:t.indexOf("safari")!=-1&&t.indexOf("chrome")<=-1&&(this.requiresTimeout=!0)}else this.requiresTimeout=!0}}]),t}();e.default=d},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(108),d=i(121),l=i(1),u=function(){function t(e){(0,s.default)(this,t),this.body=e,this.pixelRatio=1,this.resizeTimer=void 0,this.resizeFunction=this._onResize.bind(this),this.cameraState={},this.initialized=!1,this.canvasViewCenter={},this.options={},this.defaultOptions={autoResize:!0,height:"100%",width:"100%"},l.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.once("resize",function(e){0!==e.width&&(t.body.view.translation.x=.5*e.width),0!==e.height&&(t.body.view.translation.y=.5*e.height)}),this.body.emitter.on("setSize",this.setSize.bind(this)),this.body.emitter.on("destroy",function(){t.hammerFrame.destroy(),t.hammer.destroy(),t._cleanUp()})}},{key:"setOptions",value:function(t){var e=this;if(void 0!==t){var i=["width","height","autoResize"];l.selectiveDeepExtend(i,this.options,t)}this.options.autoResize===!0&&(this._cleanUp(),this.resizeTimer=setInterval(function(){var t=e.setSize();t===!0&&e.body.emitter.emit("_requestRedraw")},1e3),this.resizeFunction=this._onResize.bind(this),l.addEventListener(window,"resize",this.resizeFunction))}},{key:"_cleanUp",value:function(){void 0!==this.resizeTimer&&clearInterval(this.resizeTimer),l.removeEventListener(window,"resize",this.resizeFunction),this.resizeFunction=void 0}},{key:"_onResize",value:function(){this.setSize(),this.body.emitter.emit("_redraw")}},{key:"_getCameraState",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;this.initialized===!0&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var o=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),n={x:o.x-this.cameraState.position.x,y:o.y-this.cameraState.position.y};this.body.view.translation.x+=n.x*this.body.view.scale,this.body.view.translation.y+=n.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(t.indexOf("%")!==-1||t.indexOf("px")!==-1)return t;if(t.indexOf("%")===-1)return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=900,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext){var t=this.frame.canvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1),this.frame.canvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var e=document.createElement("DIV");e.style.color="red",e.style.fontWeight="bold",e.style.padding="10px",e.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(e)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new h(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:h.DIRECTION_ALL}),d.onTouch(this.hammer,function(e){t.body.eventListeners.onTouch(e)}),this.hammer.on("tap",function(e){t.body.eventListeners.onTap(e)}),this.hammer.on("doubletap",function(e){t.body.eventListeners.onDoubleTap(e)}),this.hammer.on("press",function(e){t.body.eventListeners.onHold(e)}),this.hammer.on("panstart",function(e){t.body.eventListeners.onDragStart(e)}),this.hammer.on("panmove",function(e){t.body.eventListeners.onDrag(e)}),this.hammer.on("panend",function(e){t.body.eventListeners.onDragEnd(e)}),this.hammer.on("pinch",function(e){t.body.eventListeners.onPinch(e)}),this.frame.canvas.addEventListener("mousewheel",function(e){t.body.eventListeners.onMouseWheel(e)}),this.frame.canvas.addEventListener("DOMMouseScroll",function(e){t.body.eventListeners.onMouseWheel(e)}),this.frame.canvas.addEventListener("mousemove",function(e){t.body.eventListeners.onMouseMove(e)}),this.frame.canvas.addEventListener("contextmenu",function(e){t.body.eventListeners.onContext(e)}),this.hammerFrame=new h(this.frame),d.onRelease(this.hammerFrame,function(e){t.body.eventListeners.onRelease(e)})}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,o=this.frame.canvas.width,n=this.frame.canvas.height,s=this.frame.canvas.getContext("2d"),r=this.pixelRatio;return this.pixelRatio=(window.devicePixelRatio||1)/(s.webkitBackingStorePixelRatio||s.mozBackingStorePixelRatio||s.msBackingStorePixelRatio||s.oBackingStorePixelRatio||s.backingStorePixelRatio||1),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e?(this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0):(this.frame.canvas.width==Math.round(this.frame.canvas.clientWidth*this.pixelRatio)&&this.frame.canvas.height==Math.round(this.frame.canvas.clientHeight*this.pixelRatio)||this._getCameraState(r),this.frame.canvas.width!=Math.round(this.frame.canvas.clientWidth*this.pixelRatio)&&(this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),i=!0),this.frame.canvas.height!=Math.round(this.frame.canvas.clientHeight*this.pixelRatio)&&(this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),i=!0)),i===!0&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(o/this.pixelRatio),oldHeight:Math.round(n/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(210),d=o(h),l=i(1),u=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",this.fit.bind(this)),this.body.emitter.on("animationFinished",function(){o.body.emitter.emit("_stopRendering")}),this.body.emitter.on("unlockNode",this.releaseNode.bind(this))}return(0,a.default)(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{nodes:[]},e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=void 0,o=void 0;if(void 0!==t.nodes&&0!==t.nodes.length||(t.nodes=this.body.nodeIndices),e===!0){var n=0;for(var s in this.body.nodes)if(this.body.nodes.hasOwnProperty(s)){var r=this.body.nodes[s];r.predefinedPosition===!0&&(n+=1)}if(n>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=d.default.getRange(this.body.nodes,t.nodes);var a=this.body.nodeIndices.length;o=12.662/(a+7.4147)+.0964822;var h=Math.min(this.canvas.frame.canvas.clientWidth/600,this.canvas.frame.canvas.clientHeight/600);o*=h}else{this.body.emitter.emit("_resizeNodes"),i=d.default.getRange(this.body.nodes,t.nodes);var l=1.1*Math.abs(i.maxX-i.minX),u=1.1*Math.abs(i.maxY-i.minY),c=this.canvas.frame.canvas.clientWidth/l,p=this.canvas.frame.canvas.clientHeight/u;o=c<=p?c:p}o>1?o=1:0===o&&(o=1);var f=d.default.findCenter(i),m={position:f,scale:o,animation:t.animation};this.moveTo(m)}},{key:"focus",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.log("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){return void 0===t?void(t={}):(void 0===t.offset&&(t.offset={x:0,y:0}),void 0===t.offset.x&&(t.offset.x=0),void 0===t.offset.y&&(t.offset.y=0),void 0===t.scale&&(t.scale=this.body.view.scale),void 0===t.position&&(t.position=this.getViewPosition()),void 0===t.animation&&(t.animation={duration:0}),t.animation===!1&&(t.animation={duration:0}),t.animation===!0&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),void this.animateView(t))}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),t.locked===!0&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),i={x:e.x-t.position.x,y:e.y-t.position.y};this.targetTranslation={x:this.sourceTranslation.x+i.x*this.targetScale+t.offset.x,y:this.sourceTranslation.y+i.y*this.targetScale+t.offset.y},0===t.animation.duration?void 0!=this.lockedOnNodeId?(this.viewFunction=this._lockedRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction)):(this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw")):(this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=this._transitionRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))}}},{key:"_lockedRedraw",value:function(){var t={x:this.body.nodes[this.lockedOnNodeId].x,y:this.body.nodes[this.lockedOnNodeId].y},e=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),i={x:e.x-t.x,y:e.y-t.y},o=this.body.view.translation,n={x:o.x+i.x*this.body.view.scale+this.lockedOnNodeOffset.x,y:o.y+i.y*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=n}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=t===!0?1:this.easingTime;var e=l.easingFunctions[this.animationEasingFunction](this.easingTime);this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1&&(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,void 0!=this.lockedOnNodeId&&(this.viewFunction=this._lockedRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction)),this.body.emitter.emit("animationFinished"))}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(216),d=o(h),l=i(128),u=o(l),c=i(1),p=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.canvas=i,this.selectionHandler=o,this.navigationHandler=new d.default(e,i),this.body.eventListeners.onTap=this.onTap.bind(this),this.body.eventListeners.onTouch=this.onTouch.bind(this),this.body.eventListeners.onDoubleTap=this.onDoubleTap.bind(this),this.body.eventListeners.onHold=this.onHold.bind(this),this.body.eventListeners.onDragStart=this.onDragStart.bind(this),this.body.eventListeners.onDrag=this.onDrag.bind(this),this.body.eventListeners.onDragEnd=this.onDragEnd.bind(this),this.body.eventListeners.onMouseWheel=this.onMouseWheel.bind(this),this.body.eventListeners.onPinch=this.onPinch.bind(this),this.body.eventListeners.onMouseMove=this.onMouseMove.bind(this),this.body.eventListeners.onRelease=this.onRelease.bind(this),this.body.eventListeners.onContext=this.onContext.bind(this),this.touchTime=0,this.drag={},this.pinch={},this.popup=void 0,this.popupObj=void 0,this.popupTimer=void 0,this.body.functions.getPointer=this.getPointer.bind(this),this.options={},this.defaultOptions={dragNodes:!0,dragView:!0,hover:!1,keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02},bindToWindow:!0},navigationButtons:!1,tooltipDelay:300,zoomView:!0},c.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("destroy",function(){clearTimeout(t.popupTimer),delete t.body.functions.getPointer})}},{key:"setOptions",value:function(t){if(void 0!==t){var e=["hideEdgesOnDrag","hideNodesOnDrag","keyboard","multiselect","selectable","selectConnectedEdges"];c.selectiveNotDeepExtend(e,this.options,t),c.mergeOptions(this.options,t,"keyboard"),t.tooltip&&(c.extend(this.options.tooltip,t.tooltip),t.tooltip.color&&(this.options.tooltip.color=c.parseColor(t.tooltip.color)))}this.navigationHandler.setOptions(this.options)}},{key:"getPointer",value:function(t){return{x:t.x-c.getAbsoluteLeft(this.canvas.frame.canvas),y:t.y-c.getAbsoluteTop(this.canvas.frame.canvas)}}},{key:"onTouch",value:function(t){(new Date).valueOf()-this.touchTime>50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,t,i),this.selectionHandler._generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler._generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,t,i),this.selectionHandler._generateClickEvent("click",t,e),this.selectionHandler._generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler._generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler._generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=this.selectionHandler._getSelectedEdgeCount(),n=this.selectionHandler._getSelectedNodeCount(),s=this.selectionHandler.getSelection(),r=void 0;r=i===!0?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t);var a=this.selectionHandler._getSelectedEdgeCount(),h=this.selectionHandler._getSelectedNodeCount(),d=this.selectionHandler.getSelection(),l=this._determineIfDifferent(s,d),u=l.nodesChanged,c=l.edgesChanged,p=!1;h-n>0?(this.selectionHandler._generateClickEvent("selectNode",e,t),r=!0,p=!0):u===!0&&h>0?(this.selectionHandler._generateClickEvent("deselectNode",e,t,s),this.selectionHandler._generateClickEvent("selectNode",e,t),p=!0,r=!0):h-n<0&&(this.selectionHandler._generateClickEvent("deselectNode",e,t,s),r=!0),a-o>0&&p===!1?(this.selectionHandler._generateClickEvent("selectEdge",e,t),r=!0):a>0&&c===!0?(this.selectionHandler._generateClickEvent("deselectEdge",e,t,s),this.selectionHandler._generateClickEvent("selectEdge",e,t),r=!0):a-o<0&&(this.selectionHandler._generateClickEvent("deselectEdge",e,t,s),r=!0),r===!0&&this.selectionHandler._generateClickEvent("select",e,t)}},{key:"_determineIfDifferent",value:function(t,e){for(var i=!1,o=!1,n=0;n<t.nodes.length;n++)e.nodes.indexOf(t.nodes[n])===-1&&(i=!0);for(var s=0;s<e.nodes.length;s++)t.nodes.indexOf(t.nodes[s])===-1&&(i=!0);for(var r=0;r<t.edges.length;r++)e.edges.indexOf(t.edges[r])===-1&&(o=!0);for(var a=0;a<e.edges.length;a++)t.edges.indexOf(t.edges[a])===-1&&(o=!0);return{nodesChanged:i,edgesChanged:o}}},{key:"onDragStart",value:function(t){void 0===this.drag.pointer&&this.onTouch(t);var e=this.selectionHandler.getNodeAt(this.drag.pointer);if(this.drag.dragging=!0,this.drag.selection=[],this.drag.translation=c.extend({},this.body.view.translation),this.drag.nodeId=void 0,void 0!==e&&this.options.dragNodes===!0){this.drag.nodeId=e.id,e.isSelected()===!1&&(this.selectionHandler.unselectAll(),this.selectionHandler.selectObject(e)),this.selectionHandler._generateClickEvent("dragStart",t,this.drag.pointer);var i=this.selectionHandler.selectionObj.nodes;for(var o in i)if(i.hasOwnProperty(o)){var n=i[o],s={id:n.id,node:n,x:n.x,y:n.y,xFixed:n.options.fixed.x,yFixed:n.options.fixed.y};n.options.fixed.x=!0,n.options.fixed.y=!0,this.drag.selection.push(s)}}else this.selectionHandler._generateClickEvent("dragStart",t,this.drag.pointer,void 0,!0)}},{key:"onDrag",value:function(t){var e=this;if(this.drag.pinched!==!0){this.body.emitter.emit("unlockNode");var i=this.getPointer(t.center),o=this.drag.selection;if(o&&o.length&&this.options.dragNodes===!0)!function(){e.selectionHandler._generateClickEvent("dragging",t,i);var n=i.x-e.drag.pointer.x,s=i.y-e.drag.pointer.y;o.forEach(function(t){var i=t.node;t.xFixed===!1&&(i.x=e.canvas._XconvertDOMtoCanvas(e.canvas._XconvertCanvasToDOM(t.x)+n)),t.yFixed===!1&&(i.y=e.canvas._YconvertDOMtoCanvas(e.canvas._YconvertCanvasToDOM(t.y)+s))}),e.body.emitter.emit("startSimulation")}();else if(this.options.dragView===!0){if(this.selectionHandler._generateClickEvent("dragging",t,i,void 0,!0),void 0===this.drag.pointer)return void this.onDragStart(t);var n=i.x-this.drag.pointer.x,s=i.y-this.drag.pointer.y;this.body.view.translation={x:this.drag.translation.x+n,y:this.drag.translation.y+s},this.body.emitter.emit("_redraw")}}}},{key:"onDragEnd",value:function(t){this.drag.dragging=!1;var e=this.drag.selection;e&&e.length?(e.forEach(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed}),this.selectionHandler._generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler._generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(this.options.zoomView===!0){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var o=void 0;void 0!==this.drag&&this.drag.dragging===!0&&(o=this.canvas.DOMtoCanvas(this.drag.pointer));var n=this.body.view.translation,s=t/i,r=(1-s)*e.x+n.x*s,a=(1-s)*e.y+n.y*s;if(this.body.view.scale=t,this.body.view.translation={x:r,y:a},void 0!=o){var h=this.canvas.canvasToDOM(o);this.drag.pointer.x=h.x,this.drag.pointer.y=h.y}this.body.emitter.emit("_requestRedraw"),i<t?this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:e}):this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:e})}}},{key:"onMouseWheel",value:function(t){if(this.options.zoomView===!0){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),0!==e){var i=this.body.view.scale,o=e/10;e<0&&(o/=1-o),i*=1+o;var n=this.getPointer({x:t.clientX,y:t.clientY});this.zoom(i,n)}t.preventDefault()}}},{key:"onMouseMove",value:function(t){var e=this,i=this.getPointer({x:t.clientX,y:t.clientY}),o=!1;if(void 0!==this.popup&&(this.popup.hidden===!1&&this._checkHidePopup(i),this.popup.hidden===!1&&(o=!0,this.popup.setPosition(i.x+3,i.y-5),this.popup.show())),this.options.keyboard.bindToWindow===!1&&this.options.keyboard.enabled===!0&&this.canvas.frame.focus(),o===!1&&(void 0!==this.popupTimer&&(clearInterval(this.popupTimer),this.popupTimer=void 0),this.drag.dragging||(this.popupTimer=setTimeout(function(){return e._checkShowPopup(i)},this.options.tooltipDelay))),this.options.hover===!0){var n=this.selectionHandler.getNodeAt(i);void 0===n&&(n=this.selectionHandler.getEdgeAt(i)),this.selectionHandler.hoverObject(n)}}},{key:"_checkShowPopup",value:function(t){var e=this.canvas._XconvertDOMtoCanvas(t.x),i=this.canvas._YconvertDOMtoCanvas(t.y),o={left:e,top:i,right:e,bottom:i},n=void 0===this.popupObj?void 0:this.popupObj.id,s=!1,r="node";if(void 0===this.popupObj){for(var a=this.body.nodeIndices,h=this.body.nodes,d=void 0,l=[],c=0;c<a.length;c++)d=h[a[c]],d.isOverlappingWith(o)===!0&&void 0!==d.getTitle()&&l.push(a[c]);l.length>0&&(this.popupObj=h[l[l.length-1]],s=!0)}if(void 0===this.popupObj&&s===!1){for(var p=this.body.edgeIndices,f=this.body.edges,m=void 0,v=[],g=0;g<p.length;g++)m=f[p[g]],m.isOverlappingWith(o)===!0&&m.connected===!0&&void 0!==m.getTitle()&&v.push(p[g]);v.length>0&&(this.popupObj=f[v[v.length-1]],r="edge")}void 0!==this.popupObj?this.popupObj.id!==n&&(void 0===this.popup&&(this.popup=new u.default(this.canvas.frame)),this.popup.popupTargetType=r,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e),i===!0)){var o=this.selectionHandler.getNodeAt(t);i=void 0!==o&&o.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));i===!1&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();e.default=p},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=(i(1),i(108)),d=i(121),l=i(111),u=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.iconsCreated=!1,this.navigationHammers=[],this.boundFunctions={},this.touchTime=0,this.activated=!1,this.body.emitter.on("activate",function(){o.activated=!0,o.configureKeyboardBindings()}),this.body.emitter.on("deactivate",function(){o.activated=!1,o.configureKeyboardBindings()}),this.body.emitter.on("destroy",function(){void 0!==o.keycharm&&o.keycharm.destroy()}),this.options={}}return(0,a.default)(t,[{key:"setOptions",value:function(t){void 0!==t&&(this.options=t,this.create())}},{key:"create",value:function(){this.options.navigationButtons===!0?this.iconsCreated===!1&&this.loadNavigationElements():this.iconsCreated===!0&&this.cleanNavigation(),this.configureKeyboardBindings()}},{key:"cleanNavigation",value:function(){if(0!=this.navigationHammers.length){for(var t=0;t<this.navigationHammers.length;t++)this.navigationHammers[t].destroy();this.navigationHammers=[]}this.navigationDOM&&this.navigationDOM.wrapper&&this.navigationDOM.wrapper.parentNode&&this.navigationDOM.wrapper.parentNode.removeChild(this.navigationDOM.wrapper),this.iconsCreated=!1}},{key:"loadNavigationElements",value:function(){var t=this;this.cleanNavigation(),this.navigationDOM={};var e=["up","down","left","right","zoomIn","zoomOut","zoomExtends"],i=["_moveUp","_moveDown","_moveLeft","_moveRight","_zoomIn","_zoomOut","_fit"];this.navigationDOM.wrapper=document.createElement("div"),this.navigationDOM.wrapper.className="vis-navigation",this.canvas.frame.appendChild(this.navigationDOM.wrapper);for(var o=0;o<e.length;o++){this.navigationDOM[e[o]]=document.createElement("div"),this.navigationDOM[e[o]].className="vis-button vis-"+e[o],this.navigationDOM.wrapper.appendChild(this.navigationDOM[e[o]]);var n=new h(this.navigationDOM[e[o]]);"_fit"===i[o]?d.onTouch(n,this._fit.bind(this)):d.onTouch(n,this.bindToRedraw.bind(this,i[o])),this.navigationHammers.push(n)}var s=new h(this.canvas.frame);d.onRelease(s,function(){t._stopMovement()}),this.navigationHammers.push(s),this.iconsCreated=!0}},{key:"bindToRedraw",value:function(t){void 0===this.boundFunctions[t]&&(this.boundFunctions[t]=this[t].bind(this),this.body.emitter.on("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_startRendering"))}},{key:"unbindFromRedraw",value:function(t){void 0!==this.boundFunctions[t]&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"),delete this.boundFunctions[t])}},{key:"_fit",value:function(){(new Date).valueOf()-this.touchTime>700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)this.boundFunctions.hasOwnProperty(t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,s=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:s},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:pointer})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,s=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:s},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:pointer})}},{key:"configureKeyboardBindings",value:function(){
-var t=this;void 0!==this.keycharm&&this.keycharm.destroy(),this.options.keyboard.enabled===!0&&(this.options.keyboard.bindToWindow===!0?this.keycharm=l({container:window,preventDefault:!0}):this.keycharm=l({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),this.activated===!0&&(this.keycharm.bind("up",function(){t.bindToRedraw("_moveUp")},"keydown"),this.keycharm.bind("down",function(){t.bindToRedraw("_moveDown")},"keydown"),this.keycharm.bind("left",function(){t.bindToRedraw("_moveLeft")},"keydown"),this.keycharm.bind("right",function(){t.bindToRedraw("_moveRight")},"keydown"),this.keycharm.bind("=",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("num+",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("num-",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("-",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("[",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("]",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("pageup",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("pagedown",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("up",function(){t.unbindFromRedraw("_moveUp")},"keyup"),this.keycharm.bind("down",function(){t.unbindFromRedraw("_moveDown")},"keyup"),this.keycharm.bind("left",function(){t.unbindFromRedraw("_moveLeft")},"keyup"),this.keycharm.bind("right",function(){t.unbindFromRedraw("_moveRight")},"keyup"),this.keycharm.bind("=",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("num+",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("num-",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("-",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("[",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("]",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("pageup",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("pagedown",function(){t.unbindFromRedraw("_zoomOut")},"keyup")))}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=i(159),d=o(h),l=i(192),u=o(l),c=i(1),p=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.selectionObj={nodes:[],edges:[]},this.hoverObj={nodes:{},edges:{}},this.options={},this.defaultOptions={multiselect:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0},c.extend(this.options,this.defaultOptions),this.body.emitter.on("_dataChanged",function(){o.updateSelection()})}return(0,a.default)(t,[{key:"setOptions",value:function(t){if(void 0!==t){var e=["multiselect","hoverConnectedEdges","selectable","selectConnectedEdges"];c.selectiveDeepExtend(e,this.options,t)}}},{key:"selectOnPoint",value:function(t){var e=!1;if(this.options.selectable===!0){var i=this.getNodeAt(t)||this.getEdgeAt(t);this.unselectAll(),void 0!==i&&(e=this.selectObject(i)),this.body.emitter.emit("_requestRedraw")}return e}},{key:"selectAdditionalOnPoint",value:function(t){var e=!1;if(this.options.selectable===!0){var i=this.getNodeAt(t)||this.getEdgeAt(t);void 0!==i&&(e=!0,i.isSelected()===!0?this.deselectObject(i):this.selectObject(i),this.body.emitter.emit("_requestRedraw"))}return e}},{key:"_generateClickEvent",value:function(t,e,i,o){var n=arguments.length>4&&void 0!==arguments[4]&&arguments[4],s=void 0;s=n===!0?{nodes:[],edges:[]}:this.getSelection(),s.pointer={DOM:{x:i.x,y:i.y},canvas:this.canvas.DOMtoCanvas(i)},s.event=e,void 0!==o&&(s.previousSelection=o),this.body.emitter.emit(t,s)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;return void 0!==t&&(t instanceof d.default&&e===!0&&this._selectConnectedEdges(t),t.select(),this._addToSelection(t),!0)}},{key:"deselectObject",value:function(t){t.isSelected()===!0&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,o=0;o<this.body.nodeIndices.length;o++){var n=this.body.nodeIndices[o];i[n].isOverlappingWith(t)&&e.push(n)}return e}},{key:"_pointerToPositionObject",value:function(t){var e=this.canvas.DOMtoCanvas(t);return{left:e.x-1,top:e.y+1,right:e.x+1,bottom:e.y-1}}},{key:"getNodeAt",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),o=this._getAllNodesOverlappingWith(i);return o.length>0?e===!0?this.body.nodes[o[o.length-1]]:o[o.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,o=0;o<this.body.edgeIndices.length;o++){var n=this.body.edgeIndices[o];i[n].isOverlappingWith(t)&&e.push(n)}}},{key:"_getAllEdgesOverlappingWith",value:function(t){var e=[];return this._getEdgesOverlappingWith(t,e),e}},{key:"getEdgeAt",value:function(t){for(var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),o=10,n=null,s=this.body.edges,r=0;r<this.body.edgeIndices.length;r++){var a=this.body.edgeIndices[r],h=s[a];if(h.connected){var d=h.from.x,l=h.from.y,u=h.to.x,c=h.to.y,p=h.edgeType.getDistanceToEdge(d,l,u,c,i.x,i.y);p<o&&(n=a,o=p)}}return n?e===!0?this.body.edges[n]:n:void 0}},{key:"_addToSelection",value:function(t){t instanceof d.default?this.selectionObj.nodes[t.id]=t:this.selectionObj.edges[t.id]=t}},{key:"_addToHover",value:function(t){t instanceof d.default?this.hoverObj.nodes[t.id]=t:this.hoverObj.edges[t.id]=t}},{key:"_removeFromSelection",value:function(t){t instanceof d.default?(delete this.selectionObj.nodes[t.id],this._unselectConnectedEdges(t)):delete this.selectionObj.edges[t.id]}},{key:"unselectAll",value:function(){for(var t in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(t)&&this.selectionObj.nodes[t].unselect();for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&this.selectionObj.edges[e].unselect();this.selectionObj={nodes:{},edges:{}}}},{key:"_getSelectedNodeCount",value:function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);return t}},{key:"_getSelectedNode",value:function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return this.selectionObj.nodes[t]}},{key:"_getSelectedEdge",value:function(){for(var t in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(t))return this.selectionObj.edges[t]}},{key:"_getSelectedEdgeCount",value:function(){var t=0;for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(t+=1);return t}},{key:"_getSelectedObjectCount",value:function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);for(var i in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(i)&&(t+=1);return t}},{key:"_selectionIsEmpty",value:function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return!1;for(var e in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(e))return!1;return!0}},{key:"_clusterInSelection",value:function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t)&&this.selectionObj.nodes[t].clusterSize>1)return!0;return!1}},{key:"_selectConnectedEdges",value:function(t){for(var e=0;e<t.edges.length;e++){var i=t.edges[e];i.select(),this._addToSelection(i)}}},{key:"_hoverConnectedEdges",value:function(t){for(var e=0;e<t.edges.length;e++){var i=t.edges[e];i.hover=!0,this._addToHover(i)}}},{key:"_unselectConnectedEdges",value:function(t){for(var e=0;e<t.edges.length;e++){var i=t.edges[e];i.unselect(),this._removeFromSelection(i)}}},{key:"blurObject",value:function(t){t.hover===!0&&(t.hover=!1,t instanceof d.default?this.body.emitter.emit("blurNode",{node:t.id}):this.body.emitter.emit("blurEdge",{edge:t.id}))}},{key:"hoverObject",value:function(t){var e=!1;for(var i in this.hoverObj.nodes)this.hoverObj.nodes.hasOwnProperty(i)&&(void 0===t||t instanceof d.default&&t.id!=i||t instanceof u.default)&&(this.blurObject(this.hoverObj.nodes[i]),delete this.hoverObj.nodes[i],e=!0);for(var o in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(o)&&(e===!0?(this.hoverObj.edges[o].hover=!1,delete this.hoverObj.edges[o]):(void 0===t||t instanceof u.default&&t.id!=o||t instanceof d.default&&!t.hover)&&(this.blurObject(this.hoverObj.edges[o]),delete this.hoverObj.edges[o],e=!0));void 0!==t&&(t.hover===!1&&(t.hover=!0,this._addToHover(t),e=!0,t instanceof d.default?this.body.emitter.emit("hoverNode",{node:t.id}):this.body.emitter.emit("hoverEdge",{edge:t.id})),t instanceof d.default&&this.options.hoverConnectedEdges===!0&&this._hoverConnectedEdges(t)),e===!0&&this.body.emitter.emit("_requestRedraw")}},{key:"getSelection",value:function(){var t=this.getSelectedNodes(),e=this.getSelectedEdges();return{nodes:t,edges:e}}},{key:"getSelectedNodes",value:function(){var t=[];if(this.options.selectable===!0)for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&t.push(this.selectionObj.nodes[e].id);return t}},{key:"getSelectedEdges",value:function(){var t=[];if(this.options.selectable===!0)for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&t.push(this.selectionObj.edges[e].id);return t}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=void 0,o=void 0;if(!t||!t.nodes&&!t.edges)throw"Selection must be an object with nodes and/or edges properties";if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes)for(i=0;i<t.nodes.length;i++){o=t.nodes[i];var n=this.body.nodes[o];if(!n)throw new RangeError('Node with id "'+o+'" not found');this.selectObject(n,e.highlightEdges)}if(t.edges)for(i=0;i<t.edges.length;i++){o=t.edges[i];var s=this.body.edges[o];if(!s)throw new RangeError('Edge with id "'+o+'" not found');this.selectObject(s)}this.body.emitter.emit("_requestRedraw")}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(t)&&(this.body.nodes.hasOwnProperty(t)||delete this.selectionObj.nodes[t]);for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(this.body.edges.hasOwnProperty(e)||delete this.selectionObj.edges[e])}}]),t}();e.default=p},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(58),s=o(n),r=i(161),a=o(r),h=i(62),d=o(h),l=i(115),u=o(l),c=i(116),p=o(c),f=i(210),m=o(f),v=i(1),g=function(){function t(e){(0,u.default)(this,t),this.body=e,this.initialRandomSeed=Math.round(1e6*Math.random()),this.randomSeed=this.initialRandomSeed,this.setPhysics=!1,this.options={},this.optionsBackup={physics:{}},this.defaultOptions={randomSeed:void 0,improvedLayout:!0,hierarchical:{enabled:!1,levelSeparation:150,nodeSpacing:100,treeSpacing:200,blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:"UD",sortMethod:"hubsize"}},v.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,p.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("_dataChanged",function(){t.setupHierarchicalLayout()}),this.body.emitter.on("_dataLoaded",function(){t.layoutNetwork()}),this.body.emitter.on("_resetHierarchicalLayout",function(){t.setupHierarchicalLayout()})}},{key:"setOptions",value:function(t,e){if(void 0!==t){var i=this.options.hierarchical.enabled;if(v.selectiveDeepExtend(["randomSeed","improvedLayout"],this.options,t),v.mergeOptions(this.options,t,"hierarchical"),void 0!==t.randomSeed&&(this.initialRandomSeed=t.randomSeed),this.options.hierarchical.enabled===!0)return i===!0&&this.body.emitter.emit("refresh",!0),"RL"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?this.options.hierarchical.levelSeparation>0&&(this.options.hierarchical.levelSeparation*=-1):this.options.hierarchical.levelSeparation<0&&(this.options.hierarchical.levelSeparation*=-1),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(i===!0)return this.body.emitter.emit("refresh"),v.deepExtend(e,this.optionsBackup)}return e}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(this.options.hierarchical.enabled===!0){void 0===t.physics||t.physics===!0?(t.physics={enabled:void 0===this.optionsBackup.physics.enabled||this.optionsBackup.physics.enabled,solver:"hierarchicalRepulsion"},this.optionsBackup.physics.enabled=void 0===this.optionsBackup.physics.enabled||this.optionsBackup.physics.enabled,this.optionsBackup.physics.solver=this.optionsBackup.physics.solver||"barnesHut"):"object"===(0,d.default)(t.physics)?(this.optionsBackup.physics.enabled=void 0===t.physics.enabled||t.physics.enabled,this.optionsBackup.physics.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):t.physics!==!1&&(this.optionsBackup.physics.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var e="horizontal";"RL"!==this.options.hierarchical.direction&&"LR"!==this.options.hierarchical.direction||(e="vertical"),void 0===t.edges?(this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1}):void 0===t.edges.smooth?(this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1):"boolean"==typeof t.edges.smooth?(this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:e}):(void 0!==t.edges.smooth.type&&"dynamic"!==t.edges.smooth.type&&(e=t.edges.smooth.type),this.optionsBackup.edges={smooth:void 0===t.edges.smooth.enabled||t.edges.smooth.enabled,type:void 0===t.edges.smooth.type?"dynamic":t.edges.smooth.type,roundness:void 0===t.edges.smooth.roundness?.5:t.edges.smooth.roundness,forceDirection:void 0!==t.edges.smooth.forceDirection&&t.edges.smooth.forceDirection},t.edges.smooth={enabled:void 0===t.edges.smooth.enabled||t.edges.smooth.enabled,type:e,roundness:void 0===t.edges.smooth.roundness?.5:t.edges.smooth.roundness,forceDirection:void 0!==t.edges.smooth.forceDirection&&t.edges.smooth.forceDirection}),this.body.emitter.emit("_forceDisableDynamicCurves",e)}return t}},{key:"seededRandom",value:function(){var t=1e4*Math.sin(this.randomSeed++);return t-Math.floor(t)}},{key:"positionInitially",value:function(t){if(this.options.hierarchical.enabled!==!0){this.randomSeed=this.initialRandomSeed;for(var e=0;e<t.length;e++){var i=t[e],o=1*t.length+10,n=2*Math.PI*this.seededRandom();void 0===i.x&&(i.x=o*Math.cos(n)),void 0===i.y&&(i.y=o*Math.sin(n))}}}},{key:"layoutNetwork",value:function(){if(this.options.hierarchical.enabled!==!0&&this.options.improvedLayout===!0){for(var t=0,e=0;e<this.body.nodeIndices.length;e++){var i=this.body.nodes[this.body.nodeIndices[e]];i.predefinedPosition===!0&&(t+=1)}if(t<.5*this.body.nodeIndices.length){var o=10,n=0,s=100;if(this.body.nodeIndices.length>s){for(var r=this.body.nodeIndices.length;this.body.nodeIndices.length>s;){n+=1;var a=this.body.nodeIndices.length;n%3===0?this.body.modules.clustering.clusterBridges():this.body.modules.clustering.clusterOutliers();var h=this.body.nodeIndices.length;if(a==h&&n%3!==0||n>o)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*r)})}this.body.modules.kamadaKawai.solve(this.body.nodeIndices,this.body.edgeIndices,!0),this._shiftToCenter();for(var d=70,l=0;l<this.body.nodeIndices.length;l++)this.body.nodes[this.body.nodeIndices[l]].predefinedPosition===!1&&(this.body.nodes[this.body.nodeIndices[l]].x+=(.5-this.seededRandom())*d,this.body.nodes[this.body.nodeIndices[l]].y+=(.5-this.seededRandom())*d);this._declusterAll(),this.body.emitter.emit("_repositionBezierNodes")}}}},{key:"_shiftToCenter",value:function(){for(var t=m.default.getRangeCore(this.body.nodes,this.body.nodeIndices),e=m.default.findCenter(t),i=0;i<this.body.nodeIndices.length;i++)this.body.nodes[this.body.nodeIndices[i]].x-=e.x,this.body.nodes[this.body.nodeIndices[i]].y-=e.y}},{key:"_declusterAll",value:function(){for(var t=!0;t===!0;){t=!1;for(var e=0;e<this.body.nodeIndices.length;e++)this.body.nodes[this.body.nodeIndices[e]].isCluster===!0&&(t=!0,this.body.modules.clustering.openCluster(this.body.nodeIndices[e],{},!1));t===!0&&this.body.emitter.emit("_dataChanged")}}},{key:"getSeed",value:function(){return this.initialRandomSeed}},{key:"setupHierarchicalLayout",value:function(){if(this.options.hierarchical.enabled===!0&&this.body.nodeIndices.length>0){var t=void 0,e=void 0,i=!1,o=!0,n=!1;this.hierarchicalLevels={},this.lastNodeOnLevel={},this.hierarchicalChildrenReference={},this.hierarchicalParentReference={},this.hierarchicalTrees={},this.treeIndex=-1,this.distributionOrdering={},this.distributionIndex={},this.distributionOrderingPresence={};for(e in this.body.nodes)this.body.nodes.hasOwnProperty(e)&&(t=this.body.nodes[e],void 0===t.options.x&&void 0===t.options.y&&(o=!1),void 0!==t.options.level?(i=!0,this.hierarchicalLevels[e]=t.options.level):n=!0);if(n===!0&&i===!0)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");n===!0&&("hubsize"===this.options.hierarchical.sortMethod?this._determineLevelsByHubsize():"directed"===this.options.hierarchical.sortMethod?this._determineLevelsDirected():"custom"===this.options.hierarchical.sortMethod&&this._determineLevelsCustomCallback());for(var s in this.body.nodes)this.body.nodes.hasOwnProperty(s)&&void 0===this.hierarchicalLevels[s]&&(this.hierarchicalLevels[s]=0);var r=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(r),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},o=function(){for(var e=h(),i=0;i<e.length-1;i++){var o=e[i].max-e[i+1].min;n(i+1,o+t.options.hierarchical.treeSpacing)}},n=function(e,i){for(var o in t.hierarchicalTrees)if(t.hierarchicalTrees.hasOwnProperty(o)&&t.hierarchicalTrees[o]===e){var n=t.body.nodes[o],s=t._getPositionForHierarchy(n);t._setPositionForHierarchy(n,s+i,void 0,!0)}},r=function(e){var i=1e9,o=-1e9;for(var n in t.hierarchicalTrees)if(t.hierarchicalTrees.hasOwnProperty(n)&&t.hierarchicalTrees[n]===e){var s=t._getPositionForHierarchy(t.body.nodes[n]);i=Math.min(s,i),o=Math.max(s,o)}return{min:i,max:o}},h=function(){for(var e=[],i=0;i<=t.treeIndex;i++)e.push(r(i));return e},d=function e(i,o){if(o[i.id]=!0,t.hierarchicalChildrenReference[i.id]){var n=t.hierarchicalChildrenReference[i.id];if(n.length>0)for(var s=0;s<n.length;s++)e(t.body.nodes[n[s]],o)}},l=function(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e9,o=1e9,n=1e9,s=1e9,r=-1e9;for(var h in e)if(e.hasOwnProperty(h)){var d=t.body.nodes[h],l=t.hierarchicalLevels[d.id],u=t._getPositionForHierarchy(d),c=t._getSpaceAroundNode(d,e),p=(0,a.default)(c,2),f=p[0],m=p[1];o=Math.min(f,o),n=Math.min(m,n),l<=i&&(s=Math.min(u,s),r=Math.max(u,r))}return[s,r,o,n]},u=function e(i){var o=t.hierarchicalLevels[i];if(t.hierarchicalChildrenReference[i]){var n=t.hierarchicalChildrenReference[i];if(n.length>0)for(var s=0;s<n.length;s++)o=Math.max(o,e(n[s]))}return o},c=function(t,e){var i=u(t.id),o=u(e.id);return Math.min(i,o)},p=function(e,i){var o=t.hierarchicalParentReference[e.id],n=t.hierarchicalParentReference[i.id];if(void 0===o||void 0===n)return!1;for(var s=0;s<o.length;s++)for(var r=0;r<n.length;r++)if(o[s]==n[r])return!0;return!1},f=function(e,i,o){for(var n=0;n<i.length;n++){var s=i[n],r=t.distributionOrdering[s];if(r.length>1)for(var a=0;a<r.length-1;a++)p(r[a],r[a+1])===!0&&t.hierarchicalTrees[r[a].id]===t.hierarchicalTrees[r[a+1].id]&&e(r[a],r[a+1],o)}},m=function(i,o){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],s=t._getPositionForHierarchy(i),r=t._getPositionForHierarchy(o),h=Math.abs(r-s);if(h>t.options.hierarchical.nodeSpacing){var u={};u[i.id]=!0;var p={};p[o.id]=!0,d(i,u),d(o,p);var f=c(i,o),m=l(u,f),v=(0,a.default)(m,4),g=(v[0],v[1]),y=(v[2],v[3],l(p,f)),b=(0,a.default)(y,4),_=b[0],w=(b[1],b[2]),x=(b[3],Math.abs(g-_));if(x>t.options.hierarchical.nodeSpacing){var k=g-_+t.options.hierarchical.nodeSpacing;k<-w+t.options.hierarchical.nodeSpacing&&(k=-w+t.options.hierarchical.nodeSpacing),k<0&&(t._shiftBlock(o.id,k),e=!0,n===!0&&t._centerParent(o))}}},v=function(o,n){for(var s=n.id,r=n.edges,h=t.hierarchicalLevels[n.id],u=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,c={},p=[],f=0;f<r.length;f++){var m=r[f];if(m.toId!=m.fromId){var v=m.toId==s?m.from:m.to;c[r[f].id]=v,t.hierarchicalLevels[v.id]<h&&p.push(m)}}var g=function(e,i){for(var o=0,n=0;n<i.length;n++)if(void 0!==c[i[n].id]){var s=t._getPositionForHierarchy(c[i[n].id])-e;o+=s/Math.sqrt(s*s+u)}return o},y=function(e,i){for(var o=0,n=0;n<i.length;n++)if(void 0!==c[i[n].id]){var s=t._getPositionForHierarchy(c[i[n].id])-e;o-=u*Math.pow(s*s+u,-1.5)}return o},b=function(e,i){for(var o=t._getPositionForHierarchy(n),s={},r=0;r<e;r++){var a=g(o,i),h=y(o,i),d=40,l=Math.max(-d,Math.min(d,Math.round(a/h)));if(o-=l,void 0!==s[o])break;s[o]=r}return o},_=function(o){var s=t._getPositionForHierarchy(n);if(void 0===i[n.id]){var r={};r[n.id]=!0,d(n,r),i[n.id]=r}var h=l(i[n.id]),u=(0,a.default)(h,4),c=(u[0],u[1],u[2]),p=u[3],f=o-s,m=0;f>0?m=Math.min(f,p-t.options.hierarchical.nodeSpacing):f<0&&(m=-Math.min(-f,c-t.options.hierarchical.nodeSpacing)),0!=m&&(t._shiftBlock(n.id,m),e=!0)},w=function(i){var o=t._getPositionForHierarchy(n),s=t._getSpaceAroundNode(n),r=(0,a.default)(s,2),h=r[0],d=r[1],l=i-o,u=o;l>0?u=Math.min(o+(d-t.options.hierarchical.nodeSpacing),i):l<0&&(u=Math.max(o-(h-t.options.hierarchical.nodeSpacing),i)),u!==o&&(t._setPositionForHierarchy(n,u,void 0,!0),e=!0)},x=b(o,p);_(x),x=b(o,r),w(x)},g=function(i){var o=(0,s.default)(t.distributionOrdering);o=o.reverse();for(var n=0;n<i;n++){e=!1;for(var r=0;r<o.length;r++)for(var a=o[r],h=t.distributionOrdering[a],d=0;d<h.length;d++)v(1e3,h[d]);if(e!==!0)break}},y=function(i){var o=(0,s.default)(t.distributionOrdering);o=o.reverse();for(var n=0;n<i&&(e=!1,f(m,o,!0),e===!0);n++);},b=function(){for(var e in t.body.nodes)t.body.nodes.hasOwnProperty(e)&&t._centerParent(t.body.nodes[e])},_=function(){var e=(0,s.default)(t.distributionOrdering);e=e.reverse();for(var i=0;i<e.length;i++)for(var o=e[i],n=t.distributionOrdering[o],r=0;r<n.length;r++)t._centerParent(n[r])};this.options.hierarchical.blockShifting===!0&&(y(5),b()),this.options.hierarchical.edgeMinimization===!0&&g(20),this.options.hierarchical.parentCentralization===!0&&_(),o()}},{key:"_getSpaceAroundNode",value:function(t,e){var i=!0;void 0===e&&(i=!1);var o=this.hierarchicalLevels[t.id];if(void 0!==o){var n=this.distributionIndex[t.id],s=this._getPositionForHierarchy(t),r=1e9,a=1e9;if(0!==n){var h=this.distributionOrdering[o][n-1];if(i===!0&&void 0===e[h.id]||i===!1){var d=this._getPositionForHierarchy(h);r=s-d}}if(n!=this.distributionOrdering[o].length-1){var l=this.distributionOrdering[o][n+1];if(i===!0&&void 0===e[l.id]||i===!1){var u=this._getPositionForHierarchy(l);a=Math.min(a,u-s)}}return[r,a]}return[0,0]}},{key:"_centerParent",value:function(t){if(this.hierarchicalParentReference[t.id])for(var e=this.hierarchicalParentReference[t.id],i=0;i<e.length;i++){var o=e[i],n=this.body.nodes[o];if(this.hierarchicalChildrenReference[o]){var s=1e9,r=-1e9,h=this.hierarchicalChildrenReference[o];if(h.length>0)for(var d=0;d<h.length;d++){var l=this.body.nodes[h[d]];s=Math.min(s,this._getPositionForHierarchy(l)),r=Math.max(r,this._getPositionForHierarchy(l))}var u=this._getPositionForHierarchy(n),c=this._getSpaceAroundNode(n),p=(0,a.default)(c,2),f=p[0],m=p[1],v=.5*(s+r),g=u-v;(g<0&&Math.abs(g)<m-this.options.hierarchical.nodeSpacing||g>0&&Math.abs(g)<f-this.options.hierarchical.nodeSpacing)&&this._setPositionForHierarchy(n,v,void 0,!0)}}}},{key:"_placeNodesByHierarchy",value:function(t){this.positionedNodes={};for(var e in t)if(t.hasOwnProperty(e)){var i=(0,s.default)(t[e]);i=this._indexArrayToNodes(i),this._sortNodeArray(i);for(var o=0,n=0;n<i.length;n++){var r=i[n];if(void 0===this.positionedNodes[r.id]){var a=this.options.hierarchical.nodeSpacing*o;o>0&&(a=this._getPositionForHierarchy(i[n-1])+this.options.hierarchical.nodeSpacing),this._setPositionForHierarchy(r,a,e),this._validataPositionAndContinue(r,e,a),o++}}}}},{key:"_placeBranchNodes",value:function(t,e){if(void 0!==this.hierarchicalChildrenReference[t]){for(var i=[],o=0;o<this.hierarchicalChildrenReference[t].length;o++)i.push(this.body.nodes[this.hierarchicalChildrenReference[t][o]]);this._sortNodeArray(i);for(var n=0;n<i.length;n++){var s=i[n],r=this.hierarchicalLevels[s.id];if(!(r>e&&void 0===this.positionedNodes[s.id]))return;var a=void 0;a=0===n?this._getPositionForHierarchy(this.body.nodes[t]):this._getPositionForHierarchy(i[n-1])+this.options.hierarchical.nodeSpacing,this._setPositionForHierarchy(s,a,r),this._validataPositionAndContinue(s,r,a)}for(var h=1e9,d=-1e9,l=0;l<i.length;l++){var u=i[l].id;h=Math.min(h,this._getPositionForHierarchy(this.body.nodes[u])),d=Math.max(d,this._getPositionForHierarchy(this.body.nodes[u]))}this._setPositionForHierarchy(this.body.nodes[t],.5*(h+d),e)}}},{key:"_validataPositionAndContinue",value:function(t,e,i){if(void 0!==this.lastNodeOnLevel[e]){var o=this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-o<this.options.hierarchical.nodeSpacing){var n=o+this.options.hierarchical.nodeSpacing-i,s=this._findCommonParent(this.lastNodeOnLevel[e],t.id);this._shiftBlock(s.withChild,n)}}this.lastNodeOnLevel[e]=t.id,this.positionedNodes[t.id]=!0,this._placeBranchNodes(t.id,e)}},{key:"_indexArrayToNodes",value:function(t){for(var e=[],i=0;i<t.length;i++)e.push(this.body.nodes[t[i]]);return e}},{key:"_getDistribution",value:function(){var t={},e=void 0,i=void 0;for(e in this.body.nodes)if(this.body.nodes.hasOwnProperty(e)){i=this.body.nodes[e];var o=void 0===this.hierarchicalLevels[e]?0:this.hierarchicalLevels[e];"UD"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?(i.y=this.options.hierarchical.levelSeparation*o,i.options.fixed.y=!0):(i.x=this.options.hierarchical.levelSeparation*o,i.options.fixed.x=!0),void 0===t[o]&&(t[o]={}),t[o][e]=i}return t}},{key:"_getHubSize",value:function(){var t=0;for(var e in this.body.nodes)if(this.body.nodes.hasOwnProperty(e)){var i=this.body.nodes[e];void 0===this.hierarchicalLevels[e]&&(t=i.edges.length<t?t:i.edges.length)}return t}},{key:"_determineLevelsByHubsize",value:function(){for(var t=this,e=1,i=function(e,i){void 0===t.hierarchicalLevels[i.id]&&(void 0===t.hierarchicalLevels[e.id]&&(t.hierarchicalLevels[e.id]=0),t.hierarchicalLevels[i.id]=t.hierarchicalLevels[e.id]+1)};e>0&&(e=this._getHubSize(),0!==e);)for(var o in this.body.nodes)if(this.body.nodes.hasOwnProperty(o)){var n=this.body.nodes[o];n.edges.length===e&&this._crawlNetwork(i,o)}}},{key:"_determineLevelsCustomCallback",value:function(){var t=this,e=1e5,i=function(t,e,i){},o=function(o,n,s){var r=t.hierarchicalLevels[o.id];void 0===r&&(t.hierarchicalLevels[o.id]=e);var a=i(m.default.cloneOptions(o,"node"),m.default.cloneOptions(n,"node"),m.default.cloneOptions(s,"edge"));t.hierarchicalLevels[n.id]=t.hierarchicalLevels[o.id]+a};this._crawlNetwork(o),this._setMinLevelToZero()}},{key:"_determineLevelsDirected",value:function(){var t=this,e=1e4,i=function(i,o,n){var s=t.hierarchicalLevels[i.id];void 0===s&&(t.hierarchicalLevels[i.id]=e),n.toId==o.id?t.hierarchicalLevels[o.id]=t.hierarchicalLevels[i.id]+1:t.hierarchicalLevels[o.id]=t.hierarchicalLevels[i.id]-1};this._crawlNetwork(i),this._setMinLevelToZero()}},{key:"_setMinLevelToZero",value:function(){var t=1e9;for(var e in this.body.nodes)this.body.nodes.hasOwnProperty(e)&&void 0!==this.hierarchicalLevels[e]&&(t=Math.min(this.hierarchicalLevels[e],t));for(var i in this.body.nodes)this.body.nodes.hasOwnProperty(i)&&void 0!==this.hierarchicalLevels[i]&&(this.hierarchicalLevels[i]-=t)}},{key:"_generateMap",value:function(){var t=this,e=function(e,i){if(t.hierarchicalLevels[i.id]>t.hierarchicalLevels[e.id]){var o=e.id,n=i.id;void 0===t.hierarchicalChildrenReference[o]&&(t.hierarchicalChildrenReference[o]=[]),t.hierarchicalChildrenReference[o].push(n),void 0===t.hierarchicalParentReference[n]&&(t.hierarchicalParentReference[n]=[]),t.hierarchicalParentReference[n].push(o)}};this._crawlNetwork(e)}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments[1],o={},n=0,s=function i(n,s){if(void 0===o[n.id]){void 0===t.hierarchicalTrees[n.id]&&(t.hierarchicalTrees[n.id]=s,t.treeIndex=Math.max(s,t.treeIndex)),o[n.id]=!0;for(var r=void 0,a=0;a<n.edges.length;a++)n.edges[a].connected===!0&&(r=n.edges[a].toId===n.id?n.edges[a].from:n.edges[a].to,n.id!==r.id&&(e(n,r,n.edges[a]),i(r,s)))}};if(void 0===i)for(var r=0;r<this.body.nodeIndices.length;r++){var a=this.body.nodes[this.body.nodeIndices[r]];void 0===o[a.id]&&(s(a,n),n+=1)}else{var h=this.body.nodes[i];if(void 0===h)return void console.error("Node not found:",i);s(h)}}},{key:"_shiftBlock",value:function(t,e){if("UD"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?this.body.nodes[t].x+=e:this.body.nodes[t].y+=e,void 0!==this.hierarchicalChildrenReference[t])for(var i=0;i<this.hierarchicalChildrenReference[t].length;i++)this._shiftBlock(this.hierarchicalChildrenReference[t][i],e)}},{key:"_findCommonParent",value:function(t,e){var i=this,o={},n=function t(e,o){if(void 0!==i.hierarchicalParentReference[o])for(var n=0;n<i.hierarchicalParentReference[o].length;n++){var s=i.hierarchicalParentReference[o][n];e[s]=!0,t(e,s)}},s=function t(e,o){if(void 0!==i.hierarchicalParentReference[o])for(var n=0;n<i.hierarchicalParentReference[o].length;n++){var s=i.hierarchicalParentReference[o][n];if(void 0!==e[s])return{foundParent:s,withChild:o};var r=t(e,s);if(null!==r.foundParent)return r}return{foundParent:null,withChild:o}};return n(o,t),s(o,e)}},{key:"_setPositionForHierarchy",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];o!==!0&&(void 0===this.distributionOrdering[i]&&(this.distributionOrdering[i]=[],this.distributionOrderingPresence[i]={}),void 0===this.distributionOrderingPresence[i][t.id]&&(this.distributionOrdering[i].push(t),this.distributionIndex[t.id]=this.distributionOrdering[i].length-1),this.distributionOrderingPresence[i][t.id]=!0),"UD"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?t.x=e:t.y=e}},{key:"_getPositionForHierarchy",value:function(t){return"UD"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?t.x:t.y}},{key:"_sortNodeArray",value:function(t){t.length>1&&("UD"===this.options.hierarchical.direction||"DU"===this.options.hierarchical.direction?t.sort(function(t,e){return t.x-e.x}):t.sort(function(t,e){return t.y-e.y}))}}]),t}();e.default=g},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(58),s=o(n),r=i(82),a=o(r),h=i(62),d=o(h),l=i(115),u=o(l),c=i(116),p=o(c),f=i(1),m=i(108),v=i(121),g=function(){function t(e,i,o){var n=this;(0,u.default)(this,t),this.body=e,this.canvas=i,this.selectionHandler=o,this.editMode=!1,this.manipulationDiv=void 0,
-this.editModeDiv=void 0,this.closeDiv=void 0,this.manipulationHammers=[],this.temporaryUIFunctions={},this.temporaryEventFunctions=[],this.touchTime=0,this.temporaryIds={nodes:[],edges:[]},this.guiEnabled=!1,this.inMode=!1,this.selectedControlNode=void 0,this.options={},this.defaultOptions={enabled:!1,initiallyActive:!1,addNode:!0,addEdge:!0,editNode:void 0,editEdge:!0,deleteNode:!0,deleteEdge:!0,controlNodeStyle:{shape:"dot",size:6,color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968",border:"#3c3c3c"}},borderWidth:2,borderWidthSelected:2}},f.extend(this.options,this.defaultOptions),this.body.emitter.on("destroy",function(){n._clean()}),this.body.emitter.on("_dataChanged",this._restore.bind(this)),this.body.emitter.on("_resetData",this._restore.bind(this))}return(0,p.default)(t,[{key:"_restore",value:function(){this.inMode!==!1&&(this.options.initiallyActive===!0?this.enableEditMode():this.disableEditMode())}},{key:"setOptions",value:function(t,e,i){void 0!==e&&(void 0!==e.locale?this.options.locale=e.locale:this.options.locale=i.locale,void 0!==e.locales?this.options.locales=e.locales:this.options.locales=i.locales),void 0!==t&&("boolean"==typeof t?this.options.enabled=t:(this.options.enabled=!0,f.deepExtend(this.options,t)),this.options.initiallyActive===!0&&(this.editMode=!0),this._setup())}},{key:"toggleEditMode",value:function(){this.editMode===!0?this.disableEditMode():this.enableEditMode()}},{key:"enableEditMode",value:function(){this.editMode=!0,this._clean(),this.guiEnabled===!0&&(this.manipulationDiv.style.display="block",this.closeDiv.style.display="block",this.editModeDiv.style.display="none",this.showManipulatorToolbar())}},{key:"disableEditMode",value:function(){this.editMode=!1,this._clean(),this.guiEnabled===!0&&(this.manipulationDiv.style.display="none",this.closeDiv.style.display="none",this.editModeDiv.style.display="block",this._createEditButton())}},{key:"showManipulatorToolbar",value:function(){if(this._clean(),this.manipulationDOM={},this.guiEnabled===!0){this.editMode=!0,this.manipulationDiv.style.display="block",this.closeDiv.style.display="block";var t=this.selectionHandler._getSelectedNodeCount(),e=this.selectionHandler._getSelectedEdgeCount(),i=t+e,o=this.options.locales[this.options.locale],n=!1;this.options.addNode!==!1&&(this._createAddNodeButton(o),n=!0),this.options.addEdge!==!1&&(n===!0?this._createSeperator(1):n=!0,this._createAddEdgeButton(o)),1===t&&"function"==typeof this.options.editNode?(n===!0?this._createSeperator(2):n=!0,this._createEditNodeButton(o)):1===e&&0===t&&this.options.editEdge!==!1&&(n===!0?this._createSeperator(3):n=!0,this._createEditEdgeButton(o)),0!==i&&(t>0&&this.options.deleteNode!==!1?(n===!0&&this._createSeperator(4),this._createDeleteButton(o)):0===t&&this.options.deleteEdge!==!1&&(n===!0&&this._createSeperator(4),this._createDeleteButton(o))),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this)),this._temporaryBindEvent("select",this.showManipulatorToolbar.bind(this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){if(this.editMode!==!0&&this.enableEditMode(),this._clean(),this.inMode="addNode",this.guiEnabled===!0){var t=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(t),this._createSeperator(),this._createDescription(t.addDescription||this.options.locales.en.addDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}this._temporaryBindEvent("click",this._performAddNode.bind(this))}},{key:"editNode",value:function(){var t=this;this.editMode!==!0&&this.enableEditMode(),this._clean();var e=this.selectionHandler._getSelectedNode();if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(e.isCluster!==!0){var i=f.deepExtend({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,function(e){null!==e&&void 0!==e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()})}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){if(this.editMode!==!0&&this.enableEditMode(),this._clean(),this.inMode="addEdge",this.guiEnabled===!0){var t=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(t),this._createSeperator(),this._createDescription(t.edgeDescription||this.options.locales.en.edgeDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}this._temporaryBindUI("onTouch",this._handleConnect.bind(this)),this._temporaryBindUI("onDragEnd",this._finishConnect.bind(this)),this._temporaryBindUI("onDrag",this._dragControlNode.bind(this)),this._temporaryBindUI("onRelease",this._finishConnect.bind(this)),this._temporaryBindUI("onDragStart",function(){}),this._temporaryBindUI("onHold",function(){})}},{key:"editEdgeMode",value:function(){var t=this;if(this.editMode!==!0&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"===(0,d.default)(this.options.editEdge)&&"function"==typeof this.options.editEdge.editWithoutDrag&&(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdges()[0],void 0!==this.edgeBeingEditedId)){var e=this.body.edges[this.edgeBeingEditedId];return void this._performEditEdge(e.from,e.to)}if(this.guiEnabled===!0){var i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}this.edgeBeingEditedId=this.selectionHandler.getSelectedEdges()[0],void 0!==this.edgeBeingEditedId?!function(){var e=t.body.edges[t.edgeBeingEditedId],i=t._getNewTargetNode(e.from.x,e.from.y),o=t._getNewTargetNode(e.to.x,e.to.y);t.temporaryIds.nodes.push(i.id),t.temporaryIds.nodes.push(o.id),t.body.nodes[i.id]=i,t.body.nodeIndices.push(i.id),t.body.nodes[o.id]=o,t.body.nodeIndices.push(o.id),t._temporaryBindUI("onTouch",t._controlNodeTouch.bind(t)),t._temporaryBindUI("onTap",function(){}),t._temporaryBindUI("onHold",function(){}),t._temporaryBindUI("onDragStart",t._controlNodeDragStart.bind(t)),t._temporaryBindUI("onDrag",t._controlNodeDrag.bind(t)),t._temporaryBindUI("onDragEnd",t._controlNodeDragEnd.bind(t)),t._temporaryBindUI("onMouseMove",function(){}),t._temporaryBindEvent("beforeDrawing",function(t){var n=e.edgeType.findBorderPositions(t);i.selected===!1&&(i.x=n.from.x,i.y=n.from.y),o.selected===!1&&(o.x=n.to.x,o.y=n.to.y)}),t.body.emitter.emit("_redraw")}():this.showManipulatorToolbar()}},{key:"deleteSelected",value:function(){var t=this;this.editMode!==!0&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodes(),i=this.selectionHandler.getSelectedEdges(),o=void 0;if(e.length>0){for(var n=0;n<e.length;n++)if(this.body.nodes[e[n]].isCluster===!0)return void alert(this.options.locales[this.options.locale].deleteClusterError||this.options.locales.en.deleteClusterError);"function"==typeof this.options.deleteNode&&(o=this.options.deleteNode)}else i.length>0&&"function"==typeof this.options.deleteEdge&&(o=this.options.deleteEdge);if("function"==typeof o){var s={nodes:e,edges:i};if(2!==o.length)throw new Error("The function for delete does not support two arguments (data, callback)");o(s,function(e){null!==e&&void 0!==e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){this.options.enabled===!0?(this.guiEnabled=!0,this._createWrappers(),this.editMode===!1?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",this.editMode===!0?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",this.editMode===!0?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv&&(this.closeDiv=document.createElement("div"),this.closeDiv.className="vis-close",this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=f.deepExtend({},this.options.controlNodeStyle);i.id="targetNode"+f.randomUUID(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var o=this.body.functions.createNode(i);return o.shape.boundingBox={left:t,right:t,top:e,bottom:e},o}},{key:"_createEditButton",value:function(){this._clean(),this.manipulationDOM={},f.recursiveDOMDelete(this.editModeDiv);var t=this.options.locales[this.options.locale],e=this._createButton("editMode","vis-button vis-edit vis-edit-mode",t.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(e),this._bindHammerToDiv(e,this.toggleEditMode.bind(this))}},{key:"_clean",value:function(){this.inMode=!1,this.guiEnabled===!0&&(f.recursiveDOMDelete(this.editModeDiv),f.recursiveDOMDelete(this.manipulationDiv),this._cleanManipulatorHammers()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanManipulatorHammers",value:function(){if(0!=this.manipulationHammers.length){for(var t=0;t<this.manipulationHammers.length;t++)this.manipulationHammers[t].destroy();this.manipulationHammers=[]}}},{key:"_removeManipulationDOM",value:function(){this._clean(),f.recursiveDOMDelete(this.manipulationDiv),f.recursiveDOMDelete(this.editModeDiv),f.recursiveDOMDelete(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e=this._createButton("addNode","vis-button vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.addNodeMode.bind(this))}},{key:"_createAddEdgeButton",value:function(t){var e=this._createButton("addEdge","vis-button vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.addEdgeMode.bind(this))}},{key:"_createEditNodeButton",value:function(t){var e=this._createButton("editNode","vis-button vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.editNode.bind(this))}},{key:"_createEditEdgeButton",value:function(t){var e=this._createButton("editEdge","vis-button vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.editEdgeMode.bind(this))}},{key:"_createDeleteButton",value:function(t){if(this.options.rtl)var e="vis-button vis-delete-rtl";else var e="vis-button vis-delete";var i=this._createButton("delete",e,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(i),this._bindHammerToDiv(i,this.deleteSelected.bind(this))}},{key:"_createBackButton",value:function(t){var e=this._createButton("back","vis-button vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.showManipulatorToolbar.bind(this))}},{key:"_createButton",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("div"),this.manipulationDOM[t+"Div"].className=e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=o,this.manipulationDOM[t+"Label"].innerHTML=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDiv.appendChild(this._createButton("description","vis-button vis-none",t))}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+(0,a.default)((0,s.default)(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)this.temporaryUIFunctions.hasOwnProperty(t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t<this.temporaryEventFunctions.length;t++){var e=this.temporaryEventFunctions[t].event,i=this.temporaryEventFunctions[t].boundFunction;this.body.emitter.off(e,i)}this.temporaryEventFunctions=[]}},{key:"_bindHammerToDiv",value:function(t,e){var i=new m(t,{});v.onTouch(i,e),this.manipulationHammers.push(i)}},{key:"_cleanupTemporaryNodesAndEdges",value:function(){for(var t=0;t<this.temporaryIds.edges.length;t++){this.body.edges[this.temporaryIds.edges[t]].disconnect(),delete this.body.edges[this.temporaryIds.edges[t]];var e=this.body.edgeIndices.indexOf(this.temporaryIds.edges[t]);e!==-1&&this.body.edgeIndices.splice(e,1)}for(var i=0;i<this.temporaryIds.nodes.length;i++){delete this.body.nodes[this.temporaryIds.nodes[i]];var o=this.body.nodeIndices.indexOf(this.temporaryIds.nodes[i]);o!==-1&&this.body.nodeIndices.splice(o,1)}this.temporaryIds={nodes:[],edges:[]}}},{key:"_controlNodeTouch",value:function(t){this.selectionHandler.unselectAll(),this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=f.extend({},this.body.view.translation)}},{key:"_controlNodeDragStart",value:function(t){var e=this.lastTouch,i=this.selectionHandler._pointerToPositionObject(e),o=this.body.nodes[this.temporaryIds.nodes[0]],n=this.body.nodes[this.temporaryIds.nodes[1]],s=this.body.edges[this.edgeBeingEditedId];this.selectedControlNode=void 0;var r=o.isOverlappingWith(i),a=n.isOverlappingWith(i);r===!0?(this.selectedControlNode=o,s.edgeType.from=o):a===!0&&(this.selectedControlNode=n,s.edgeType.to=n),void 0!==this.selectedControlNode&&this.selectionHandler.selectObject(this.selectedControlNode),this.body.emitter.emit("_redraw")}},{key:"_controlNodeDrag",value:function(t){this.body.emitter.emit("disablePhysics");var e=this.body.functions.getPointer(t.center),i=this.canvas.DOMtoCanvas(e);if(void 0!==this.selectedControlNode)this.selectedControlNode.x=i.x,this.selectedControlNode.y=i.y;else{var o=e.x-this.lastTouch.x,n=e.y-this.lastTouch.y;this.body.view.translation={x:this.lastTouch.translation.x+o,y:this.lastTouch.translation.y+n}}this.body.emitter.emit("_redraw")}},{key:"_controlNodeDragEnd",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=this.body.edges[this.edgeBeingEditedId];if(void 0!==this.selectedControlNode){this.selectionHandler.unselectAll();for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),s=void 0,r=n.length-1;r>=0;r--)if(n[r]!==this.selectedControlNode.id){s=this.body.nodes[n[r]];break}if(void 0!==s&&void 0!==this.selectedControlNode)if(s.isCluster===!0)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(s.id,o.to.id):this._performEditEdge(o.from.id,s.id)}else o.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=f.extend({},this.body.view.translation);var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(i.isCluster===!0)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var o=this._getNewTargetNode(i.x,i.y);this.body.nodes[o.id]=o,this.body.nodeIndices.push(o.id);var n=this.body.functions.createEdge({id:"connectionEdge"+f.randomUUID(),from:i.id,to:o.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[n.id]=n,this.body.edgeIndices.push(n.id),this.temporaryIds.nodes.push(o.id),this.temporaryIds.edges.push(n.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center);if(void 0!==this.temporaryIds.nodes[0]){var i=this.body.nodes[this.temporaryIds.nodes[0]];i.x=this.canvas._XconvertDOMtoCanvas(e.x),i.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else{var o=e.x-this.lastTouch.x,n=e.y-this.lastTouch.y;this.body.view.translation={x:this.lastTouch.translation.x+o,y:this.lastTouch.translation.y+n}}}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),s=void 0,r=n.length-1;r>=0;r--)if(this.temporaryIds.nodes.indexOf(n[r])===-1){s=this.body.nodes[n[r]];break}this._cleanupTemporaryNodesAndEdges(),void 0!==s&&(s.isCluster===!0?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[o]&&void 0!==this.body.nodes[s.id]&&this._performAddEdge(o,s.id)),this.body.emitter.emit("_redraw")}},{key:"_performAddNode",value:function(t){var e=this,i={id:f.randomUUID(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,function(t){null!==t&&void 0!==t&&"addNode"===e.inMode&&(e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar())})}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,o={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(o,function(t){null!==t&&void 0!==t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().add(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,o={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges._data[this.edgeBeingEditedId].label},n=this.options.editEdge;if("object"===("undefined"==typeof n?"undefined":(0,d.default)(n))&&(n=n.editWithoutDrag),"function"==typeof n){if(2!==n.length)throw new Error("The function for edit does not support two arguments (data, callback)");n(o,function(t){null===t||void 0===t||"editEdge"!==i.inMode?(i.body.edges[o.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().update(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}();e.default=g},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var i="string",o="boolean",n="number",s="array",r="object",a="dom",h="any",d={configure:{enabled:{boolean:o},filter:{boolean:o,string:i,array:s,function:"function"},container:{dom:a},showButton:{boolean:o},__type__:{object:r,boolean:o,string:i,array:s,function:"function"}},edges:{arrows:{to:{enabled:{boolean:o},scaleFactor:{number:n},type:{string:["arrow","circle"]},__type__:{object:r,boolean:o}},middle:{enabled:{boolean:o},scaleFactor:{number:n},type:{string:["arrow","circle"]},__type__:{object:r,boolean:o}},from:{enabled:{boolean:o},scaleFactor:{number:n},type:{string:["arrow","circle"]},__type__:{object:r,boolean:o}},__type__:{string:["from","to","middle"],object:r}},arrowStrikethrough:{boolean:o},chosen:{label:{boolean:o,function:"function"},edge:{boolean:o,function:"function"},__type__:{object:r,boolean:o}},color:{color:{string:i},highlight:{string:i},hover:{string:i},inherit:{string:["from","to","both"],boolean:o},opacity:{number:n},__type__:{object:r,string:i}},dashes:{boolean:o,array:s},font:{color:{string:i},size:{number:n},face:{string:i},background:{string:i},strokeWidth:{number:n},strokeColor:{string:i},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:n},multi:{boolean:o,string:i},bold:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},boldital:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},ital:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},mono:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},__type__:{object:r,string:i}},hidden:{boolean:o},hoverWidth:{function:"function",number:n},label:{string:i,undefined:"undefined"},labelHighlightBold:{boolean:o},length:{number:n,undefined:"undefined"},physics:{boolean:o},scaling:{min:{number:n},max:{number:n},label:{enabled:{boolean:o},min:{number:n},max:{number:n},maxVisible:{number:n},drawThreshold:{number:n},__type__:{object:r,boolean:o}},customScalingFunction:{function:"function"},__type__:{object:r}},selectionWidth:{function:"function",number:n},selfReferenceSize:{number:n},shadow:{enabled:{boolean:o},color:{string:i},size:{number:n},x:{number:n},y:{number:n},__type__:{object:r,boolean:o}},smooth:{enabled:{boolean:o},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:n},forceDirection:{string:["horizontal","vertical","none"],boolean:o},__type__:{object:r,boolean:o}},title:{string:i,undefined:"undefined"},width:{number:n},widthConstraint:{maximum:{number:n},__type__:{object:r,boolean:o,number:n}},value:{number:n,undefined:"undefined"},__type__:{object:r}},groups:{useDefaultGroups:{boolean:o},__any__:"get from nodes, will be overwritten below",__type__:{object:r}},interaction:{dragNodes:{boolean:o},dragView:{boolean:o},hideEdgesOnDrag:{boolean:o},hideNodesOnDrag:{boolean:o},hover:{boolean:o},keyboard:{enabled:{boolean:o},speed:{x:{number:n},y:{number:n},zoom:{number:n},__type__:{object:r}},bindToWindow:{boolean:o},__type__:{object:r,boolean:o}},multiselect:{boolean:o},navigationButtons:{boolean:o},selectable:{boolean:o},selectConnectedEdges:{boolean:o},hoverConnectedEdges:{boolean:o},tooltipDelay:{number:n},zoomView:{boolean:o},__type__:{object:r}},layout:{randomSeed:{undefined:"undefined",number:n},improvedLayout:{boolean:o},hierarchical:{enabled:{boolean:o},levelSeparation:{number:n},nodeSpacing:{number:n},treeSpacing:{number:n},blockShifting:{boolean:o},edgeMinimization:{boolean:o},parentCentralization:{boolean:o},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},__type__:{object:r,boolean:o}},__type__:{object:r}},manipulation:{enabled:{boolean:o},initiallyActive:{boolean:o},addNode:{boolean:o,function:"function"},addEdge:{boolean:o,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:r,boolean:o,function:"function"}},deleteNode:{boolean:o,function:"function"},deleteEdge:{boolean:o,function:"function"},controlNodeStyle:"get from nodes, will be overwritten below",__type__:{object:r,boolean:o}},nodes:{borderWidth:{number:n},borderWidthSelected:{number:n,undefined:"undefined"},brokenImage:{string:i,undefined:"undefined"},chosen:{label:{boolean:o,function:"function"},node:{boolean:o,function:"function"},__type__:{object:r,boolean:o}},color:{border:{string:i},background:{string:i},highlight:{border:{string:i},background:{string:i},__type__:{object:r,string:i}},hover:{border:{string:i},background:{string:i},__type__:{object:r,string:i}},__type__:{object:r,string:i}},fixed:{x:{boolean:o},y:{boolean:o},__type__:{object:r,boolean:o}},font:{align:{string:i},color:{string:i},size:{number:n},face:{string:i},background:{string:i},strokeWidth:{number:n},strokeColor:{string:i},vadjust:{number:n},multi:{boolean:o,string:i},bold:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},boldital:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},ital:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},mono:{color:{string:i},size:{number:n},face:{string:i},mod:{string:i},vadjust:{number:n},__type__:{object:r,string:i}},__type__:{object:r,string:i}},group:{string:i,number:n,undefined:"undefined"},heightConstraint:{minimum:{number:n},valign:{string:i},__type__:{object:r,boolean:o,number:n}},hidden:{boolean:o},icon:{face:{string:i},code:{string:i},size:{number:n},color:{string:i},__type__:{object:r}},id:{string:i,number:n},image:{string:i,undefined:"undefined"},label:{string:i,undefined:"undefined"},labelHighlightBold:{boolean:o},level:{number:n,undefined:"undefined"},margin:{top:{number:n},right:{number:n},bottom:{number:n},left:{number:n},__type__:{object:r,number:n}},mass:{number:n},physics:{boolean:o},scaling:{min:{number:n},max:{number:n},label:{enabled:{boolean:o},min:{number:n},max:{number:n},maxVisible:{number:n},drawThreshold:{number:n},__type__:{object:r,boolean:o}},customScalingFunction:{function:"function"},__type__:{object:r}},shadow:{enabled:{boolean:o},color:{string:i},size:{number:n},x:{number:n},y:{number:n},__type__:{object:r,boolean:o}},shape:{string:["ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon"]},shapeProperties:{borderDashes:{boolean:o,array:s},borderRadius:{number:n},interpolation:{boolean:o},useImageSize:{boolean:o},useBorderWithImage:{boolean:o},__type__:{object:r}},size:{number:n},title:{string:i,undefined:"undefined"},value:{number:n,undefined:"undefined"},widthConstraint:{minimum:{number:n},maximum:{number:n},__type__:{object:r,boolean:o,number:n}},x:{number:n},y:{number:n},__type__:{object:r}},physics:{enabled:{boolean:o},barnesHut:{gravitationalConstant:{number:n},centralGravity:{number:n},springLength:{number:n},springConstant:{number:n},damping:{number:n},avoidOverlap:{number:n},__type__:{object:r}},forceAtlas2Based:{gravitationalConstant:{number:n},centralGravity:{number:n},springLength:{number:n},springConstant:{number:n},damping:{number:n},avoidOverlap:{number:n},__type__:{object:r}},repulsion:{centralGravity:{number:n},springLength:{number:n},springConstant:{number:n},nodeDistance:{number:n},damping:{number:n},__type__:{object:r}},hierarchicalRepulsion:{centralGravity:{number:n},springLength:{number:n},springConstant:{number:n},nodeDistance:{number:n},damping:{number:n},__type__:{object:r}},maxVelocity:{number:n},minVelocity:{number:n},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:o},iterations:{number:n},updateInterval:{number:n},onlyDynamicEdges:{boolean:o},fit:{boolean:o},__type__:{object:r,boolean:o}},timestep:{number:n},adaptiveTimestep:{boolean:o},__type__:{object:r,boolean:o}},autoResize:{boolean:o},clickToUse:{boolean:o},locale:{string:i},locales:{__any__:{any:h},__type__:{object:r}},height:{string:i},width:{string:i},__type__:{object:r}};d.groups.__any__=d.nodes,d.manipulation.controlNodeStyle=d.nodes;var l={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],
-springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01]}};e.allOptions=d,e.configureOptions=l},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(161),s=o(n),r=i(115),a=o(r),h=i(116),d=o(h),l=i(222),u=o(l),c=function(){function t(e,i,o){(0,a.default)(this,t),this.body=e,this.springLength=i,this.springConstant=o,this.distanceSolver=new u.default}return(0,d.default)(t,[{key:"setOptions",value:function(t){t&&(t.springLength&&(this.springLength=t.springLength),t.springConstant&&(this.springConstant=t.springConstant))}},{key:"solve",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(o),this._createK_matrix(o);for(var n=.01,r=1,a=0,h=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),d=5,l=1e9,u=0,c=0,p=0,f=0,m=0;l>n&&a<h;){a+=1;var v=this._getHighestEnergyNode(i),g=(0,s.default)(v,4);for(u=g[0],l=g[1],c=g[2],p=g[3],f=l,m=0;f>r&&m<d;){m+=1,this._moveNode(u,c,p);var y=this._getEnergy(u),b=(0,s.default)(y,3);f=b[0],c=b[1],p=b[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,o=0,n=e[0],r=0,a=0,h=0;h<e.length;h++){var d=e[h];if(i[d].predefinedPosition===!1||i[d].isCluster===!0&&t===!0||i[d].options.fixed.x===!0||i[d].options.fixed.y===!0){var l=this._getEnergy(d),u=(0,s.default)(l,3),c=u[0],p=u[1],f=u[2];o<c&&(o=c,n=d,r=p,a=f)}}return[n,o,r,a]}},{key:"_getEnergy",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,o=i[t].x,n=i[t].y,s=0,r=0,a=0;a<e.length;a++){var h=e[a];if(h!==t){var d=i[h].x,l=i[h].y,u=1/Math.sqrt(Math.pow(o-d,2)+Math.pow(n-l,2));s+=this.K_matrix[t][h]*(o-d-this.L_matrix[t][h]*(o-d)*u),r+=this.K_matrix[t][h]*(n-l-this.L_matrix[t][h]*(n-l)*u)}}var c=Math.sqrt(Math.pow(s,2)+Math.pow(r,2));return[c,s,r]}},{key:"_moveNode",value:function(t,e,i){for(var o=this.body.nodeIndices,n=this.body.nodes,s=0,r=0,a=0,h=n[t].x,d=n[t].y,l=0;l<o.length;l++){var u=o[l];if(u!==t){var c=n[u].x,p=n[u].y,f=1/Math.pow(Math.pow(h-c,2)+Math.pow(d-p,2),1.5);s+=this.K_matrix[t][u]*(1-this.L_matrix[t][u]*Math.pow(d-p,2)*f),r+=this.K_matrix[t][u]*(this.L_matrix[t][u]*(h-c)*(d-p)*f),a+=this.K_matrix[t][u]*(1-this.L_matrix[t][u]*Math.pow(h-c,2)*f)}}var m=s,v=r,g=e,y=a,b=i,_=(g/m+b/v)/(v/m-y/v),w=-(v*_+g)/m;n[t].x+=w,n[t].y+=_}},{key:"_createL_matrix",value:function(t){var e=this.body.nodeIndices,i=this.springLength;this.L_matrix=[];for(var o=0;o<e.length;o++){this.L_matrix[e[o]]={};for(var n=0;n<e.length;n++)this.L_matrix[e[o]][e[n]]=i*t[e[o]][e[n]]}}},{key:"_createK_matrix",value:function(t){var e=this.body.nodeIndices,i=this.springConstant;this.K_matrix=[];for(var o=0;o<e.length;o++){this.K_matrix[e[o]]={};for(var n=0;n<e.length;n++)this.K_matrix[e[o]][e[n]]=i*Math.pow(t[e[o]][e[n]],-2)}}}]),t}();e.default=c},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(115),s=o(n),r=i(116),a=o(r),h=function(){function t(){(0,s.default)(this,t)}return(0,a.default)(t,[{key:"getDistances",value:function(t,e,i){for(var o={},n=t.edges,s=0;s<e.length;s++){o[e[s]]={},o[e[s]]={};for(var r=0;r<e.length;r++)o[e[s]][e[r]]=s==r?0:1e9,o[e[s]][e[r]]=s==r?0:1e9}for(var a=0;a<i.length;a++){var h=n[i[a]];h.connected===!0&&void 0!==o[h.fromId]&&void 0!==o[h.toId]&&(o[h.fromId][h.toId]=1,o[h.toId][h.fromId]=1)}for(var d=e.length,l=0;l<d;l++)for(var u=0;u<d-1;u++)for(var c=u+1;c<d;c++)o[e[u]][e[c]]=Math.min(o[e[u]][e[c]],o[e[u]][e[l]]+o[e[l]][e[c]]),o[e[c]][e[u]]=o[e[u]][e[c]];return o}}]),t}();e.default=h},function(t,e){"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1),this.closePath()},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i),this.closePath()},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath(),i*=1.15,e+=.275*i;var o=2*i,n=o/2,s=Math.sqrt(3)/6*o,r=Math.sqrt(o*o-n*n);this.moveTo(t,e-(r-s)),this.lineTo(t+n,e+s),this.lineTo(t-n,e+s),this.lineTo(t,e-(r-s)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath(),i*=1.15,e-=.275*i;var o=2*i,n=o/2,s=Math.sqrt(3)/6*o,r=Math.sqrt(o*o-n*n);this.moveTo(t,e+(r-s)),this.lineTo(t+n,e-s),this.lineTo(t-n,e-s),this.lineTo(t,e+(r-s)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath(),i*=.82,e+=.1*i;for(var o=0;o<10;o++){var n=o%2===0?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*o*Math.PI/10),e-n*Math.cos(2*o*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.diamond=function(t,e,i){this.beginPath(),this.lineTo(t,e+i),this.lineTo(t+i,e),this.lineTo(t,e-i),this.lineTo(t-i,e),this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,o,n){var s=Math.PI/180;i-2*n<0&&(n=i/2),o-2*n<0&&(n=o/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*s,360*s,!1),this.lineTo(t+i,e+o-n),this.arc(t+i-n,e+o-n,n,0,90*s,!1),this.lineTo(t+n,e+o),this.arc(t+n,e+o-n,n,90*s,180*s,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*s,270*s,!1),this.closePath()},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,o){var n=.5522848,s=i/2*n,r=o/2*n,a=t+i,h=e+o,d=t+i/2,l=e+o/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-s,e,d,e),this.bezierCurveTo(d+s,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+s,h,d,h),this.bezierCurveTo(d-s,h,t,l+r,t,l),this.closePath()},CanvasRenderingContext2D.prototype.database=function(t,e,i,o){var n=1/3,s=i,r=o*n,a=.5522848,h=s/2*a,d=r/2*a,l=t+s,u=e+r,c=t+s/2,p=e+r/2,f=e+(o-r/2),m=e+o;this.beginPath(),this.moveTo(l,p),this.bezierCurveTo(l,p+d,c+h,u,c,u),this.bezierCurveTo(c-h,u,t,p+d,t,p),this.bezierCurveTo(t,p-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,p-d,l,p),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,p)},CanvasRenderingContext2D.prototype.arrowEndpoint=function(t,e,i,o){var n=t-o*Math.cos(i),s=e-o*Math.sin(i),r=t-.9*o*Math.cos(i),a=e-.9*o*Math.sin(i),h=n+o/3*Math.cos(i+.5*Math.PI),d=s+o/3*Math.sin(i+.5*Math.PI),l=n+o/3*Math.cos(i-.5*Math.PI),u=s+o/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,u),this.closePath()},CanvasRenderingContext2D.prototype.circleEndpoint=function(t,e,i,o){var n=.4*o,s=t-n*Math.cos(i),r=e-n*Math.sin(i);this.circle(s,r,n)},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,o,n){this.beginPath(),this.moveTo(t,e);for(var s=n.length,r=i-t,a=o-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,u=!0,c=0,p=n[0];d>=.1;)p=n[l++%s],p>d&&(p=d),c=Math.sqrt(p*p/(1+h*h)),c=r<0?-c:c,t+=c,e+=h*c,u===!0?this.lineTo(t,e):this.moveTo(t,e),d-=p,u=!u})},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t){return R=t,m()}function s(){L=0,A=R.charAt(0)}function r(){L++,A=R.charAt(L)}function a(){return R.charAt(L+1)}function h(t){return H.test(t)}function d(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t,e,i){for(var o=e.split("."),n=t;o.length;){var s=o.shift();o.length?(n[s]||(n[s]={}),n=n[s]):n[s]=i}}function u(t,e){for(var i,o,n=null,s=[t],r=t;r.parent;)s.push(r.parent),r=r.parent;if(r.nodes)for(i=0,o=r.nodes.length;i<o;i++)if(e.id===r.nodes[i].id){n=r.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=d(n.attr,t.node))),i=s.length-1;i>=0;i--){var a=s[i];a.nodes||(a.nodes=[]),a.nodes.indexOf(n)===-1&&a.nodes.push(n)}e.attr&&(n.attr=d(n.attr,e.attr))}function c(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=d({},t.edge);e.attr=d(i,e.attr)}}function p(t,e,i,o,n){var s={from:e,to:i,type:o};return t.edge&&(s.attr=d({},t.edge)),s.attr=d(s.attr||{},n),s}function f(){for(F=N.NULL,B="";" "===A||"\t"===A||"\n"===A||"\r"===A;)r();do{var t=!1;if("#"===A){for(var e=L-1;" "===R.charAt(e)||"\t"===R.charAt(e);)e--;if("\n"===R.charAt(e)||""===R.charAt(e)){for(;""!=A&&"\n"!=A;)r();t=!0}}if("/"===A&&"/"===a()){for(;""!=A&&"\n"!=A;)r();t=!0}if("/"===A&&"*"===a()){for(;""!=A;){if("*"===A&&"/"===a()){r(),r();break}r()}t=!0}for(;" "===A||"\t"===A||"\n"===A||"\r"===A;)r()}while(t);if(""===A)return void(F=N.DELIMITER);var i=A+a();if(z[i])return F=N.DELIMITER,B=i,r(),void r();if(z[A])return F=N.DELIMITER,B=A,void r();if(h(A)||"-"===A){for(B+=A,r();h(A);)B+=A,r();return"false"===B?B=!1:"true"===B?B=!0:isNaN(Number(B))||(B=Number(B)),void(F=N.IDENTIFIER)}if('"'===A){for(r();""!=A&&('"'!=A||'"'===A&&'"'===a());)B+=A,'"'===A&&r(),r();if('"'!=A)throw k('End of string " expected');return r(),void(F=N.IDENTIFIER)}for(F=N.UNKNOWN;""!=A;)B+=A,r();throw new SyntaxError('Syntax error in part "'+O(B,30)+'"')}function m(){var t={};if(s(),f(),"strict"===B&&(t.strict=!0,f()),"graph"!==B&&"digraph"!==B||(t.type=B,f()),F===N.IDENTIFIER&&(t.id=B,f()),"{"!=B)throw k("Angle bracket { expected");if(f(),v(t),"}"!=B)throw k("Angle bracket } expected");if(f(),""!==B)throw k("End of file expected");return f(),delete t.node,delete t.edge,delete t.graph,t}function v(t){for(;""!==B&&"}"!=B;)g(t),";"===B&&f()}function g(t){var e=y(t);if(e)return void w(t,e);var i=b(t);if(!i){if(F!=N.IDENTIFIER)throw k("Identifier expected");var o=B;if(f(),"="===B){if(f(),F!=N.IDENTIFIER)throw k("Identifier expected");t[o]=B,f()}else _(t,o)}}function y(t){var e=null;if("subgraph"===B&&(e={},e.type="subgraph",f(),F===N.IDENTIFIER&&(e.id=B,f())),"{"===B){if(f(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,v(e),"}"!=B)throw k("Angle bracket } expected");f(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function b(t){return"node"===B?(f(),t.node=x(),"node"):"edge"===B?(f(),t.edge=x(),"edge"):"graph"===B?(f(),t.graph=x(),"graph"):null}function _(t,e){var i={id:e},o=x();o&&(i.attr=o),u(t,i),w(t,e)}function w(t,e){for(;"->"===B||"--"===B;){var i,o=B;f();var n=y(t);if(n)i=n;else{if(F!=N.IDENTIFIER)throw k("Identifier or subgraph expected");i=B,u(t,{id:i}),f()}var s=x(),r=p(t,e,i,o,s);c(t,r),e=i}}function x(){for(var t=null;"["===B;){for(f(),t={};""!==B&&"]"!=B;){if(F!=N.IDENTIFIER)throw k("Attribute name expected");var e=B;if(f(),"="!=B)throw k("Equal sign = expected");if(f(),F!=N.IDENTIFIER)throw k("Attribute value expected");var i=B;l(t,e,i),f(),","==B&&f()}if("]"!=B)throw k("Bracket ] expected");f()}return t}function k(t){return new SyntaxError(t+', got "'+O(B,30)+'" (char '+L+")")}function O(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function D(t,e,i){Array.isArray(t)?t.forEach(function(t){Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}):Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}function S(t,e,i){for(var o=e.split("."),n=o.pop(),s=t,r=0;r<o.length;r++){var a=o[r];a in s||(s[a]={}),s=s[a]}return s[n]=i,t}function M(t,e){var i={};for(var o in t)if(t.hasOwnProperty(o)){var n=e[o];Array.isArray(n)?n.forEach(function(e){S(i,e,t[o])}):"string"==typeof n?S(i,n,t[o]):S(i,o,t[o])}return i}function C(t){var e=n(t),i={nodes:[],edges:[],options:{}};if(e.nodes&&e.nodes.forEach(function(t){var e={id:t.id,label:String(t.label||t.id)};d(e,M(t.attr,P)),e.image&&(e.shape="image"),i.nodes.push(e)}),e.edges){var o=function(t){var e={from:t.from,to:t.to};return d(e,M(t.attr,I)),e.arrows="->"===t.type?"to":void 0,e};e.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=o(t);i.edges.push(e)}),D(e,n,function(e,n){var s=p(i,e.id,n.id,t.type,t.attr),r=o(s);i.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=o(t);i.edges.push(e)})})}return e.attr&&(i.options=e.attr),i}var T=i(55),E=o(T),P={fontsize:"font.size",fontcolor:"font.color",labelfontcolor:"font.color",fontname:"font.face",color:["color.border","color.background"],fillcolor:"color.background",tooltip:"title",labeltooltip:"title"},I=(0,E.default)(P);I.color="color.color";var N={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},z={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},R="",L=0,A="",B="",F=N.NULL,H=/[a-zA-Z_0-9.:#]/;e.parseDOT=n,e.DOTToGraph=C},function(t,e){function i(t,e){var i=[],o=[],n={edges:{inheritColor:!1},nodes:{fixed:!1,parseColor:!1}};void 0!==e&&(void 0!==e.fixed&&(n.nodes.fixed=e.fixed),void 0!==e.parseColor&&(n.nodes.parseColor=e.parseColor),void 0!==e.inheritColor&&(n.edges.inheritColor=e.inheritColor));for(var s=t.edges,r=t.nodes,a=0;a<s.length;a++){var h={},d=s[a];h.id=d.id,h.from=d.source,h.to=d.target,h.attributes=d.attributes,h.label=d.label,h.title=void 0!==d.attributes?d.attributes.title:void 0,"Directed"===d.type&&(h.arrows="to"),d.color&&n.inheritColor===!1&&(h.color=d.color),i.push(h)}for(var a=0;a<r.length;a++){var l={},u=r[a];l.id=u.id,l.attributes=u.attributes,l.title=u.title,l.x=u.x,l.y=u.y,l.label=u.label,l.title=void 0!==u.attributes?u.attributes.title:void 0,n.nodes.parseColor===!0?l.color=u.color:l.color=void 0!==u.color?{background:u.color,border:u.color,highlight:{background:u.color,border:u.color},hover:{background:u.color,border:u.color}}:void 0,l.size=u.size,l.fixed=n.nodes.fixed&&void 0!==u.x&&void 0!==u.y,o.push(l)}return{nodes:o,edges:i}}e.parseGephi=i},function(t,e){e.en={edit:"Edit",del:"Delete selected",back:"Back",addNode:"Add Node",addEdge:"Add Edge",editNode:"Edit Node",editEdge:"Edit Edge",addDescription:"Click in an empty space to place a new node.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",createEdgeError:"Cannot link edges to a cluster.",deleteClusterError:"Clusters cannot be deleted.",editClusterError:"Clusters cannot be edited."},e.en_EN=e.en,e.en_US=e.en,e.de={edit:"Editieren",del:"Lösche Auswahl",back:"Zurück",addNode:"Knoten hinzufügen",addEdge:"Kante hinzufügen",editNode:"Knoten editieren",editEdge:"Kante editieren",addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",deleteClusterError:"Cluster können nicht gelöscht werden.",editClusterError:"Cluster können nicht editiert werden."},e.de_DE=e.de,e.es={edit:"Editar",del:"Eliminar selección",back:"Átras",addNode:"Añadir nodo",addEdge:"Añadir arista",editNode:"Editar nodo",editEdge:"Editar arista",addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",createEdgeError:"No se puede conectar una arista a un grupo.",deleteClusterError:"No es posible eliminar grupos.",editClusterError:"No es posible editar grupos."},e.es_ES=e.es,e.it={edit:"Modifica",del:"Cancella la selezione",back:"Indietro",addNode:"Aggiungi un nodo",addEdge:"Aggiungi un vertice",editNode:"Modifica il nodo",editEdge:"Modifica il vertice",addDescription:"Clicca per aggiungere un nuovo nodo",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",createEdgeError:"Non si possono collegare vertici ad un cluster",deleteClusterError:"I cluster non possono essere cancellati",editClusterError:"I clusters non possono essere modificati."},e.it_IT=e.it,e.nl={edit:"Wijzigen",del:"Selectie verwijderen",back:"Terug",addNode:"Node toevoegen",addEdge:"Link toevoegen",editNode:"Node wijzigen",editEdge:"Link wijzigen",addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",createEdgeError:"Kan geen link maken naar een cluster.",deleteClusterError:"Clusters kunnen niet worden verwijderd.",editClusterError:"Clusters kunnen niet worden aangepast."},e.nl_NL=e.nl,e.nl_BE=e.nl,e["pt-br"]={edit:"Editar",del:"Remover selecionado",back:"Voltar",addNode:"Adicionar nó",addEdge:"Adicionar aresta",editNode:"Editar nó",editEdge:"Editar aresta",addDescription:"Clique em um espaço em branco para adicionar um novo nó",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",createEdgeError:"Não foi possível linkar arestas a um cluster.",deleteClusterError:"Clusters não puderam ser removidos.",editClusterError:"Clusters não puderam ser editados."},e["pt-BR"]=e["pt-br"],e.pt_BR=e["pt-br"],e.pt_br=e["pt-br"],e.ru={edit:"Редактировать",del:"Удалить выбранное",back:"Назад",addNode:"Добавить узел",addEdge:"Добавить ребро",editNode:"Редактировать узел",editEdge:"Редактировать ребро",addDescription:"Кликните в свободное место, чтобы добавить новый узел.",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",createEdgeError:"Невозможно соединить ребра в кластер.",deleteClusterError:"Кластеры не могут быть удалены",editClusterError:"Кластеры недоступны для редактирования."},e.ru_RU=e.ru}])});
-//# sourceMappingURL=vis.map
diff --git a/packages/flamenco/flamenco/tasks/__init__.py b/packages/flamenco/flamenco/tasks/__init__.py
deleted file mode 100644
index 1fdb87ef784e9422bf9896a91a7860e123b56f04..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/tasks/__init__.py
+++ /dev/null
@@ -1,147 +0,0 @@
-"""Task management."""
-
-import attr
-
-import werkzeug.exceptions as wz_exceptions
-
-from pillar import attrs_extra
-from pillar.web.system_util import pillar_api
-
-from pillarsdk.exceptions import ResourceNotFound
-
-# Keep this synced with _config.sass
-COLOR_FOR_TASK_STATUS = {
-    'queued': '#b4bbaa',
-    'canceled': '#999',
-    'failed': '#ff8080',
-    'claimed-by-manager': '#d1c5d3',
-    'processing': '#ffbe00',
-    'active': '#00ceff',
-    'completed': '#bbe151',
-}
-
-REQUEABLE_TASK_STATES = {'completed', 'canceled', 'failed'}
-
-
-@attr.s
-class TaskManager(object):
-    _log = attrs_extra.log('%s.TaskManager' % __name__)
-
-    def api_create_task(self, job, commands, name, parents=None, priority=50):
-        """Creates a task in MongoDB for the given job, executing commands.
-
-        Returns the ObjectId of the created task.
-        """
-
-        from eve.methods.post import post_internal
-
-        task = {
-            'job': job['_id'],
-            'manager': job['manager'],
-            'user': job['user'],
-            'name': name,
-            'status': 'queued',
-            'job_type': job['job_type'],
-            'commands': [cmd.to_dict() for cmd in commands],
-            'job_priority': job['priority'],
-            'priority': priority,
-            'project': job['project'],
-        }
-        # Insertion of None parents is not supported
-        if parents:
-            task['parents'] = parents
-
-        self._log.info('Creating task %s for manager %s, user %s',
-                       name, job['manager'], job['user'])
-
-        r, _, _, status = post_internal('flamenco_tasks', task)
-        if status != 201:
-            self._log.error('Error %i creating task %s: %s',
-                            status, task, r)
-            raise wz_exceptions.InternalServerError('Unable to create task')
-
-        return r['_id']
-
-    def tasks_for_job(self, job_id, status=None, page=1):
-        from .sdk import Task
-
-        api = pillar_api()
-        payload = {
-            'where': {
-                'job': unicode(job_id),
-            },
-            'sorted': [
-                ('priority', -1),
-                ('_id', 1),
-            ],
-            # 'max_results': 100,
-            'page': page,
-        }
-        if status:
-            payload['where']['status'] = status
-        tasks = Task.all(payload, api=api)
-        return tasks
-
-    def tasks_for_project(self, project_id):
-        """Returns the tasks for the given project.
-
-        :returns: {'_items': [task, task, ...], '_meta': {Eve metadata}}
-        """
-        from .sdk import Task
-
-        api = pillar_api()
-        try:
-            tasks = Task.all({
-                'where': {
-                    'project': project_id,
-                }}, api=api)
-        except ResourceNotFound:
-            return {'_items': [], '_meta': {'total': 0}}
-
-        return tasks
-
-    def web_set_task_status(self, task_id, new_status):
-        """Web-level call to updates the task status."""
-        from .sdk import Task
-
-        api = pillar_api()
-        task = Task({'_id': task_id})
-        task.patch({'op': 'set-task-status',
-                    'status': new_status}, api=api)
-
-    def api_find_job_enders(self, job_id):
-        """Returns a list of tasks that could be the last tasks of a job.
-
-        In other words, returns all tasks that are not a parent of other tasks.
-
-        :returns: list of task IDs
-        :rtype: list
-        """
-
-        from flamenco import current_flamenco
-
-        tasks_coll = current_flamenco.db('tasks')
-
-        # Get the distinct set of tasks used as parents.
-        parent_tasks = tasks_coll.aggregate([
-            {'$match': {'job': job_id}},
-            {'$project': {'parents': 1}},
-            {'$unwind': {'path': '$parents'}},
-            {'$group': {'_id': '$parents'}},
-        ])
-        parent_ids = [t['_id'] for t in parent_tasks]
-
-        # Get all the tasks that do not have such an ID.
-        tasks = tasks_coll.find({'job': job_id,
-                                 '_id': {'$nin': parent_ids}},
-                                projection={'_id': 1})
-
-        tids = [t['_id'] for t in tasks]
-        return tids
-
-
-def setup_app(app):
-    from . import eve_hooks, patch
-
-    eve_hooks.setup_app(app)
-    patch.setup_app(app)
diff --git a/packages/flamenco/flamenco/tasks/eve_hooks.py b/packages/flamenco/flamenco/tasks/eve_hooks.py
deleted file mode 100644
index 89f749c80b588b18eef8cd30933fd4039d2e182b..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/tasks/eve_hooks.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-import logging
-
-import werkzeug.exceptions as wz_exceptions
-from pillar.api.utils.authorization import user_matches_roles
-
-from flamenco import current_flamenco, ROLES_REQUIRED_TO_VIEW_ITEMS, ROLES_REQUIRED_TO_VIEW_LOGS
-
-log = logging.getLogger(__name__)
-
-
-def check_task_permission_fetch(task_doc):
-
-    if current_flamenco.current_user_is_flamenco_admin():
-        return
-
-    if not current_flamenco.manager_manager.user_is_manager():
-        # Subscribers can read Flamenco tasks.
-        if user_matches_roles(ROLES_REQUIRED_TO_VIEW_ITEMS):
-            return
-        raise wz_exceptions.Forbidden()
-
-    if not current_flamenco.manager_manager.user_manages(mngr_doc_id=task_doc.get('manager')):
-        # FIXME: Regular user or not task-owning manager, undefined behaviour as of yet.
-        # # Run validation process, since GET on nodes entry point is public
-        # check_permissions('flamenco_tasks', task_doc, 'GET',
-        #                   append_allowed_methods=True)
-        raise wz_exceptions.Forbidden()
-
-    # Managers can re-fetch their own tasks to validate their local task cache.
-
-
-def check_task_log_permission_fetch(task_log_docs):
-    if user_matches_roles(ROLES_REQUIRED_TO_VIEW_LOGS):
-        return
-    raise wz_exceptions.Forbidden()
-
-
-def task_logs_remove_fields(task_log_docs):
-    """Some fields are added by Eve, but we don't need those for task logs."""
-
-    for task_log in task_log_docs.get('_items', []):
-        task_log_remove_fields(task_log)
-
-
-def task_log_remove_fields(task_log):
-    task_log.pop('_etag', None)
-    task_log.pop('_updated', None)
-    task_log.pop('_created', None)
-
-
-def check_task_permission_fetch_resource(response):
-    if current_flamenco.current_user_is_flamenco_admin():
-        return
-
-    if not current_flamenco.manager_manager.user_is_manager():
-        # Subscribers can read Flamenco tasks.
-        if user_matches_roles(ROLES_REQUIRED_TO_VIEW_ITEMS):
-            return
-
-    raise wz_exceptions.Forbidden()
-
-
-def check_task_permissions_create_delete(task_doc, original_doc=None):
-    """For now, only admins are allowed to create and delete tasks."""
-
-    if not current_flamenco.current_user_is_flamenco_admin():
-        raise wz_exceptions.Forbidden()
-
-    # FIXME: check user access to the project.
-
-
-def check_task_permissions_edit(task_doc, original_doc=None):
-    """For now, only admins and owning managers are allowed to edit."""
-
-    if not current_flamenco.current_user_is_flamenco_admin():
-        raise wz_exceptions.Forbidden()
-
-    # FIXME: check user access to the project.
-
-
-def update_job_status(task_doc, original_doc):
-    """Update the job status given the new task status."""
-
-    current_status = task_doc.get('status')
-    old_status = original_doc.get('status')
-
-    if current_status == old_status:
-        return
-
-    task_id = task_doc['_id']
-    job_id = task_doc.get('job')
-    if not job_id:
-        log.warning('update_job_status(): Task %s has no job, this should not happen.', task_id)
-        return
-
-    current_flamenco.job_manager.update_job_after_task_status_change(
-        job_id, task_id, current_status)
-
-
-def setup_app(app):
-    app.on_fetched_resource_flamenco_task_logs += check_task_log_permission_fetch
-    app.on_fetched_resource_flamenco_task_logs += task_logs_remove_fields
-    app.on_fetched_item_flamenco_task_logs += task_log_remove_fields
-
-    app.on_fetched_item_flamenco_tasks += check_task_permission_fetch
-    app.on_fetched_resource_flamenco_tasks += check_task_permission_fetch_resource
-
-    app.on_insert_flamenco_tasks += check_task_permissions_create_delete
-    app.on_delete_flamenco_tasks += check_task_permissions_create_delete
-    app.on_update_flamenco_tasks += check_task_permissions_edit
-    app.on_replace_flamenco_tasks += check_task_permissions_edit
-    app.on_replaced_flamenco_tasks += update_job_status
diff --git a/packages/flamenco/flamenco/tasks/patch.py b/packages/flamenco/flamenco/tasks/patch.py
deleted file mode 100644
index c58e8686deee84e52b7182bce3f76b0a38c9e7bb..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/tasks/patch.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""Task patching support."""
-
-import logging
-
-import werkzeug.exceptions as wz_exceptions
-from flask import Blueprint, request
-from pillar.api.utils import authorization, authentication, str2id
-
-from flamenco import current_flamenco
-
-log = logging.getLogger(__name__)
-blueprint = Blueprint('flamenco.tasks.patch', __name__)
-
-patch_handlers = {}
-
-
-def patch_handler(operation):
-    """Decorator, marks the decorated function as PATCH handler."""
-
-    def decorator(func):
-        patch_handlers[operation] = func
-        return func
-
-    return decorator
-
-
-@blueprint.route('/<task_id>', methods=['PATCH'])
-@authorization.require_login()
-def patch_task(task_id):
-    # Parse the request
-    task_id = str2id(task_id)
-    patch = request.get_json()
-
-    try:
-        patch_op = patch['op']
-    except KeyError:
-        raise wz_exceptions.BadRequest("PATCH should contain 'op' key to denote operation.")
-
-    log.debug('User %s wants to PATCH %s task %s',
-              authentication.current_user_id(), patch_op, task_id)
-
-    # Find the PATCH handler for the operation.
-    try:
-        handler = patch_handlers[patch_op]
-    except KeyError:
-        log.warning('No PATCH handler for operation %r', patch_op)
-        raise wz_exceptions.BadRequest('Operation %r not supported' % patch_op)
-
-    # Let the PATCH handler do its thing.
-    return handler(task_id, patch)
-
-
-@patch_handler(u'set-task-status')
-@authorization.require_login(require_roles={u'flamenco-admin'})
-def patch_set_task_status(task_id, patch):
-    """Updates a task's status in the database."""
-
-    from flamenco import current_flamenco
-    from pillar.api.utils import str2id
-
-    new_status = patch['status']
-    task_id = str2id(task_id)
-
-    try:
-        current_flamenco.update_status('tasks', task_id, new_status)
-    except ValueError:
-        raise wz_exceptions.UnprocessableEntity('Invalid status')
-
-    # also inspect other tasks of the same job, and possibly update the job status as well.
-    tasks_coll = current_flamenco.db('tasks')
-    task_job = tasks_coll.find_one({'_id': task_id}, projection={'job': 1})
-
-    current_flamenco.job_manager.update_job_after_task_status_change(task_job['job'],
-                                                                     task_id,
-                                                                     new_status)
-
-    return '', 204
-
-
-def setup_app(app):
-    app.register_api_blueprint(blueprint, url_prefix='/flamenco/tasks')
diff --git a/packages/flamenco/flamenco/tasks/routes.py b/packages/flamenco/flamenco/tasks/routes.py
deleted file mode 100644
index 277d36a46b06eed567c31045e35c54884e290520..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/tasks/routes.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# coding=utf-8
-import logging
-
-from flask import Blueprint, render_template, request
-import flask_login
-import werkzeug.exceptions as wz_exceptions
-
-from pillar.web.system_util import pillar_api
-
-from flamenco.routes import flamenco_project_view
-from flamenco import current_flamenco, ROLES_REQUIRED_TO_VIEW_ITEMS, ROLES_REQUIRED_TO_VIEW_LOGS
-
-TASK_LOG_PAGE_SIZE = 10
-
-# The task statuses that can be set from the web-interface.
-ALLOWED_TASK_STATUSES_FROM_WEB = {'cancel-requested', 'queued'}
-
-perjob_blueprint = Blueprint('flamenco.tasks.perjob', __name__,
-                             url_prefix='/<project_url>/jobs/<job_id>')
-perproject_blueprint = Blueprint('flamenco.tasks.perproject', __name__,
-                                 url_prefix='/<project_url>/tasks')
-log = logging.getLogger(__name__)
-
-
-@perproject_blueprint.route('/', endpoint='index')
-@flamenco_project_view()
-def list_for_project(project, task_id=None):
-    tasks = current_flamenco.task_manager.tasks_for_project(project['_id'])
-    return render_template('flamenco/tasks/list_for_project.html',
-                           tasks=tasks['_items'],
-                           open_task_id=task_id,
-                           project=project)
-
-
-@perjob_blueprint.route('/tasks')
-@flamenco_project_view()
-def list_for_job(project, job_id, task_id=None):
-    from pillar.web.utils import last_page_index
-
-    page_idx = int(request.args.get('page', '1'))
-
-    tasks = current_flamenco.task_manager.tasks_for_job(job_id, page=page_idx)
-    return render_template('flamenco/tasks/list_for_job_embed.html',
-                           tasks=tasks['_items'],
-                           open_task_id=task_id,
-                           project=project,
-                           task_count=tasks['_meta']['total'],
-                           page_idx=page_idx,
-                           page_count=last_page_index(tasks['_meta']),
-                           )
-
-
-@perproject_blueprint.route('/<task_id>')
-@flask_login.login_required
-@flamenco_project_view(extension_props=True)
-def view_task(project, flamenco_props, task_id):
-    from flamenco.tasks.sdk import Task
-
-    api = pillar_api()
-
-    if not request.is_xhr:
-        # Render page that'll perform the XHR.
-        from flamenco.jobs import routes as job_routes
-
-        task = Task.find(task_id, {'projection': {'job': 1}}, api=api)
-        return job_routes.for_project(project, job_id=task['job'], task_id=task_id)
-
-    # Task list is public, task details are not.
-    if not flask_login.current_user.has_role(*ROLES_REQUIRED_TO_VIEW_ITEMS):
-        raise wz_exceptions.Forbidden()
-
-    task = Task.find(task_id, api=api)
-
-    from . import REQUEABLE_TASK_STATES
-    write_access = current_flamenco.current_user_is_flamenco_admin()
-    can_requeue_task = write_access and task['status'] in REQUEABLE_TASK_STATES
-
-    return render_template('flamenco/tasks/view_task_embed.html',
-                           task=task,
-                           project=project,
-                           flamenco_props=flamenco_props.to_dict(),
-                           flamenco_context=request.args.get('context'),
-                           can_requeue_task=can_requeue_task)
-
-
-@perproject_blueprint.route('/<task_id>/set-status', methods=['POST'])
-@flask_login.login_required
-@flamenco_project_view(extension_props=False)
-def set_task_status(project, task_id):
-    from flask_login import current_user
-
-    new_status = request.form['status']
-    if new_status not in ALLOWED_TASK_STATUSES_FROM_WEB:
-        log.warning('User %s tried to set status of task %s to disallowed status "%s"; denied.',
-                    current_user.objectid, task_id, new_status)
-        raise wz_exceptions.UnprocessableEntity('Status "%s" not allowed' % new_status)
-
-    log.info('User %s set status of task %s to "%s"', current_user.objectid, task_id, new_status)
-    current_flamenco.task_manager.web_set_task_status(task_id, new_status)
-
-    return '', 204
-
-
-@perproject_blueprint.route('/<task_id>/log')
-@flask_login.login_required
-@flamenco_project_view()
-def view_task_log(project, task_id):
-    """Shows a limited number of task log entries.
-
-    Pass page=N (N≥1) to request further entries.
-    """
-
-    from pillarsdk import ResourceNotFound
-    from pillar.web.utils import is_valid_id, last_page_index
-    from flamenco.tasks.sdk import TaskLog
-
-    if not is_valid_id(task_id):
-        raise wz_exceptions.UnprocessableEntity()
-
-    # Task list is public, task details are not.
-    if not flask_login.current_user.has_role(*ROLES_REQUIRED_TO_VIEW_LOGS):
-        raise wz_exceptions.Forbidden()
-
-    page_idx = int(request.args.get('page', 1))
-    api = pillar_api()
-    try:
-        logs = TaskLog.all({'where': {'task': task_id},
-                            'page': page_idx,
-                            'max_results': TASK_LOG_PAGE_SIZE},
-                           api=api)
-    except ResourceNotFound:
-        logs = {'_items': [],
-                '_meta': {'total': 0,
-                          'page': page_idx,
-                          'max_results': TASK_LOG_PAGE_SIZE}}
-
-    last_page_idx = last_page_index(logs['_meta'])
-    has_next_page = page_idx < last_page_idx
-    has_prev_page = page_idx > 1
-
-    return render_template('flamenco/tasks/view_task_log_embed.html',
-                           page_idx=page_idx,
-                           logs=logs,
-                           has_prev_page=has_prev_page,
-                           has_next_page=has_next_page,
-                           last_page_idx=last_page_idx,
-                           project=project,
-                           task_id=task_id)
-
-
-@perproject_blueprint.route('/<task_id>/download-log')
-@flask_login.login_required
-@flamenco_project_view()
-def download_task_log(project, task_id):
-    """Shows the entire task log as text/plain"""
-
-    from flask import Response, current_app
-
-    from pillar.web.utils import is_valid_id, last_page_index
-    from flamenco.tasks.sdk import TaskLog
-
-    if not is_valid_id(task_id):
-        raise wz_exceptions.UnprocessableEntity()
-
-    # Task list is public, task details are not.
-    if not flask_login.current_user.has_role(*ROLES_REQUIRED_TO_VIEW_LOGS):
-        raise wz_exceptions.Forbidden()
-
-    # Required because the stream_log() generator will run outside the app context.
-    app = current_app._get_current_object()
-    api = pillar_api()
-
-    def stream_log():
-        page_idx = 1
-        while True:
-            with app.app_context():
-                logs = TaskLog.all({'where': {'task': task_id},
-                                    'page': page_idx,
-                                    'max_results': TASK_LOG_PAGE_SIZE},
-                                   api=api)
-
-            for tasklog in logs['_items']:
-                yield tasklog.log + '\n'
-
-            if page_idx >= last_page_index(logs['_meta']):
-                break
-
-            page_idx += 1
-
-    return Response(stream_log(), mimetype='text/plain')
diff --git a/packages/flamenco/flamenco/tasks/sdk.py b/packages/flamenco/flamenco/tasks/sdk.py
deleted file mode 100644
index 2c8bf68f8e5b623fd5bde73e342adf6bcc3b7cc6..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/tasks/sdk.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from pillarsdk.resource import List
-from pillarsdk.resource import Find
-from pillarsdk.resource import Patch
-
-
-class Task(List, Find, Patch):
-    """Task class wrapping the REST nodes endpoint
-    """
-    path = 'flamenco/tasks'
-    ensure_query_projections = {'project': 1, 'job': 1}
-
-
-class TaskLog(List, Find):
-    """Task log class wrapping the REST nodes endpoint
-    """
-    path = 'flamenco/task_logs'
diff --git a/packages/flamenco/flamenco/utils.py b/packages/flamenco/flamenco/utils.py
deleted file mode 100644
index 94cdbf0447826283f97bca2b57104b7d37578b8f..0000000000000000000000000000000000000000
--- a/packages/flamenco/flamenco/utils.py
+++ /dev/null
@@ -1,131 +0,0 @@
-import contextlib
-
-
-def frame_range_parse(frame_range=None):
-    """Given a range of frames, return a list containing each frame.
-
-    :type frame_range: str
-    :rtype: list
-
-    :Example:
-    >>> frames = "1,3-5,8"
-    >>> frame_range_parse(frames)
-    >>> [1, 3, 4, 5, 8]
-    """
-    if not frame_range:
-        return list()
-
-    frames_list = []
-    for part in frame_range.split(','):
-        x = part.split("-")
-        num_parts = len(x)
-        if num_parts == 1:
-            frame = int(x[0])
-            frames_list.append(frame)
-            # print("Individual frame %d" % (frame))
-        elif num_parts == 2:
-            frame_start = int(x[0])
-            frame_end = int(x[1])
-            frames_list += range(frame_start, frame_end + 1)
-            # print("Frame range %d-%d" % (frame_start, frame_end))
-    frames_list.sort()
-    return frames_list
-
-
-def frame_range_merge(frames_list=None, blender_style=False):
-    """Given a frames list, merge them and return them as range of frames.
-
-    :type frames_list: list
-    :type blender_style: bool
-    :param blender_style: whether to use Blender style frame range notation (3..5) or not (3-5).
-    :rtype: str
-
-    :Example:
-    >>> frames = [1, 3, 4, 5, 8]
-    >>> frame_range_merge(frames)
-    u'1,3-5,8'
-    >>> frame_range_merge(frames, blender_style=True)
-    u'1,3..5,8'
-    """
-    if not frames_list:
-        return ""
-
-    range_sep = '..' if blender_style else '-'
-
-    ranges = []
-    current_frame = start_frame = prev_frame = frames_list[0]
-    n = len(frames_list)
-    for i in range(1, n):
-        current_frame = frames_list[i]
-        if current_frame == prev_frame + 1:
-            pass
-        else:
-            if start_frame == prev_frame:
-                ranges.append(str(start_frame))
-            elif start_frame + 1 == prev_frame:
-                ranges.append(str(start_frame))
-                ranges.append(str(prev_frame))
-            else:
-                ranges.append(u'{}{}{}'.format(start_frame, range_sep, prev_frame))
-            start_frame = current_frame
-        prev_frame = current_frame
-    if start_frame == current_frame:
-        ranges.append(str(start_frame))
-    elif start_frame + 1 == current_frame:
-        ranges.append(str(start_frame))
-        ranges.append(str(current_frame))
-    else:
-        ranges.append(u'{}{}{}'.format(start_frame, range_sep, current_frame))
-    return u','.join(ranges)
-
-
-def iter_frame_range(merged_frame_range, chunk_size):
-    """Generator, iterates over frame chunks.
-
-    Yields lists of frame numbers. Each except the last list is exactly
-    'chunk_size' frame numbers long.
-    """
-
-    parsed_frames = frame_range_parse(merged_frame_range)
-
-    for chunk_start in range(0, len(parsed_frames), chunk_size):
-        chunk_frames = parsed_frames[chunk_start:chunk_start + chunk_size]
-        yield chunk_frames
-
-
-@contextlib.contextmanager
-def report_duration(logger, description):
-    import time
-
-    start_time = time.time()
-    try:
-        yield
-    finally:
-        end_time = time.time()
-        logger.debug('report_duration: %s took %f seconds', description, end_time - start_time)
-
-
-def camel_case_to_lower_case_underscore(string):
-    """
-    Converts a string from CamelCase to lower_case_underscore.
-
-    None-safe.
-
-    :type string: unicode or str or None
-    :rtype: unicode or str or None
-    """
-
-    if string is None:
-        return None
-
-    words = []
-    from_char_position = 0
-    for current_char_position, char in enumerate(string):
-        if char.isupper() and from_char_position < current_char_position:
-            words.append(string[from_char_position:current_char_position].lower())
-            from_char_position = current_char_position
-    words.append(string[from_char_position:].lower())
-
-    if isinstance(string, str):
-        return '_'.join(words)
-    return u'_'.join(words)
diff --git a/packages/flamenco/gulp b/packages/flamenco/gulp
deleted file mode 100755
index 093ad60fa4562c2b83b5e9ad5e007a44dd7a4e0f..0000000000000000000000000000000000000000
--- a/packages/flamenco/gulp
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash -ex
-
-GULP=./node_modules/.bin/gulp
-
-function install() {
-    npm install
-    touch $GULP  # installer doesn't always touch this after a build, so we do.
-}
-
-# Rebuild Gulp if missing or outdated.
-[ -e $GULP ] || install
-[ gulpfile.js -nt $GULP ] && install
-
-if [ "$1" == "watch" ]; then
-    # Treat "gulp watch" as "gulp && gulp watch"
-    $GULP
-fi
-
-exec $GULP "$@"
diff --git a/packages/flamenco/gulpfile.js b/packages/flamenco/gulpfile.js
deleted file mode 100644
index de598722041d20d7688b8b583442d91d7e41a3f4..0000000000000000000000000000000000000000
--- a/packages/flamenco/gulpfile.js
+++ /dev/null
@@ -1,98 +0,0 @@
-var argv         = require('minimist')(process.argv.slice(2));
-var autoprefixer = require('gulp-autoprefixer');
-var chmod        = require('gulp-chmod');
-var concat       = require('gulp-concat');
-var gulp         = require('gulp');
-var gulpif       = require('gulp-if');
-var jade         = require('gulp-jade');
-var livereload   = require('gulp-livereload');
-var plumber      = require('gulp-plumber');
-var rename       = require('gulp-rename');
-var sass         = require('gulp-sass');
-var sourcemaps   = require('gulp-sourcemaps');
-var uglify       = require('gulp-uglify');
-var cache        = require('gulp-cached');
-
-var enabled = {
-    uglify: argv.production,
-    maps: argv.production,
-    failCheck: argv.production,
-    prettyPug: !argv.production,
-    liveReload: !argv.production
-};
-
-
-/* CSS */
-gulp.task('styles', function() {
-    gulp.src('src/styles/**/*.sass')
-        .pipe(gulpif(enabled.failCheck, plumber()))
-        .pipe(gulpif(enabled.maps, sourcemaps.init()))
-        .pipe(sass({
-            outputStyle: 'compressed'}
-            ))
-        .pipe(autoprefixer("last 3 versions"))
-        .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
-        .pipe(gulp.dest('flamenco/static/assets/css'))
-        .pipe(gulpif(enabled.liveReload, livereload()));
-});
-
-
-/* Templates - Jade */
-gulp.task('templates', function() {
-    gulp.src('src/templates/**/*.jade')
-        .pipe(gulpif(enabled.failCheck, plumber()))
-        .pipe(cache('templating'))
-        .pipe(jade({
-            pretty: enabled.prettyPug
-        }))
-        .pipe(gulp.dest('flamenco/templates/'))
-        .pipe(gulpif(enabled.liveReload, livereload()));
-});
-
-
-/* Individual Uglified Scripts */
-gulp.task('scripts', function() {
-    gulp.src('src/scripts/*.js')
-        .pipe(gulpif(enabled.failCheck, plumber()))
-        .pipe(cache('scripting'))
-        .pipe(gulpif(enabled.maps, sourcemaps.init()))
-        .pipe(gulpif(enabled.uglify, uglify()))
-        .pipe(rename({suffix: '.min'}))
-        .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
-        .pipe(chmod(644))
-        .pipe(gulp.dest('flamenco/static/assets/js/generated/'))
-        .pipe(gulpif(enabled.liveReload, livereload()));
-});
-
-
-/* Collection of scripts in src/scripts/tutti/ to merge into tutti.min.js */
-/* Since it's always loaded, it's only for functions that we want site-wide */
-gulp.task('scripts_tutti', function() {
-    gulp.src('src/scripts/tutti/**/*.js')
-        .pipe(gulpif(enabled.failCheck, plumber()))
-        .pipe(gulpif(enabled.maps, sourcemaps.init()))
-        .pipe(concat("tutti.min.js"))
-        .pipe(gulpif(enabled.uglify, uglify()))
-        .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
-        .pipe(chmod(644))
-        .pipe(gulp.dest('flamenco/static/assets/js/generated/'))
-        .pipe(gulpif(enabled.liveReload, livereload()));
-});
-
-
-// While developing, run 'gulp watch'
-gulp.task('watch',function() {
-    // Only listen for live reloads if ran with --livereload
-    if (argv.livereload){
-        livereload.listen();
-    }
-
-    gulp.watch('src/styles/**/*.sass',['styles']);
-    gulp.watch('src/templates/**/*.jade',['templates']);
-    gulp.watch('src/scripts/*.js',['scripts']);
-    gulp.watch('src/scripts/tutti/*.js',['scripts_tutti']);
-});
-
-
-// Run 'gulp' to build everything at once
-gulp.task('default', ['styles', 'templates', 'scripts', 'scripts_tutti']);
diff --git a/packages/flamenco/package.json b/packages/flamenco/package.json
deleted file mode 100644
index bc30f7737f8746b6b665686a7f4cf69ed1c2fcc6..0000000000000000000000000000000000000000
--- a/packages/flamenco/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-	"name": "flamenco",
-	"license": "GPL",
-	"author": "Blender Institute",
-	"repository": {
-		"type": "git",
-		"url": "git://git.blender.org/flamenco-server.git"
-	},
-	"devDependencies": {
-		"gulp": "~3.9.1",
-		"gulp-autoprefixer": "~2.3.1",
-		"gulp-cached": "~1.1.0",
-		"gulp-chmod": "~1.3.0",
-		"gulp-concat": "~2.6.0",
-		"gulp-if": "^2.0.1",
-		"gulp-jade": "~1.1.0",
-		"gulp-livereload": "~3.8.1",
-		"gulp-plumber": "~1.1.0",
-		"gulp-rename": "~1.2.2",
-		"gulp-sass": "~2.3.1",
-		"gulp-sourcemaps": "~1.6.0",
-		"gulp-uglify": "~1.5.3",
-		"minimist": "^1.2.0"
-	}
-}
diff --git a/packages/flamenco/requirements.txt b/packages/flamenco/requirements.txt
deleted file mode 100644
index 635814726df3a87825baa8255b7ff7d5c7068bae..0000000000000000000000000000000000000000
--- a/packages/flamenco/requirements.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# Primary requirements:
-# pillarsdk
-# pillar
-
-attrs==16.2.0
-python-dateutil==2.5.3
-pylru==1.0.4
-pathlib2==2.2.1
-
-# Secondary requirements:
-six==1.10.0
-scandir==1.4
-
-# Testing requirements:
-pytest==3.0.1
-responses==0.5.1
-pytest-cov==2.3.1
-mock==2.0.0
diff --git a/packages/flamenco/rsync_ui.sh b/packages/flamenco/rsync_ui.sh
deleted file mode 100755
index 2a1c8b3eb3c6474dba8db6288c19e99759ede808..0000000000000000000000000000000000000000
--- a/packages/flamenco/rsync_ui.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-
-set -e  # error out when one of the commands in the script errors.
-
-# macOS does not support readlink -f, so we use greadlink instead
-if [[ `uname` == 'Darwin' ]]; then
-    command -v greadlink 2>/dev/null 2>&1 || { echo >&2 "Install greadlink using brew."; exit 1; }
-    readlink='greadlink'
-else
-    readlink='readlink'
-fi
-
-FLAMENCO_DIR="$(dirname "$($readlink -f "$0")")"
-if [ ! -d "$FLAMENCO_DIR" ]; then
-    echo "Unable to find Flamenco dir '$FLAMENCO_DIR'"
-    exit 1
-fi
-
-ASSETS="$FLAMENCO_DIR/flamenco/static/assets/"
-TEMPLATES="$FLAMENCO_DIR/flamenco/templates/flamenco"
-
-if [ ! -d "$ASSETS" ]; then
-    echo "Unable to find assets dir $ASSETS"
-    exit 1
-fi
-
-cd $FLAMENCO_DIR
-if [ $(git rev-parse --abbrev-ref HEAD) != "production" ]; then
-    echo "You are NOT on the production branch, refusing to rsync_ui." >&2
-    exit 1
-fi
-
-echo
-echo "*** GULPA GULPA ***"
-./gulp --production
-
-echo
-echo "*** SYNCING ASSETS ***"
-# Exclude files managed by Git.
-rsync -avh $ASSETS --exclude js/vendor/ root@cloud.blender.org:/data/git/flamenco/packages/flamenco/flamenco/static/assets/
-
-echo
-echo "*** SYNCING TEMPLATES ***"
-rsync -avh $TEMPLATES root@cloud.blender.org:/data/git/flamenco/packages/flamenco/flamenco/templates/
diff --git a/packages/flamenco/runserver.py b/packages/flamenco/runserver.py
deleted file mode 100644
index c71628e0ca8d6bee8a2ebeabe3ac7a25ca3c52cc..0000000000000000000000000000000000000000
--- a/packages/flamenco/runserver.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env python
-
-from pillar import PillarServer
-from flamenco import FlamencoExtension
-
-app = PillarServer('.')
-app.load_extension(FlamencoExtension(), '/flamenco')
-app.process_extensions()
-
-if __name__ == '__main__':
-    app.run('::0', 5000, debug=True)
diff --git a/packages/flamenco/setup.cfg b/packages/flamenco/setup.cfg
deleted file mode 100644
index 2e6a735066a05cd7019bce378eea75f67694484f..0000000000000000000000000000000000000000
--- a/packages/flamenco/setup.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[tool:pytest]
-addopts = -v --cov flamenco --cov-report term-missing --ignore node_modules --ff
-
-[pep8]
-max-line-length = 100
diff --git a/packages/flamenco/setup.py b/packages/flamenco/setup.py
deleted file mode 100644
index 57ce55f58965e0bd0a48f76c71f6ee463c0ffa6f..0000000000000000000000000000000000000000
--- a/packages/flamenco/setup.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-
-"""Setup file for the Flamenco extension."""
-
-import setuptools
-
-setuptools.setup(
-    name='flamenco',
-    version='2.0-beta10',
-    packages=setuptools.find_packages('.', exclude=['test']),
-    install_requires=[
-        'pillar>=2.0',
-    ],
-    tests_require=[
-        'pytest>=2.9.1',
-        'responses>=0.5.1',
-        'pytest-cov>=2.2.1',
-        'mock>=2.0.0',
-    ],
-    zip_safe=False,
-)
diff --git a/packages/flamenco/src/scripts/depsgraph.js b/packages/flamenco/src/scripts/depsgraph.js
deleted file mode 100644
index c4d3b50857b67b068639354e3f19f0fc27eec325..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/scripts/depsgraph.js
+++ /dev/null
@@ -1,34 +0,0 @@
-function depsgraph(canvas_id, nodes, edges) {
-    var container = document.getElementById(canvas_id);
-
-    // provide the data in the vis format
-    var data = {
-        nodes: new vis.DataSet(nodes),
-        edges: new vis.DataSet(edges)
-    };
-    var options = {
-        layout: {
-            hierarchical: {
-                direction: "RL",
-                // sortMethod: "directed",
-                blockShifting: true,
-                edgeMinimization: true,
-                parentCentralization: true,
-                levelSeparation: 250,
-            },
-        },
-        edges: {
-            smooth: false,
-        },
-        interaction: {
-            dragNodes: false,
-        },
-        physics: {
-            enabled: false,
-        },
-    };
-
-    // initialize your network!
-    var network = new vis.Network(container, data, options);
-
-}
diff --git a/packages/flamenco/src/scripts/tutti/00_utils.js b/packages/flamenco/src/scripts/tutti/00_utils.js
deleted file mode 100644
index bd2ab625f3a1ddf919416ba3ae2297126c96e39b..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/scripts/tutti/00_utils.js
+++ /dev/null
@@ -1,152 +0,0 @@
-(function ( $ ) {
-    $.fn.flashOnce = function() {
-        var target = this;
-        this
-            .addClass('flash-on')
-            .delay(1000) // this delay is linked to the transition in the flash-on CSS class.
-            .queue(function() {
-                target
-                    .removeClass('flash-on')
-                    .addClass('flash-off')
-                    .dequeue()
-                ;})
-            .delay(1000)  // this delay is just to clean up the flash-X classes.
-            .queue(function() {
-                target
-                    .removeClass('flash-on flash-off')
-                    .dequeue()
-                ;})
-        ;
-        return this;
-    };
-
-    /**
-     * Fades out the element, then erases its contents and shows the now-empty element again.
-     */
-    $.fn.fadeOutAndClear = function(fade_speed) {
-        var target = this;
-        this
-            .fadeOut(fade_speed, function() {
-                target
-                    .html('')
-                    .show();
-            });
-    }
-
-    $.fn.hideAndRemove = function(hide_speed, finished) {
-        this.slideUp(hide_speed, function() {
-            this.remove();
-            if (typeof finished !== 'undefined') finished();
-        });
-    }
-
-    $.fn.removeClassPrefix = function(prefix) {
-        this.each(function(i, el) {
-            var classes = el.className.split(" ").filter(function(c) {
-                return c.lastIndexOf(prefix, 0) !== 0;
-            });
-            el.className = $.trim(classes.join(" "));
-        });
-        return this;
-    }
-
-    $.fn.openModalUrl = function(title, url) {
-        this.on('click', function(e){
-            e.preventDefault();
-
-            $('#modal').modal();
-            $("#modal .modal-header span.title").html(title);
-            $("#modal .modal-body").load(url);
-        });
-    };
-
-    /*
-     * jQuery autoResize (textarea auto-resizer)
-     * @copyright James Padolsey http://james.padolsey.com
-     * @version 1.04
-     * cracked by icyleaf <icyleaf.cn@gmail.com>
-     * https://gist.github.com/icyleaf/269160
-     */
-    $.fn.autoResize = function(options) {
-        var settings = $.extend({
-            onResize : function(){},
-            animate : true,
-            animateDuration : 0,
-            animateCallback : function(){},
-            extraSpace : 20,
-            limit: 500
-        }, options);
-
-        this.filter('textarea').each(function(){
-            var textarea = $(this).css({resize:'none','overflow-y':'hidden'}),
-            origHeight = textarea.height(),
-            clone = (function(){
-                var props = ['height','width','lineHeight','textDecoration','letterSpacing'],
-                    propOb = {};
-
-                $.each(props, function(i, prop){
-                    propOb[prop] = textarea.css(prop);
-                });
-
-                return textarea.clone().removeAttr('id').removeAttr('name').css({
-                    position: 'absolute',
-                    top: 0,
-                    left: -9999
-                }).css(propOb).attr('tabIndex','-1').insertBefore(textarea);
-            })(),
-            lastScrollTop = null,
-            updateSize = function() {
-
-                clone.height(0).val($(this).val()).scrollTop(10000);
-                var scrollTop = Math.max(clone.scrollTop(), origHeight) + settings.extraSpace,
-                    toChange = $(this).add(clone);
-
-                if (lastScrollTop === scrollTop) { return; }
-                lastScrollTop = scrollTop;
-
-                if ( scrollTop >= settings.limit ) {
-                    if ( settings.limit != 0) {
-                        $(this).css('overflow-y','').css('height', settings.limit+'px');
-                        return;
-                    }
-                }
-                settings.onResize.call(this);
-                settings.animate && textarea.css('display') === 'block' ?
-                    toChange.stop().animate({height:scrollTop}, settings.animateDuration, settings.animateCallback)
-                    : toChange.height(scrollTop);
-            };
-            textarea
-                .unbind('.dynSiz')
-                .bind('keyup.dynSiz', updateSize)
-                .bind('keydown.dynSiz', updateSize)
-                .bind('change.dynSiz', updateSize)
-                .bind('blur.dynSiz', updateSize);
-        });
-        return this;
-    };
-
-}(jQuery));
-
-function clearMainOverlay(){
-    $('#col_main-overlay-content').html('');
-    $('#col_main-overlay').removeAttr('class');
-}
-
-$(document).ready(function() {
-    /* Clear the modal inner html when hidding */
-    $('#modal').on('hidden.bs.modal', function () {
-        $("#modal .modal-body").html('');
-    });
-});
-
-document.onkeydown = function(evt) {
-    evt = evt || window.event;
-    if (evt.keyCode == 27 || evt.key == 'Escape') {
-        if ($('#col_main-overlay').hasClass('active')){
-            /* If we're in the context of a job, it means we're closing Task details*/
-            if (ProjectUtils.context() == 'job') {
-                closeTaskDetails(); // From view_task_embed template
-            }
-        }
-    }
-};
diff --git a/packages/flamenco/src/scripts/tutti/10_tasks.js b/packages/flamenco/src/scripts/tutti/10_tasks.js
deleted file mode 100644
index cac424b4b0b5a3937837f2dd0d36cb6d2d38b442..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/scripts/tutti/10_tasks.js
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * Open an item such as tasks/jobs in the corresponding div
- * Jobs load on #item-details, Tasks load on #col_main-overlay-content
- */
-function item_open(item_id, item_type, pushState, project_url)
-{
-    if (item_id === undefined || item_type === undefined) {
-        throw new ReferenceError("item_open(" + item_id + ", " + item_type + ") called.");
-    }
-
-    if (typeof project_url === 'undefined') {
-        project_url = ProjectUtils.projectUrl();
-        if (typeof project_url === 'undefined') {
-            throw new ReferenceError("ProjectUtils.projectUrl() undefined");
-        }
-    }
-
-    // Style elements starting with item_type and dash, e.g. "#job-uuid"
-    $('[id^="' + item_type + '-"]').removeClass('active');
-    var current_item = $('#' + item_type + '-' + item_id);
-    current_item.addClass('processing');
-
-    var item_url = '/flamenco/' + project_url + '/' + item_type + 's/' + item_id;
-    var push_url = item_url;
-    if (ProjectUtils.context() == 'job' && item_type == 'task'){
-        push_url = '/flamenco/' + project_url + '/jobs/with-task/' + item_id;
-    }
-    item_url += '?context=' + ProjectUtils.context();
-
-    statusBarSet('default', 'Loading ' + item_type + '…');
-
-    $.get(item_url, function(item_data) {
-        statusBarClear();
-
-        if (ProjectUtils.context() == 'job' && item_type == 'task'){
-            $('#col_main-overlay-content').html(item_data);
-            $('#col_main-overlay .col_header span.header_text').text(item_type + ' details');
-            $('#col_main-overlay').addClass('active');
-        } else {
-            $('#item-details').html(item_data);
-            $('#col_right .col_header span.header_text').text(item_type + ' details');
-        }
-
-        current_item
-            .removeClass('processing')
-            .addClass('active');
-
-    }).fail(function(xhr) {
-        if (console) {
-            console.log('Error fetching task', item_id, 'from', item_url);
-            console.log('XHR:', xhr);
-        }
-
-        current_item.removeClass('processing');
-        statusBarSet('error', 'Failed to open ' + item_type, 'pi-warning');
-
-        if (xhr.status) {
-            $('#item-details').html(xhr.responseText);
-        } else {
-            $('#item-details').html('<p class="text-danger">Opening ' + item_type + ' failed. There possibly was ' +
-            'an error connecting to the server. Please check your network connection and ' +
-            'try again.</p>');
-        }
-    });
-
-    // Determine whether we should push the new state or not.
-    pushState = (typeof pushState !== 'undefined') ? pushState : true;
-    if (!pushState) return;
-
-    // Push the correct URL onto the history.
-    var push_state = {itemId: item_id, itemType: item_type};
-
-    window.history.pushState(
-            push_state,
-            item_type + ': ' + item_id,
-            push_url
-    );
-}
-
-// Fine if project_url is undefined, but that requires ProjectUtils.projectUrl().
-function job_open(job_id, project_url)
-{
-    item_open(job_id, 'job', true, project_url);
-}
-function task_open(task_id, project_url)
-{
-    item_open(task_id, 'task', true, project_url);
-}
-
-
-window.onpopstate = function(event)
-{
-    var state = event.state;
-
-    item_open(state.itemId, state.itemType, false);
-}
-
-
-function loadActivities(url)
-{
-    return $.get(url)
-  .done(function(data) {
-    if(console) console.log('Activities loaded OK');
-    $('#activities').html(data);
-  })
-  .fail(function(xhr) {
-      if (console) {
-          console.log('Error fetching activities');
-          console.log('XHR:', xhr);
-      }
-
-        statusBarSet('error', 'Opening activity log failed.', 'pi-warning');
-
-      if (xhr.status) {
-          $('#activities').html(xhr.responseText);
-      } else {
-          $('#activities').html('<p class="text-danger">Opening activity log failed. There possibly was ' +
-          'an error connecting to the server. Please check your network connection and ' +
-          'try again.</p>');
-      }
-  });
-}
-
-function loadTasks(url) {
-    return $.get(url)
-    .done(function(data) {
-        if(console) console.log('Tasks loaded OK\n' + url);
-        $('#tasks').html(data);
-        setupJsTaskLinkClickHandlers();
-    })
-}
-
-function setupJsTaskLinkClickHandlers() {
-    $("a.task-link[data-task-id]")
-    .off('click')  // clean up previous click handlers, before adding another one.
-    .click(function(e) {
-        e.preventDefault();
-        var task_id = e.delegateTarget.dataset.taskId;
-        var project_url = e.delegateTarget.dataset.projectUrl;  // fine if undefined
-        task_open(task_id, project_url);
-    });
-}
-
-function setupJsJobLinkClickHandlers() {
-    $("a.job-link[data-job-id]")
-    .off('click')  // clean up previous click handlers, before adding another one.
-    .click(function(e) {
-        e.preventDefault();
-        // delegateTarget is the thing the event hander was attached to,
-        // rather than the thing we clicked on.
-        var job_id = e.delegateTarget.dataset.jobId;
-        job_open(job_id);
-    });
-}
-
-$(function() {
-    setupJsJobLinkClickHandlers()
-    setupJsTaskLinkClickHandlers()
-});
-
-/**
- * Request cancellation or re-queueing of the given job ID.
- */
-function setJobStatus(job_id, new_status) {
-    if (typeof job_id === 'undefined' || typeof new_status === 'undefined') {
-        if (console) console.log("setJobStatus(" + job_id + ", " + new_status + ") called");
-        return;
-    }
-
-    return $.post('/flamenco/jobs/' + job_id + '/set-status', {status: new_status})
-    .done(function(data) {
-        if(console) console.log('Job set-status request OK');
-        // Reload the entire page, since both the view-embed and the job list need refreshing.
-        location.reload(true);
-    })
-    .fail(function(xhr) {
-        if (console) {
-            console.log('Error setting job status');
-            console.log('XHR:', xhr);
-        }
-
-        statusBarSet('error', 'Error requesting job status change', 'pi-error');
-
-        var show_html;
-        if (xhr.status) {
-            show_html = xhr.responseText;
-        } else {
-            show_html = $('<p>').addClass('text-danger').text(
-              'Setting job status failed. There possibly was an error connecting to the server. ' +
-              'Please check your network connection and try again.');
-        }
-        $('.job #item-action-panel .action-result-panel').html(show_html);
-    });
-}
-
-/**
- * Request cancellation or re-queueing of the given task ID.
- */
-function setTaskStatus(task_id, new_status) {
-    if (typeof task_id === 'undefined' || typeof new_status === 'undefined') {
-        if (console) console.log("setTaskStatus(" + task_id + ", " + new_status + ") called");
-        return;
-    }
-
-    project_url = ProjectUtils.projectUrl();
-    return $.post('/flamenco/' + project_url + '/tasks/' + task_id + '/set-status', {status: new_status})
-    .done(function(data) {
-        if(console) console.log('Job set-status request OK');
-        // Reload the entire page, since both the view-embed and the task list need refreshing.
-        location.reload(true);
-    })
-    .fail(function(xhr) {
-        if (console) {
-            console.log('Error setting task status');
-            console.log('XHR:', xhr);
-        }
-
-        statusBarSet('error', 'Error requesting task status change', 'pi-error');
-
-        var show_html;
-        if (xhr.status) {
-            show_html = xhr.responseText;
-        } else {
-            show_html = $('<p>').addClass('text-danger').text(
-              'Setting task status failed. There possibly was an error connecting to the server. ' +
-              'Please check your network connection and try again.');
-        }
-        $('.task #task-action-panel .action-result-panel').html(show_html);
-    });
-}
-
-/* Get the task log and populate the container */
-function getTaskLog(url, container){
-    if (typeof url === 'undefined' || typeof container === 'undefined') {
-        if (console) console.log("getTaskLog(" + url + ", " + container + ") called");
-        return;
-    }
-
-    var log_height = $('#col_main-overlay-content').height() - $('.flamenco-box.task').offset().top - $('.flamenco-box.task').height() - 100;
-
-    $.get(url)
-        .done(function(data) {
-            if(console) console.log('Task log loaded OK\n' + url);
-            $(container).html(data);
-
-            var container_content = $(container).children('.item-log-content');
-            $(container_content)
-                .height(log_height)
-                .scrollTop($(container_content).prop('scrollHeight'));
-        })
-        .fail(function(xhr) {
-                if (console) {
-                        console.log('Error fetching task log');
-                        console.log('XHR:', xhr);
-                }
-
-                    statusBarSet('error', 'Opening task log failed.', 'pi-warning');
-
-                if (xhr.status) {
-                        $(container).html(xhr.responseText);
-                } else {
-                        $(container).html('<p class="text-danger">Opening task log failed. There possibly was ' +
-                        'an error connecting to the server. Please check your network connection and ' +
-                        'try again.</p>');
-                }
-        });
-}
diff --git a/packages/flamenco/src/styles/_app_base.sass b/packages/flamenco/src/styles/_app_base.sass
deleted file mode 100644
index d6f7ca5c0a16bc2ec9a5ff8f25e1a8de6b9493af..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_app_base.sass
+++ /dev/null
@@ -1,404 +0,0 @@
-body
-	position: absolute // allow columns/errors to fill the whole page
-	top: 0
-	left: 0
-	right: 0
-	bottom: 0
-	background-color: $color-background-light
-
-	&[data-context="dashboard"]
-		nav.sidebar .navbar-item.flamenco
-			+sidebar-button-active
-	&[data-context="task"]
-		nav.sidebar .navbar-item.tasks
-			+sidebar-button-active
-	&[data-context="job"]
-		nav.sidebar .navbar-item.jobs
-			+sidebar-button-active
-		#col_main .col_header
-			box-shadow: none
-
-nav.sidebar
-	a.navbar-item
-		&.tasks, &.jobs
-			text-transform: initial
-			font-size: .85em
-
-.input-group
-	width: 100%
-	display: flex
-	align-items: center
-
-	label
-		padding-right: 10px
-		min-width: 80px
-		white-space: nowrap
-
-	&.select_multiple
-		margin-bottom: 10px
-
-.input-group
-	input, textarea, select
-		margin-top: 10px
-		margin-bottom: 10px
-		width: 100%
-
-	button
-		&#item-save
-			+button($color-success, 3px)
-
-.btn
-	+button($color-text-dark-primary, 3px, false)
-
-	&.dropdown-toggle
-		padding-right: 10px
-.btn-danger
-	+button($color-danger, 3px, false)
-.btn-success
-	+button($color-success, 3px, false)
-
-/* Flamenco specific table tweaks */
-#col_main-overlay
-	position: absolute
-	z-index: 2
-	top: 0
-	left: 0
-	right: 0
-	bottom: 0
-	color: $color-text-dark-secondary
-	background-color: $color-background
-	opacity: 0
-	visibility: hidden
-	overflow: auto
-
-	&.active
-		opacity: 1
-		visibility: visible
-
-	#col_main-overlay-close
-		position: absolute
-		z-index: 2
-		top: 0
-		right: 0
-		padding: 10px
-
-		&:hover
-			color: $color-primary
-			cursor: pointer
-
-.item-list
-	font-size: .9em
-	overflow-x: auto
-
-	.table
-		background-color: white
-	.table-row:hover
-		background-color: $color-background-light
-
-	.table-cell
-		&.item-status
-			width: 5px
-			height: 100%
-			border-bottom: none
-
-	.table-head
-		.table-cell
-			text-align: center
-
-			&.highlight .collapser
-				color: $color-primary-dark
-
-			&.item-status
-				min-width: 60px
-
-			&.item-name
-				text-align: left
-				padding-left: 5px
-
-			span.collapser
-				cursor: pointer
-				width: 100%
-				display: inline-block
-				padding: 5px
-
-			&:hover
-				span.collapser
-					color: $color-primary
-
-	.table-body
-		.table-row
-			@include status-color-property(background-color, ' .item-status a', 'dark')
-			@include status-color-property(border-color, ' .item-status a', 'light')
-
-		.table-cell
-			text-align: center
-			font:
-				family: monospace
-				size: .95em
-			line-height: 1.2em
-
-			&.active
-				background-color: $color-background
-
-			&.highlight
-				background-color: rgba(white, .5)
-
-				&.task-type a:before
-					transform: translate(-50%, -50%) scale(1.2)
-
-			&.item-name
-				text-align: left
-				position: relative
-				height: 100%
-				a
-					display: flex
-					padding: 3px 10px
-					color: $color-text-dark-primary
-
-					span
-						margin: auto 0
-						line-height: 1.1em
-
-			&.item-type
-				text-align: left
-				a
-					+text-overflow-ellipsis
-					color: $color-text-dark-primary
-
-			&.item-priority a
-				color: $color-text-dark-secondary
-
-			&.item-status
-				a
-					display: inline-block
-					color: white
-					font-size: .75em
-					text-transform: uppercase
-					font-family: $font-body
-					padding: 1px 5px
-					border-radius: 3px
-					width: 100%
-					margin-left: 3px
-
-.item-list-header
-	a
-		color: $color-text-dark
-		+text-overflow-ellipsis
-	a.item-project
-		color: $color-text-dark-secondary
-		margin: 0 10px
-
-/* General style for activities in all places */
-.d-activity
-	font-size: .9em
-
-	$activity-highlight-color: #00cc9f
-	ul
-		cursor: default
-		padding: 5px
-		color: $color-text-dark-primary
-		list-style: none
-
-		li
-			padding: 0 10px 7px 10px
-			position: relative
-
-			span.date
-				color: darken($activity-highlight-color, 5%)
-
-			/* Left Dot */
-			&:after
-				content: ''
-				display: block
-				position: absolute
-				top: 6px
-				left: -3px
-				width: 5px
-				height: 5px
-				border-radius: 50%
-				background-color: $color-background-light
-				border: thin solid $activity-highlight-color
-				transition: all 250ms ease-in-out
-
-			/* Left Line */
-			&:before
-				content: ''
-				display: block
-				position: absolute
-				top: 10px
-				left: -1px
-				width: 1px
-				height: 100%
-				background-color: $activity-highlight-color
-				transition: all 250ms ease-in-out
-
-			&:last-child
-				&:before
-					background-color: transparent
-
-		span.actor
-			padding: 0 5px
-			color: $color-text-dark
-
-		img.actor-avatar
-			width: 16px
-			height: 16px
-			border-radius: 50%
-			margin-right: 5px
-			position: relative
-			top: -2px
-
-
-.flamenco-box
-	.item-id
-		padding: 8px
-		margin-left: 10px
-		width: 40px
-		border: thin solid transparent
-		background-color: white
-		color: $color-text-dark-secondary
-		box-shadow: none
-		border-color: $color-text-dark-hint
-
-		&:hover
-			color: $color-text-dark-primary
-			border-color: $color-text-dark-primary
-
-
-#item-details
-	overflow-x: hidden
-
-	.item-details-empty
-		display: flex
-		align-items: center
-		justify-content: center
-		width: 100%
-		height: 100%
-		color: rgba($color-text-dark-hint, .5)
-		cursor: default
-		padding: 15px 10px
-		font:
-			size: 2em
-			weight: 100
-
-#item-view-feed
-	padding: 10px
-	color: $color-text-dark-primary
-	pre
-		margin: 15px auto
-
-	#comments-container
-		margin-top: 0
-
-	#col_main
-		width: 100%
-
-#item-action-panel
-	padding: 0 10px 10px 10px
-	width: 100%
-	display: flex
-	justify-content: flex-end
-
-	.btn
-		font-size: .8em
-
-	.item-log-load
-		margin-right: auto
-
-#item-log
-	margin: 10px
-	border-radius: 3px
-	background-color: white
-	position: relative
-
-	.item-log-header
-		padding: 5px 0 4px 5px
-		color: $color-text-dark-secondary
-		box-shadow: 0 5px 15px rgba(black, .1)
-
-		.header-title
-			padding-left: 5px
-
-		.download-log
-			padding: 5px
-			font-size: .9em
-			color: $color-text-dark-secondary
-
-			&:hover
-				color: $color-primary
-
-	.item-log-content
-		position: relative
-		overflow: auto
-		width: 100%
-		cursor: default
-
-	.item-log-navigation
-		float: right
-		a.log-navigate, span.log-page
-			padding: 7px 10px 4px 10px
-			user-select: none
-			text-transform: uppercase
-			font-size: .8em
-			color: $color-text-dark
-
-		span.log-page
-			cursor: default
-			padding: 0 15px
-			color: $color-text-dark-secondary
-
-		a.log-navigate
-			text-decoration: none
-			border-bottom: 2px solid $color-text-dark-hint
-			&:hover
-				color: $color-primary
-				border-color: $color-primary
-
-			&.disabled
-				cursor: default
-				pointer-events: none
-
-			&.disabled
-				color: $color-text-dark-hint
-				border-bottom-color: rgba(black, .1)
-			&.active
-				color: $color-primary
-				border-bottom: 2px solid $color-primary
-				font-weight: bold
-
-	.item-log-loader
-		padding: 20px
-		width: 100%
-		display: flex
-		align-items: center
-		justify-content: center
-		font-size: 1.2em
-		color: $color-text-dark-hint
-
-		span
-			margin-right: 15px
-			display: inline-block
-
-.item-log-line
-	color: $color-text-dark-primary
-	font:
-		family: monospace
-		size: .8em
-	line-height: 1.2em
-	position: relative
-	margin: 0
-	padding: 0 10px 0 5px
-
-	white-space: nowrap
-	width: 100%
-
-	&:hover
-		color: black
-
-	&:first-child
-		padding-top: 5px
-
-	&.log-warning
-		color: darken($color-warning, 25%)
-	&.log-error
-		color: $color-danger
diff --git a/packages/flamenco/src/styles/_app_utils.sass b/packages/flamenco/src/styles/_app_utils.sass
deleted file mode 100644
index 59d936e5ea1e1d20fffd59864ae904e3124030cc..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_app_utils.sass
+++ /dev/null
@@ -1,609 +0,0 @@
-/* Collection of mixins that can be plugged everywhere */
-
-=clearfix
-	clear: both
-	&:after
-		// Basically same as .clearfix from bootstrap
-		clear: both
-		display: block
-		content: ' '
-
-
-@mixin button($mixin-color, $roundness, $filled: false)
-	font-family: $font-body
-	text-transform: uppercase
-	opacity: .9
-	padding:
-		left: 15px
-		right: 15px
-	border-radius: $roundness
-
-	@if $filled
-		background: linear-gradient(lighten($mixin-color, 2%), $mixin-color)
-		color: white
-		border: thin solid darken($mixin-color, 5%)
-		text-shadow: 1px 1px 0 rgba(black, .15)
-	@else
-		background-color: transparent
-		color: $mixin-color
-		border: thin solid $mixin-color
-		text-shadow: none
-
-	transition: color 350ms ease-out, border 150ms ease-in-out, opacity 150ms ease-in-out, background-color 150ms ease-in-out
-
-	&:hover
-		opacity: 1
-		cursor: pointer
-		text-decoration: none
-
-		@if $filled
-			background: linear-gradient(lighten($mixin-color, 5%), lighten($mixin-color, 5%))
-			color: white
-			border-color: lighten($mixin-color, 5%)
-		@else
-			background-color: rgba($mixin-color, .1)
-			color: $mixin-color
-			border-color: $mixin-color
-
-	&:active
-		outline: none
-		border-color: $mixin-color
-		background-color: $mixin-color
-		color: white
-
-	i
-		margin-right: 5px
-	small
-		font-size: .6em
-
-	&:disabled
-		cursor: not-allowed
-		color: $color-text-dark-secondary
-		border-color: $color-text-dark-hint
-
-		&:hover
-			@if $filled
-				background: rgba($color-text-dark-hint, .2)
-			@else
-				background-color: rgba($color-text-dark-hint, .1)
-
-		@if $filled
-			background: rgba($color-text-dark-hint, .1)
-			text-shadow: none
-
-
-@mixin overlay($from-color, $from-percentage, $to-color, $to-percentage)
-	position: absolute
-	top: 0
-	left: 0
-	right: 0
-	bottom: 0
-	background: linear-gradient(to bottom, $from-color $from-percentage, $to-color $to-percentage)
-
-
-@mixin stripes($color-light, $color-dark, $deg, $size)
-	background-size: $size $size
-	background-image: linear-gradient($deg, $color-light 25%, $color-dark 25%, $color-dark 50%, $color-light 50%, $color-light 75%, $color-dark 75%, $color-dark)
-
-=stripes-animate
-	animation:
-		name: background-slide
-		duration: 1s
-		delay: 0s
-		// fill-mode: forwards
-		iteration-count: infinite
-		timing-function: linear
-
-=container-box
-	position: relative
-	background-color: white
-	border-radius: 3px
-	box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px
-
-=text-overflow-ellipsis
-	overflow: hidden
-	white-space: nowrap
-	text-overflow: ellipsis
-
-=position-center-translate
-	position: absolute
-	top: 50%
-	left: 50%
-	transform: translate(-50%, -50%)
-
-=input-generic
-	color: $color-text-dark
-	box-shadow: none
-	font-family: $font-body
-	border-radius: 3px
-	border-color: $color-background-dark
-	background-color: $color-background-light
-
-	&:focus
-		border-color: $color-info
-		box-shadow: none
-
-=label-generic
-	color: $color-text-dark
-	font-family: $font-body
-	font-weight: 300
-
-@mixin badge($mixin-color, $roundness)
-	padding:
-		left: 10px
-		right: 10px
-
-	text-transform: uppercase
-
-	color: $mixin-color
-	border: 1px solid $mixin-color
-	border-radius: $roundness
-
-	i
-		margin-right: 10px
-
-/* Smallest, like phones on portrait.
- **  Menu is collapsed, columns stack, no brand */
-=media-xs
-	@media (max-width: #{$screen-tablet - 1px})
-		@content
-
-/* Small but wide: phablets, iPads
- **  Menu is collapsed, columns stack, no brand */
-=media-sm
-	@media (min-width: #{$screen-tablet}) and (max-width: #{$screen-desktop - 1px})
-		@content
-
-/* Tablets portrait.
- **  Menu is expanded, but columns stack, brand is shown */
-=media-md
-	@media (min-width: #{$screen-desktop})
-		@content
-
-=media-lg
-	@media (min-width: #{$screen-lg-desktop})
-		@content
-
-=media-print
-	@media print
-		@content
-
-=spin
-	animation:
-		name: spin-once
-		duration: 1s
-		delay: 0s
-		fill-mode: forwards
-		iteration-count: infinite
-		timing-function: linear
-
-=spin-once
-	+spin
-	animation:
-		iteration-count: 1
-
-=pulse
-	animation:
-		name: pulse
-		duration: 1s
-		delay: 0s
-		fill-mode: forwards
-		iteration-count: infinite
-
-=pulse-75
-	animation:
-		name: pulse-75
-		duration: 1s
-		delay: 0
-		fill-mode: forwards
-		iteration-count: infinite
-
-=animation-wiggle
-	animation:
-		name: wiggle
-		duration: 1s
-		delay: 0s
-		fill-mode: forwards
-		iteration-count: infinite
-		timing-function: linear
-
-.spin
-	+spin
-	&:before, &:after
-		+spin
-
-@keyframes spin-once
-	from
-		transform: rotate(0deg)
-	to
-		transform: rotate(360deg)
-
-@keyframes wiggle
-	0
-		transform: rotate(0deg)
-	25%
-		transform: rotate(25deg)
-	75%
-		transform: rotate(-25deg)
-	100%
-		transform: rotate(0deg)
-
-@keyframes pulse
-	0
-		opacity: 1
-	50%
-		opacity: 0
-	100%
-		opacity: 1
-
-@keyframes pulse-75
-	0
-		opacity: 1
-	50%
-		opacity: .8
-	100%
-		opacity: 1
-
-@keyframes background-fill-left-right
-	from
-		background-position: right bottom
-	to
-		background-position: left bottom
-
-@keyframes grow-bounce-in
-	0
-		transform: scale(0.8)
-		opacity: 0
-	50%
-		transform: scale(1.05)
-		opacity: 1
-	85%
-		transform: scale(1.0)
-	90%
-		transform: scale(0.99)
-	100%
-		transform: scale(1.0)
-
-@keyframes grow-bounce-out
-	0
-		transform: scale(1.0)
-		opacity: 1
-	100%
-		transform: scale(0.9)
-		opacity: 0
-
-@keyframes background-slide
-	from
-		background-position: 0 0
-	to
-		background-position: 50px 50px
-
-@keyframes grow-bounce
-	0
-		transform: scale(1.0)
-		opacity: 1
-	50%
-		transform: scale(1.01)
-		opacity: .9
-	85%
-		transform: scale(1.0)
-	90%
-		transform: scale(0.99)
-		opacity: 1
-	100%
-		transform: scale(1.0)
-
-@keyframes grow-bounce-heartbeat
-	0
-		transform: scale(1.0)
-	85%
-		transform: scale(1.0)
-	90%
-		transform: scale(1.15)
-	94%
-		transform: scale(0.9)
-	96%
-		transform: scale(1.05)
-	100%
-		transform: scale(1.0)
-
-=list-bullets
-	ul
-		padding-left: 20px
-		list-style: none
-
-		li:before
-			content: '·'
-			font-weight: 400
-			position: relative
-			left: -10px
-
-
-=node-details-description
-	padding: 15px 0 25px 0
-	color: darken($color-text-dark, 5%)
-	font:
-		family: $font-body
-		weight: 300
-		size: 1.2em
-
-	word-break: break-word
-	clear: both
-	+clearfix
-
-	+media-xs
-		font-size: 1.1em
-
-	strong, b
-		font-weight: 400
-
-	a:not([class])
-		color: $color-text-dark-primary
-		text-decoration: underline
-
-		&:hover
-			color: $color-primary
-
-	p
-		padding:
-			left: 20px
-			right: 20px
-		margin-bottom: 20px
-		line-height: 1.5em
-		word-wrap: break-word
-
-	h1, h2, h3, h4, h5, h6
-		padding:
-			top: 20px
-			left: 20px
-			right: 20px
-
-	blockquote
-		background-color: lighten($color-background, 5%)
-		text-shadow: 1px 1px 0 rgba(white, .2)
-		margin:
-			left: 20px
-			right: 20px
-			bottom: 30px
-		font-size: 1em
-
-		p
-			padding: 0
-			margin: 0
-	ul li blockquote
-		margin:
-			left: 0
-			top: 15px
-
-	img,
-	p img,
-	ul li img
-		max-width: 100%
-		padding:
-			top: 25px
-			// bottom: 10px
-			bottom: 25px
-
-	h2
-		margin-bottom: 15px
-
-		+media-xs
-			font-size: 1.5em
-
-	/* e.g. YouTube embed */
-	iframe
-		margin-top: 20px
-		width: 100%
-		max-width: 100%
-		height: auto
-		min-height: 354px
-
-	+media-sm
-		iframe
-			min-height: 314px
-	+media-xs
-		iframe
-			min-height: 314px
-
-	iframe[src^="https://w.soundcloud"]
-		min-height: auto
-
-	+list-bullets
-
-	ul
-		padding-left: 40px
-		margin-bottom: 25px
-
-		li
-			margin-bottom: 7px
-			img
-				display: block
-				padding:
-					top: 25px
-					bottom: 10px
-
-			ul, ul li ul
-				margin-top: 15px
-				padding-left: 20px
-
-	code, kbd, pre, samp
-		font-size: 1.3rem
-
-	pre
-		background-color: lighten($color-background, 5%)
-		border-color: $color-background
-		border-radius: 3px
-		color: $color-text
-
-		/* when <pre> is outside <p> */
-		margin:
-			left: 20px
-			right: 20px
-	pre+p
-		margin-top: 30px
-
-	p+pre
-		/* a <pre> right after a <p> usually are related, remove some spacing */
-		margin-top: -10px
-
-	p
-		pre
-			/* We already have spacing on the sides inside <p> */
-			margin:
-				left: 0
-				right: 0
-
-
-=markdown-preview-container
-	border:
-		top: 1px solid $color-background
-		bottom: 1px solid $color-background
-	position: relative
-	margin: 40px auto 25px auto
-	padding: 10px 10px 25px 10px
-	color: $color-text-dark-primary
-	cursor: default
-	transition: all 150ms ease-in-out
-
-	+node-details-description
-
-	// Funny, normalize.css doesn't normalize when it's outside
-	h1
-		font-size: 2.8em
-	h2
-		margin-bottom: 15px
-
-
-=ribbon
-	background-color: $color-success
-	cursor: default
-	overflow: hidden
-	white-space: nowrap
-	position: absolute
-	right: -40px
-	top: 10px
-	-webkit-transform: rotate(45deg)
-	-moz-transform: rotate(45deg)
-	-ms-transform: rotate(45deg)
-	-o-transform: rotate(45deg)
-	transform: rotate(45deg)
-
-	span
-		border: thin dashed rgba(white, .5)
-		color: white
-		display: block
-		font-size: 70%
-		margin: 1px 0
-		padding: 3px 50px
-		text:
-			align: center
-			transform: uppercase
-
-@mixin text-background($text-color, $background-color, $roundness, $padding)
-	border-radius: $roundness
-	padding: $padding
-	background-color: rgba($background-color, .9)
-	box-shadow: 0.5em 0 0 rgba($background-color, .9),-0.5em 0 0 rgba($background-color, .9)
-	box-decoration-break: clone
-	color: $text-color
-
-=list-meta
-	margin: 0
-	padding: 0
-	list-style: none
-	color: $color-text-dark-primary
-
-	li
-		display: inline-block
-		padding-left: 15px
-		position: relative
-
-		&:before
-			content: '·'
-			position: relative
-			top: 1px
-			left: -7px
-			color: $color-text-dark-secondary
-
-		&:first-child
-			padding-left: 0
-
-			&:before
-				content: ''
-	a
-		color: $color-text-dark-secondary
-		&:hover
-			color: $color-primary
-
-/* Bootstrap's img-responsive class */
-=img-responsive
-	display: block
-	max-width: 100%
-	height: auto
-
-/* Set the color for a specified property
- * 1: $property: e.g. background-color
- * 2: $where: ':before', ' .class-name', etc.
- * 3: $variation: 'light', 'dark', or empty
- * e.g. @include status-color-property(background-color, ':before', 'light')
- */
-@mixin status-color-property($property, $where: false, $variation: false)
-
-	@if not ($where)
-		$where: ''
-
-	&.status
-		&-queued#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-queued-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-queued-dark
-			@else
-				#{$property}: $color-status-queued
-		&-canceled#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-canceled-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-canceled-dark
-			@else
-				#{$property}: $color-status-canceled
-		&-failed#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-failed-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-failed-dark
-			@else
-				#{$property}: $color-status-failed
-		&-claimed-by-manager#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-claimedbymanager-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-claimedbymanager-dark
-			@else
-				#{$property}: $color-status-claimedbymanager
-		&-processing#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-processing-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-processing-dark
-			@else
-				#{$property}: $color-status-processing
-		&-completed#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-completed-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-completed-dark
-			@else
-				#{$property}: $color-status-completed
-		&-active#{$where}
-			@if ($variation == 'light')
-				#{$property}: $color-status-active-light
-			@else if ($variation == 'dark')
-				#{$property}: $color-status-active-dark
-			@else
-				#{$property}: $color-status-active
-
-=sidebar-button-active
-	background-color: $color-background-nav
-	box-shadow: inset 2px 0 0 $color-primary
-	color: white
diff --git a/packages/flamenco/src/styles/_config.sass b/packages/flamenco/src/styles/_config.sass
deleted file mode 100644
index a7727374f6b44f134e2089217d45582e5628180e..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_config.sass
+++ /dev/null
@@ -1,92 +0,0 @@
-$color-background: #eaebec
-$color-background-light: lighten($color-background, 5%)
-$color-background-dark: darken($color-background, 5%)
-$color-background-nav: hsl(hue($color-background), 20%, 25%)
-
-$color-background-nav-light: hsl(hue($color-background), 20%, 35%)
-$color-background-nav-dark: hsl(hue($color-background), 20%, 15%)
-
-$color-background-active: #dff5f6  // background colour for active items.
-
-$font-body: 'Roboto'
-$font-headings: 'Lato'
-$font-size: 14px
-
-$color-text: #4d4e53
-
-$color-text-dark: $color-text
-$color-text-dark-primary: #646469 // rgba($color-text, .87)
-$color-text-dark-secondary: #9E9FA2 // rgba($color-text, .54)
-$color-text-dark-hint: #BBBBBD // rgba($color-text, .38)
-
-$color-text-light: white
-$color-text-light-primary: rgba($color-text-light, .87)
-$color-text-light-secondary: rgba($color-text-light, .54)
-$color-text-light-hint: rgba($color-text-light, .38)
-
-$color-primary: #68B3C8
-$color-primary-light: hsl(hue($color-primary), 30%, 90%)
-$color-primary-dark: hsl(hue($color-primary), 80%, 30%)
-$color-primary-accent:  hsl(hue($color-primary), 100%, 50%)
-
-$color-secondary: #f42942
-$color-secondary-light: hsl(hue($color-secondary), 30%, 90%)
-$color-secondary-dark: hsl(hue($color-secondary), 80%, 40%)
-$color-secondary-accent: hsl(hue($color-secondary), 100%, 50%)
-
-$color-warning: #F3BB45 !default
-$color-info: #68B3C8 !default
-$color-success: #27AE60 !default
-$color-danger: #EB5E28 !default
-
-/* Borrowed from dillo.space :) */
-$color_upvote: #ff8b60
-$color_downvote: #74a4ff
-
-/* Label Status */
-$color-status-queued: #b6bbaa // brownish
-$color-status-queued-light: hsl(hue($color-status-queued), 40%, 75%)
-$color-status-queued-dark: hsl(hue($color-status-queued), 28%, 48%)
-$color-status-canceled: #999 // grayish
-$color-status-canceled-light: lighten($color-status-canceled, 10%)
-$color-status-canceled-dark: darken($color-status-canceled, 10%)
-$color-status-failed: #ff8080 // redish
-$color-status-failed-light: hsl(hue($color-status-failed), 100%, 85%)
-$color-status-failed-dark: hsl(hue($color-status-failed), 100%, 65%)
-$color-status-claimedbymanager: #d1c5d3 // subtlepurpleish
-$color-status-claimedbymanager-light: hsl(hue($color-status-claimedbymanager), 100%, 55%)
-$color-status-claimedbymanager-dark: hsl(hue($color-status-claimedbymanager), 100%, 45%)
-$color-status-processing: #ffbe00 // orangeish
-$color-status-processing-light: hsl(hue($color-status-processing), 100%, 55%)
-$color-status-processing-dark: hsl(hue($color-status-processing), 100%, 45%)
-$color-status-active: #00ceff // blueish
-$color-status-active-light: hsl(hue($color-status-active), 100%, 75%)
-$color-status-active-dark: hsl(hue($color-status-active), 100%, 40%)
-$color-status-completed: #bbe151 // greenish
-$color-status-completed-light: hsl(hue($color-status-completed), 100%, 70%)
-$color-status-completed-dark: hsl(hue($color-status-completed), 100%, 38%)
-
-$color-status-active: #00ceff // #E6F3FD
-$color-status-updated: #e7f5d3
-
-/* Mobile Stuff */
-$screen-xs: 480px !default
-$screen-xs-min: $screen-xs
-$screen-phone: $screen-xs-min
-$screen-sm: 768px !default
-$screen-sm-min: $screen-sm
-$screen-tablet: $screen-sm-min
-$screen-md: 1100px !default
-$screen-md-min: $screen-md
-$screen-desktop: $screen-md-min
-$screen-lg: 1270px !default
-$screen-lg-min: $screen-lg
-$screen-lg-desktop: $screen-lg-min
-$screen-xs-max: $screen-sm-min - 1
-$screen-sm-max: $screen-md-min - 1
-$screen-md-max: $screen-lg-min - 1
-
-
-$sidebar-width: 50px
-
-$jobs-list-thumbnail-width: 100px
diff --git a/packages/flamenco/src/styles/_dashboard.sass b/packages/flamenco/src/styles/_dashboard.sass
deleted file mode 100644
index 1e0b83a9c04692613fd3960fa4f024b2059d06fd..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_dashboard.sass
+++ /dev/null
@@ -1,105 +0,0 @@
-.d-title
-	padding: 0 15px
-	text-align: center
-
-.d-welcome
-	height: 300px
-	margin: 0 auto
-	width: 100%
-	display: flex
-	flex-direction: column
-	align-items: center
-	justify-content: center
-	border-bottom: thin solid $color-background-dark
-
-	+media-xs
-		width: auto
-
-	.welcome-logo
-		font-size: 5em
-		color: $color-primary
-		background-color: white
-		text-align: center
-		border-radius: 50%
-		margin: 15px auto
-		box-shadow: 0 0 65px rgba(black, .1)
-
-		i
-			display: block
-			margin: 15px
-
-	.welcome-title
-		font-size: 1.8em
-		font-weight: lighter
-
-	.welcome-text
-		padding: 10px
-		color: $color-text-dark-primary
-
-.d-projects
-	display: flex
-	flex-wrap: wrap
-	justify-content: space-between
-	margin: 15px auto
-	padding-left: 15px
-	padding-right: 15px
-
-	+media-xs
-		display: block
-		width: 100%
-
-	.d-projects-item
-		display: flex
-		flex-direction: column
-		width: 32%
-		margin-bottom: 15px
-		+container-box
-
-		+media-sm
-			width: 50%
-		+media-xs
-			width: 100%
-
-		&:hover
-			img
-				opacity: .9
-
-	.d-projects-item-title
-		font-size: 1.2em
-		font-weight: lighter
-		padding: 6px 10px
-
-	.d-projects-item-stats
-		.progress
-			border-radius: 0
-			border-bottom-left-radius: 3px
-			border-bottom-right-radius: 3px
-			margin: 0
-			height: 4px
-
-	.d-projects-item-header
-		background-color: $color-primary
-		img
-			width: 100%
-			border-top-left-radius: 3px
-			border-top-right-radius: 3px
-			transition: opacity 150ms ease-in-out
-
-/* Dashboard specific styles */
-.dashboard
-	.d-stats
-		padding: 0 10px
-
-		.d-stats-card
-			+container-box
-			padding: 10px
-
-			.progress
-				margin-bottom: 0
-			h4
-				margin-top: 0
-
-	.d-activity
-		margin: 0 20px 15px
-		a
-			color: $color-text-dark-primary
diff --git a/packages/flamenco/src/styles/_errors.sass b/packages/flamenco/src/styles/_errors.sass
deleted file mode 100644
index 8f669638e66bd6483e06bc4877dfa4bbdc2acf23..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_errors.sass
+++ /dev/null
@@ -1,110 +0,0 @@
-#error_container
-	display: flex
-	justify-content: center
-	align-items: center
-	position: absolute
-	top: 0
-	left: 0
-	right: 0
-	bottom: 0
-	background-color: darken($color-background-nav, 3%)
-
-	&.standalone
-		width: 100%
-		height: 100%
-		position: fixed
-
-		#error_box
-			.error-lead
-				padding: 10px 10px
-
-				p
-					display: block
-
-				&.extra
-					padding-top: 0
-
-
-	#error_box
-		min-width: 60%
-		max-width: 500px
-		text-align: center
-		display: flex
-		justify-content: center
-		align-items: center
-		flex-direction: column
-
-		+container-box
-
-		box-shadow: 0 0 15px rgba(black, .2)
-		padding: 0
-		background-color: $color-background-nav
-
-		.error-top-container
-			position: relative
-			width: 100%
-			background-color: $color-background-nav
-			background: repeating-linear-gradient(-45deg, lighten($color-background-nav, 2%), lighten($color-background-nav, 2%) 10px, $color-background-nav 10px, $color-background-nav 20px)
-
-		.error-title
-			padding: 25px 0 10px 0
-			color: white
-			font:
-				size: 2em
-				weight: 300
-
-		.error-lead
-			width: 100%
-			padding: 0 25px 15px 15px
-			line-height: 1.6em
-
-			color: $color-text-light-primary
-			font:
-				family: $font-body
-				weight: 300
-
-			a
-				text-decoration: none
-				&:hover
-					text-decoration: underline
-
-			&.extra
-				padding: 25px 0
-				font-size: .9em
-				color: $color-text-light-secondary
-				a
-					color: white
-
-
-		hr
-			margin: 0 0
-			width: 100%
-			border: none
-			height: 3px
-			background-color: lighten($color-background-nav, 5%)
-
-		.buttons
-			margin: 0 15px 25px 0
-
-			a
-				font-size: 1.2em
-				margin: 0 15px
-				&.sign-up
-					+button($color-primary, 999em, true)
-				&.sign-in
-					+button($color-background, 999em)
-					border-color: transparent
-
-
-#node-overlay
-	#error_container
-		@include overlay(rgba($color-background-nav, .8), 0%, transparent, 60%)
-
-		#error_box
-			top: 50px
-			position: absolute
-			left: 50%
-			transform: translateX(-50%)
-			border-radius: 3px
-			box-shadow: 0 0 100px rgba(black, .85)
-			overflow: hidden
diff --git a/packages/flamenco/src/styles/_jobs.sass b/packages/flamenco/src/styles/_jobs.sass
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_jobs.sass
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/packages/flamenco/src/styles/_tasks.sass b/packages/flamenco/src/styles/_tasks.sass
deleted file mode 100644
index 5b78ad40fba1fa1d0a22b3d46bd51d621e62910d..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/_tasks.sass
+++ /dev/null
@@ -1,196 +0,0 @@
-.flamenco-box
-	margin: 10px
-	padding: 10px
-	+container-box
-
-	&.with-status
-		border-top: thick solid $color-background-dark
-		@include status-color-property(border-top-color, '', 'dark')
-
-	.item-name
-		font-size: 1.6em
-		margin: 0
-
-		+text-overflow-ellipsis
-
-	span.item-name
-		padding-left: 5px
-		margin-top: 0
-		color: $color-text-dark-secondary
-
-	.item-description
-		padding: 10px 5px
-		color: $color-text-dark-primary
-
-	.dropdown button
-		height: 38px
-		margin-left: 10px
-
-	.dropdown-menu
-		top: 36px
-		left: initial
-		right: 0
-		padding-top: 0
-		padding-bottom: 0
-		border: thin solid $color-background
-		box-shadow: 1px 1px 2px rgba(black, .1), 0 5px 25px rgba(black, .1)
-
-		li
-			display: flex
-			height: 100%
-			width: 100%
-			padding: 0
-			margin: 0
-
-			&.divider
-				height: 2px
-
-			&.item-delete a:hover
-				color: $color-danger
-
-			a
-				padding: 10px 15px 10px 12px
-				flex: 1
-				height: 100%
-				color: $color-text-dark-primary
-				i
-					position: relative
-					top: -1px
-					left: -4px
-					font-size: .9em
-
-	.table
-		&.item-properties
-			margin-top: 10px
-			.table-body
-				text-shadow: 1px 1px 0 white
-
-				.table-row
-					&:hover
-						background-color: $color-background-light
-					.table-cell
-						padding: 0 10px
-						vertical-align: bottom
-						color: $color-text-dark-primary
-						word-break: break-word
-						line-height: 1.3em
-						padding: 3px 10px
-						font-family: monospace
-						font-size: .9em
-
-						@include status-color-property(color, '', 'dark')
-
-						&:first-child
-							width: 120px
-							max-width: 200px
-							text-align: right
-							padding-right: 10px
-							vertical-align: top
-							color: black
-
-					&:last-child .table-cell
-						border-bottom: none
-
-
-					&.properties-assignees
-						.table-cell span
-							display: block
-					&.properties-status
-						cursor: help
-
-		&.item-job-settings
-			margin-top: 15px
-
-
-.flamenco-box+.flamenco-box
-	margin-top: 0
-
-#task-list
-	overflow-x: hidden
-
-#task-add
-	margin-left: auto
-	font-size: .85em
-	color: $color-primary
-
-.status-indicator
-	background-color: white
-	height: 16px
-	width: 16px
-	min-width: 16px
-	margin-left: 10px
-	border-radius: 50%
-	transition: all 100ms ease-in-out
-
-.task-list-item
-	color: $color-text-dark
-	font-size: .8em
-	font-family: monospace
-
-	&:hover
-		text-decoration: none
-		color: $color-text-dark-primary
-		background-color: $color-background-light
-
-		.status-indicator
-			transform: scale(1.2)
-
-	&.active
-		text-decoration: none
-		background-color: $color-background-active
-		box-shadow: inset 5px 0 0 $color-primary
-		text-shadow: 1px 1px 0 white
-
-		.status-indicator
-			transform: scale(1.2)
-
-	.status, .type
-		display: inline-block
-		margin-right: 10px
-		text-transform: uppercase
-		font-size: .8em
-		text-decoration: none
-
-	.type
-		margin-left: auto
-		color: $color-text-dark-secondary
-		+text-overflow-ellipsis
-
-	.name
-		padding: 2px 10px
-		+text-overflow-ellipsis
-
-	.shotname
-		color: $color-text-dark-secondary
-		margin-left: 10px
-		padding-right: 10px
-		position: relative
-		+text-overflow-ellipsis
-		&:after
-			position: absolute
-			width: 2px
-			height: 2px
-			right: 0
-			border-radius: 50%
-			bottom: 9px
-			display: block
-			content: ''
-			border: thin solid $color-text-dark-hint
-
-	@include status-color-property(background-color, ' .status-indicator', '')
-
-option.invalid_task
-	color: $color-danger
-	background-color: hsl(hue($color-danger), 80%, 90%)
-
-.task-list-header
-	a
-		color: $color-text-dark
-		+text-overflow-ellipsis
-	a.task-project
-		color: $color-text-dark-secondary
-		margin-left: 10px
-
-.input-group-separator
-	margin: 10px 0
-	border-top: thin solid $color-background
diff --git a/packages/flamenco/src/styles/main.sass b/packages/flamenco/src/styles/main.sass
deleted file mode 100644
index 74f39892c953c9fd51304673e11d56cbb3e3db34..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/main.sass
+++ /dev/null
@@ -1,8 +0,0 @@
-@import _config
-@import _app_utils
-@import _app_base
-
-@import _tasks
-@import _jobs
-@import _dashboard
-@import _errors
diff --git a/packages/flamenco/src/styles/plugins/js_select2.sass b/packages/flamenco/src/styles/plugins/js_select2.sass
deleted file mode 100644
index 12b8f93caa3a47a19032afa1367240a0fca3cf75..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/styles/plugins/js_select2.sass
+++ /dev/null
@@ -1,288 +0,0 @@
-@import ../config
-.select2-container
-	width: 100% !important
-	box-sizing: border-box
-	display: inline-block
-	margin: 0
-	position: relative
-	vertical-align: middle
-	.select2-selection--single
-		box-sizing: border-box
-		cursor: pointer
-		display: block
-		height: 28px
-		user-select: none
-		-webkit-user-select: none
-		.select2-selection__rendered
-			display: block
-			padding-left: 8px
-			padding-right: 20px
-			overflow: hidden
-			text-overflow: ellipsis
-			white-space: nowrap
-		.select2-selection__clear
-			position: relative
-	.select2-selection--multiple
-		box-sizing: border-box
-		cursor: pointer
-		display: block
-		min-height: 40px
-		user-select: none
-		-webkit-user-select: none
-		.select2-selection__rendered
-			display: inline-block
-			overflow: hidden
-			padding-left: 8px
-			text-overflow: ellipsis
-			white-space: nowrap
-	.select2-search--inline
-		float: left
-		.select2-search__field
-			box-sizing: border-box
-			border: none
-			font-size: 100%
-			margin-top: 5px
-			padding: 0
-			&::-webkit-search-cancel-button
-				-webkit-appearance: none
-
-.select2-dropdown
-	background-color: $color-background-light
-	border: 1px solid $color-background-dark
-	box-shadow: 0 3px 15px rgba(black, .2)
-	box-sizing: border-box
-	display: block
-	position: absolute
-	left: -100000px
-	width: 100%
-	z-index: 1051
-	border-bottom-left-radius: 3px
-	border-bottom-right-radius: 3px
-
-.select2-results
-	display: block
-
-.select2-results__options
-	list-style: none
-	margin: 0
-	padding: 0
-
-.select2-results__option
-	padding: 8px 10px
-	user-select: none
-	-webkit-user-select: none
-	&[aria-selected]
-		cursor: pointer
-
-.select2-container--open
-	.select2-dropdown
-		left: 0
-	.select2-dropdown--above
-		border-bottom: none
-		border-bottom-left-radius: 0
-		border-bottom-right-radius: 0
-	.select2-dropdown--below
-		border-top: none
-		border-top-left-radius: 0
-		border-top-right-radius: 0
-
-.select2-search--dropdown
-	display: block
-	padding: 4px
-	.select2-search__field
-		padding: 4px
-		width: 100%
-		box-sizing: border-box
-		&::-webkit-search-cancel-button
-			-webkit-appearance: none
-	&.select2-search--hide
-		display: none
-
-.select2-close-mask
-	border: 0
-	margin: 0
-	padding: 0
-	display: block
-	position: fixed
-	left: 0
-	top: 0
-	min-height: 100%
-	min-width: 100%
-	height: auto
-	width: auto
-	opacity: 0
-	z-index: 99
-	background-color: #fff
-	filter: alpha(opacity = 0)
-
-.select2-hidden-accessible
-	border: 0 !important
-	clip: rect(0 0 0 0) !important
-	height: 1px !important
-	margin: -1px !important
-	overflow: hidden !important
-	padding: 0 !important
-	position: absolute !important
-	width: 1px !important
-
-.select2-container--default
-	.select2-selection--single
-		border-bottom: 1px solid $color-background-dark
-		cursor: text
-		transition: all 150ms ease-in-out
-		&:hover
-			border-color: $color-text-dark-secondary
-		.select2-selection__rendered
-			color: #444
-			line-height: 28px
-		.select2-selection__clear
-			cursor: pointer
-			float: right
-			font-weight: bold
-		.select2-selection__placeholder
-			color: #999
-		.select2-selection__arrow
-			height: 26px
-			position: absolute
-			top: 1px
-			right: 1px
-			width: 20px
-			b
-				border-color: #888 transparent transparent transparent
-				border-style: solid
-				border-width: 5px 4px 0 4px
-				height: 0
-				left: 50%
-				margin-left: -4px
-				margin-top: -2px
-				position: absolute
-				top: 50%
-				width: 0
-	&.select2-container--disabled .select2-selection--single
-		background-color: #eee
-		cursor: default
-		.select2-selection__clear
-			display: none
-	&.select2-container--open .select2-selection--single .select2-selection__arrow b
-		border-color: transparent transparent #888 transparent
-		border-width: 0 4px 5px 4px
-	.select2-selection--multiple
-		border-bottom: 1px solid $color-background-dark
-		cursor: text
-		transition: all 150ms ease-in-out
-		&:hover
-			border-color: $color-text-dark-secondary
-
-		.select2-selection__rendered
-			box-sizing: border-box
-			list-style: none
-			margin: 0
-			padding: 0 5px
-			width: 100%
-		.select2-selection__placeholder
-			color: #999
-			margin-top: 5px
-			float: left
-		.select2-selection__clear
-			cursor: pointer
-			float: right
-			font-weight: bold
-			margin-top: 5px
-			margin-right: 10px
-
-		/* Selected names in the select  */
-		.select2-selection__choice
-			background-color: $color-background-light
-			border: thin solid $color-background
-			border-radius: 3px
-			cursor: default
-			float: left
-			margin-right: 5px
-			margin-top: 5px
-			padding: 3px 10px
-			color: $color-text-dark-primary
-		.select2-selection__choice__remove
-			color: $color-text-dark-hint
-			cursor: pointer
-			display: inline-block
-			font-weight: bold
-			margin-right: 8px
-			&:hover
-				color: $color-danger
-	&.select2-container--focus .select2-selection--multiple
-		border-bottom: 1px solid $color-primary
-		box-shadow: 0 1px 0 0 $color-primary
-		outline: 0
-
-	&.select2-container--disabled
-		.select2-selection--multiple
-			background-color: #eee
-			cursor: default
-		.select2-selection__choice__remove
-			display: none
-	&.select2-container--open
-		&.select2-container--above
-			.select2-selection--single, .select2-selection--multiple
-				border-top-left-radius: 0
-				border-top-right-radius: 0
-		&.select2-container--below
-			.select2-selection--single, .select2-selection--multiple
-				border-bottom-left-radius: 0
-				border-bottom-right-radius: 0
-	.select2-search--dropdown .select2-search__field
-		border: 1px solid $color-background-dark
-	.select2-search--inline .select2-search__field
-		background: transparent
-		border: none
-		outline: 0
-		box-shadow: none
-		-webkit-appearance: textfield
-	.select2-results > .select2-results__options
-		max-height: 250px
-		overflow-y: auto
-	.select2-results__option
-		&:last-child
-			border-bottom-left-radius: 3px
-			border-bottom-right-radius: 3px
-
-		&[role=group]
-			padding: 0
-		&[aria-disabled=true]
-			background-color: $color-background
-			color: $color-text-dark-hint
-		&[aria-selected=true]
-			background-color: $color-background-light
-			color: $color-text-dark-primary
-		.select2-results__option
-			padding-left: 1em
-			.select2-results__group
-				padding-left: 0
-			.select2-results__option
-				margin-left: -1em
-				padding-left: 2em
-				.select2-results__option
-					margin-left: -2em
-					padding-left: 3em
-					.select2-results__option
-						margin-left: -3em
-						padding-left: 4em
-						.select2-results__option
-							margin-left: -4em
-							padding-left: 5em
-							.select2-results__option
-								margin-left: -5em
-								padding-left: 6em
-
-	/* Hovered item from the dropdown */
-	.select2-results__option--highlighted[aria-selected]
-		background-color: white
-		color: $color-primary
-
-		&:last-child
-			border-bottom-left-radius: 3px
-			border-bottom-right-radius: 3px
-
-	.select2-results__group
-		cursor: default
-		display: block
-		padding: 6px
diff --git a/packages/flamenco/src/templates/flamenco/_notifications.jade b/packages/flamenco/src/templates/flamenco/_notifications.jade
deleted file mode 100644
index cf1b56ea24ea8536780c83bf030009bd67aa4b7d..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/_notifications.jade
+++ /dev/null
@@ -1,4 +0,0 @@
-ul#notifications-list
-	li.nc-item
-		#notifications-loader
-			i.pi-spin.spin
diff --git a/packages/flamenco/src/templates/flamenco/errors/layout.jade b/packages/flamenco/src/templates/flamenco/errors/layout.jade
deleted file mode 100644
index 86fa1cf27f9c8e42b9bc2d5747dff3d95d7eb152..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/errors/layout.jade
+++ /dev/null
@@ -1,27 +0,0 @@
-doctype
-html(lang="en")
-	head
-		meta(charset="utf-8")
-		title Flamenco - Blender Cloud
-		meta(name="viewport", content="width=device-width, initial-scale=1.0")
-		meta(name="description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the past open projects.")
-		meta(name="author", content="Blender Institute")
-		meta(name="theme-color", content="#3e92aa")
-
-		script.
-			!function(e){"use strict";e.loadCSS=function(t,n,o){var r,i=e.document,l=i.createElement("link");if(n)r=n;else{var d=(i.body||i.getElementsByTagName("head")[0]).childNodes;r=d[d.length-1]}var a=i.styleSheets;l.rel="stylesheet",l.href=t,l.media="only x",r.parentNode.insertBefore(l,n?r:r.nextSibling);var f=function(e){for(var t=l.href,n=a.length;n--;)if(a[n].href===t)return e();setTimeout(function(){f(e)})};return l.onloadcssdefined=f,f(function(){l.media=o||"all"}),l},"undefined"!=typeof module&&(module.exports=e.loadCSS)}(this);
-
-			loadCSS( "//fonts.googleapis.com/css?family=Roboto:300,400,500" );
-			loadCSS( "//fonts.googleapis.com/css?family=Lato:300,400" );
-
-		link(href="{{ url_for('static_pillar', filename='assets/ico/favicon.png') }}", rel="shortcut icon")
-		link(href="{{ url_for('static_pillar', filename='assets/ico/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
-
-		link(href="{{ url_for('static_pillar', filename='assets/css/main.css') }}", rel="stylesheet")
-
-	body.error
-		| {% block body %}{% endblock %}
-
-		noscript
-			link(href='//fonts.googleapis.com/css?family=Roboto:300,400,500', rel='stylesheet', type='text/css')
-			link(href='//fonts.googleapis.com/css?family=Lato:300,400', rel='stylesheet', type='text/css')
diff --git a/packages/flamenco/src/templates/flamenco/errors/project_not_setup.jade b/packages/flamenco/src/templates/flamenco/errors/project_not_setup.jade
deleted file mode 100644
index abd2a8683184e3c4d65bd7f5a6a0f89a1351d01b..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/errors/project_not_setup.jade
+++ /dev/null
@@ -1,12 +0,0 @@
-| {% extends "flamenco/errors/layout.html" %}
-| {% block body %}
-#error_container.standalone
-	#error_box
-		.error-top-container
-			.error-title Project not set up for Flamenco.
-		.error-lead
-			p Currently Flamenco is in development, and only available to a select few.
-			hr
-			p If you want to use Flamenco, contact us at
-				a(href="mailto:cloudsupport@blender.institute") cloudsupport@blender.institute
-| {% endblock %}
diff --git a/packages/flamenco/src/templates/flamenco/help.jade b/packages/flamenco/src/templates/flamenco/help.jade
deleted file mode 100644
index 7eae98de06ba9de7039b1779623745dca57093bc..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/help.jade
+++ /dev/null
@@ -1,10 +0,0 @@
-.modal-help
-	.modal-help-panel
-		span.title Status Color Legend
-		| {% for status in statuses | sort %}
-		.status-debug-item
-			.status-debug-item-statuses
-				.light(class='status-{{ status }}')
-				.regular(class='status-{{ status }}') {{ status | undertitle }}
-				.dark(class='status-{{ status }}')
-		| {% endfor %}
diff --git a/packages/flamenco/src/templates/flamenco/index.jade b/packages/flamenco/src/templates/flamenco/index.jade
deleted file mode 100644
index 0437783129ca16ef34e56476fcc4fc319331ef2b..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/index.jade
+++ /dev/null
@@ -1,32 +0,0 @@
-| {% extends 'flamenco/layout.html' %}
-| {% block bodyattrs %}{{ super() }} data-context='dashboard'{% endblock %}
-| {% block page_title %}Dashboard{% endblock %}
-
-| {% block body %}
-#col_main
-	.dashboard
-		.d-stats
-			h3
-				i.pi-flamenco
-				|  Flamenco
-
-			| {% for proj, summary in projs_with_summaries %}
-			.d-stats-card
-				h4
-					a(href="{{ url_for('flamenco.jobs.perproject.index', project_url=proj.url) }}") {{ proj.name }}
-
-					span.pull-right
-						a(href="{{ url_for('flamenco.jobs.perproject.index', project_url=proj.url) }}") Jobs&nbsp;
-				.progress
-					| {% for status, percentage in summary.percentages() %}
-					.progress-bar.bg-status(
-						class="status-{{status}}",
-						title="{{ status | undertitle }} ({{percentage}}%)",
-						role="progressbar",
-						style="width:{{percentage}}%")
-						| {{ status | undertitle }}
-					| {% endfor %}
-				| {% endfor %}
-
-#col_right
-| {% endblock %}
diff --git a/packages/flamenco/src/templates/flamenco/index_anon_left_column.jade b/packages/flamenco/src/templates/flamenco/index_anon_left_column.jade
deleted file mode 100644
index 21b041db16eb4c4c3ec62b416335e4d0b3df44e3..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/index_anon_left_column.jade
+++ /dev/null
@@ -1,32 +0,0 @@
-
-.d-welcome
-	.welcome-logo
-		i.pi-flamenco
-	.welcome-title Welcome to Flamenco
-
-	.welcome-text
-		p Your Render Management Software
-
-h3.d-title Projects using Flamenco
-.d-projects
-	| {% for proj, summary in projs_with_summaries %}
-	.d-projects-item
-		a.d-projects-item-header(
-			href="{{ url_for('flamenco.jobs.perproject.index', project_url=proj.url) }}")
-			| {% if proj.picture_header %}
-			img(src="{{ proj.picture_header.thumbnail('m', api=api) }}")
-			| {% endif %}
-		a.d-projects-item-title(
-			href="{{ url_for('flamenco.jobs.perproject.index', project_url=proj.url) }}")
-			| {{ proj.name }}
-		.d-projects-item-stats
-			.progress
-				| {% for status, percentage in summary.percentages() %}
-				.progress-bar.bg-status(
-					class="status-{{status}}",
-					title="{{ status | undertitle }}",
-					role="progressbar",
-					style="width:{{percentage}}%")
-				| {% endfor %}
-
-	| {% endfor %}
diff --git a/packages/flamenco/src/templates/flamenco/jobs/depsgraph.jade b/packages/flamenco/src/templates/flamenco/jobs/depsgraph.jade
deleted file mode 100644
index 0852cd0ebc160c58a98861df3ec21523821df430..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/jobs/depsgraph.jade
+++ /dev/null
@@ -1,41 +0,0 @@
-doctype html
-html(lang="en")
-	head
-		meta(charset="utf-8")
-		title Job Depsgraph - Flamenco
-		meta(name="viewport", content="width=device-width, initial-scale=1.0")
-
-		link(href="{{ url_for('static_flamenco', filename='assets/css/vendor/vis.min.css') }}", rel="stylesheet")
-		script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery-3.1.0.min.js')}}")
-		script(src="{{ url_for('static_flamenco', filename='assets/js/vendor/vis.min.js')}}")
-		script(src="{{ url_for('static_flamenco', filename='assets/js/generated/depsgraph.min.js')}}")
-
-		link(href="{{ url_for('static_flamenco', filename='assets/img/favicon.png') }}", rel="shortcut icon")
-
-		style.
-			html, body {
-				background-color: white;
-				color: black;
-				margin: 0;
-				padding: 0;
-			}
-			#depsgraph {
-				position: absolute;
-				left: 0;
-				right: 0;
-				top: 0;
-				bottom: 0;
-			}
-
-	body
-
-		#depsgraph
-
-		script.
-			$.get('depsgraph', function(node_edge_data) {
-				console.log('Node/edge data: ', node_edge_data);
-				depsgraph('depsgraph', node_edge_data.nodes, node_edge_data.edges);
-			})
-			.fail(function(xhr) {
-				console.log('Could not get depsgraph data', xhr);
-			});
diff --git a/packages/flamenco/src/templates/flamenco/jobs/list_for_project.jade b/packages/flamenco/src/templates/flamenco/jobs/list_for_project.jade
deleted file mode 100644
index 1c6233e289b54eaa6aa63505d3532941e1b303b5..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/jobs/list_for_project.jade
+++ /dev/null
@@ -1,124 +0,0 @@
-| {% extends 'flamenco/layout.html' %}
-| {% block bodyattrs %}{{ super() }} data-context='job'{% endblock %}
-| {% block page_title %}Jobs - {{ project.name }}{% endblock %}
-| {% block body %}
-#col_main
-	#col_main-overlay
-		#col_main-overlay-close
-			i.pi-cancel
-		.col_header
-			span.header_text Task Details
-		#col_main-overlay-content.col-scrollable
-
-	#col_main-content
-		.col_header.item-list-header
-			// TODO: implement the stats
-			span.header_text(title='In the current project') {{ stats.nr_of_jobs }} jobs | {{ stats.nr_of_tasks }} tasks
-			a.item-project(href="{{url_for('projects.view', project_url=project.url)}}") {{ project.name }}
-
-		.item-list.col-scrollable
-			.table
-				.table-head
-					.table-row
-						.table-cell.item-status
-							span.collapser(title="Collapse status column") Status
-						.table-cell.item-name
-							span.collapser(title="Collapse name column") Name
-						.table-cell.item-priority
-							span.collapser(title="Collapse priority column") Priority
-
-				.table-body
-					| {% for job in jobs %}
-					| {% set link_url = url_for('flamenco.jobs.perproject.view_job', project_url=project.url, job_id=job._id) %}
-					.table-row(
-						id="job-{{ job._id }}",
-						class="status-{{ job.status }}{% if job._id == open_job_id %} active{% endif %}")
-						.table-cell.item-status
-							a(data-job-id="{{ job._id }}",
-								href="{{ link_url }}",
-								class="job-link")
-								| {{ job.status | undertitle }}
-						.table-cell.item-name
-							a(data-job-id="{{ job._id }}",
-								href="{{ link_url }}",
-								class="job-link")
-								span(class="job-name-{{ job._id }}") {{ job.name }}
-						.table-cell.item-priority
-							a(data-job-id="{{ job._id }}",
-								href="{{ link_url }}")
-								span(class="job-priority-{{ job._id }}") {{ job.priority }}
-					| {% endfor %}
-
-.col-splitter
-
-#col_right
-	.col_header
-		span.header_text
-		#status-bar
-	#item-details.col-scrollable
-		.item-details-empty
-			| Select a Job
-			| {{ open_job_id | hide_none }}
-
-| {% endblock %}
-| {% block footer_scripts %}
-script.
-	{% if open_task_id %}
-		$(function() { item_open('{{ open_task_id }}', 'task', false); });
-	{% endif %}
-	{% if open_job_id %}
-		$(function() { item_open('{{ open_job_id }}', 'job', false); });
-	{% endif %}
-
-	var same_cells;
-
-	/* Collapse columns by clicking on the title */
-	$('.table-head .table-cell span.collapser').on('click', function(e){
-		e.stopPropagation();
-
-		/* We need to find every cell matching the same classes */
-		same_cells = '.' + $(this).parent().attr('class').split(' ').join('.');
-		$(same_cells).hide();
-		/* Add the spacer which we later click to expand  */
-		$('<div class="table-cell-spacer ' + $(this).text() + '" title="Expand ' + $(this).text() + '"></div>').insertAfter(same_cells);
-	});
-
-	$('body').on('click', '.table-cell-spacer', function(){
-		/* We need to find every cell matching the same classes */
-		same_cells = '.' + $(this).prev().attr('class').split(' ').join('.');
-		$(same_cells).show();
-		$(same_cells).next().remove();
-	});
-
-	/* Highlight the corresponding cell type in the header */
-	$('.table-body .table-cell').mouseenter(function(){
-		same_cells = '.' + $(this).attr('class').split(' ').join('.');
-		$('.table-head ' + same_cells).addClass('highlight');
-	}).mouseleave(function(){
-		same_cells = '.' + $(this).attr('class').split(' ').join('.');
-		$('.table-head ' + same_cells).removeClass('highlight');
-	});
-
-	/* Highlight the corresponding cell type in the body */
-	$('.table-head .table-cell').mouseenter(function(){
-		same_cells = '.' + $(this).attr('class').split(' ').join('.');
-		$('.table-body ' + same_cells).addClass('highlight');
-	}).mouseleave(function(){
-		same_cells = '.' + $(this).attr('class').split(' ').join('.');
-		$('.table-body ' + same_cells).removeClass('highlight');
-	});
-
-script(src="{{ url_for('static_flamenco', filename='assets/js/vendor/clipboard.min.js')}}")
-script(src="{{ url_for('static_flamenco', filename='assets/js/vendor/jquery-resizable.min.js')}}")
-script.
-	$("#col_main").resizable({
-		handleSelector: ".col-splitter",
-		resizeHeight: false
-	});
-
-	$(window).on('load resize', function(){
-		var window_height = $(window).height() - 55; // header is 55px
-		$('.col-scrollable').css({'height': window_height});
-	});
-
-| {% endblock footer_scripts %}
diff --git a/packages/flamenco/src/templates/flamenco/jobs/view_job_embed.jade b/packages/flamenco/src/templates/flamenco/jobs/view_job_embed.jade
deleted file mode 100644
index c7479e02c9c56ce1e78fab7825fef3b8d689d5ed..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/jobs/view_job_embed.jade
+++ /dev/null
@@ -1,79 +0,0 @@
-.flamenco-box.job.with-status(class="status-{{ job.status }}")
-	p.item-name {{ job.name | hide_none }}
-	| {% if job.description %}
-	p.item-description {{ job.description | hide_none }}
-	| {% endif %}
-
-	.table.item-properties
-		.table-body
-			.table-row.properties-status.js-help(
-				data-url="{{ url_for('flamenco.help', project_url=project.url) }}")
-				.table-cell Status
-				.table-cell(class="status-{{ job.status }}")
-					| {{ job.status | undertitle }}
-			.table-row
-				.table-cell Last Update
-				.table-cell(title="{{ job._updated }}")
-					span(role='button',
-						data-toggle='collapse',
-						data-target='#task-time-creation',
-						aria-expanded='false',
-						aria-controls='#task-time-creation')
-						| {{ job._updated | pretty_date_time }}
-					#task-time-creation.collapse
-						| Created on {{ job._created | pretty_date_time }}
-			.table-row
-				.table-cell Job Type
-				.table-cell
-					| {{ job.job_type }}
-			.table-row
-				.table-cell Priority
-				.table-cell(title="Higher number means higher priority")
-					| {{ job.priority }}
-
-	.table.item-properties.item-job-settings
-		.table-body
-			| {% for set_key, set_val in job.settings.to_dict().iteritems()  %}
-			.table-row
-				.table-cell
-					| {{ set_key | undertitle }}
-				.table-cell
-					| {{ set_val }}
-			| {% endfor %}
-
-#item-action-panel
-	.pull-right
-		| {% if can_cancel_job %}
-		button.btn.btn-danger(onclick="setJobStatus('{{ job._id }}', 'cancel-requested')")
-			i.pi-cancel
-			| Cancel Job
-		| {% endif %}
-		| {% if can_requeue_job %}
-		button.btn.btn-success.requeue-job(onclick="setJobStatus('{{ job._id }}', 'queued')")
-			i.pi-refresh
-			| Re-queue Job
-		| {% endif %}
-		.action-result-panel
-
-#item-view-feed
-	| {% if config.DEBUG %}
-	.debug-info
-		a.debug-info-toggle(role='button',
-			data-toggle='collapse',
-			href='#debug-content-job',
-			aria-expanded='false',
-			aria-controls='debug-content-job')
-			i.pi-info
-			| Debug Info
-		#debug-content-job.collapse
-			pre.
-				{{ job.to_dict() | pprint }}
-	| {% endif %}
-
-	#tasks
-	#comments-embed
-script.
-
-	$('.js-help').openModalUrl('Help', "{{ url_for('flamenco.help', project_url=project.url) }}");
-
-	loadTasks("{{url_for('flamenco.tasks.perjob.list_for_job', job_id=job._id, project_url=project.url)}}");
diff --git a/packages/flamenco/src/templates/flamenco/layout.jade b/packages/flamenco/src/templates/flamenco/layout.jade
deleted file mode 100644
index 28329d1044e2d902df817c7fd01bff7cdafffc31..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/layout.jade
+++ /dev/null
@@ -1,203 +0,0 @@
-doctype html
-html(lang="en")
-	head
-		meta(charset="utf-8")
-		title {% if self.page_title() %}{% block page_title %}{% endblock %} — {% endif %}Flamenco
-		meta(name="viewport", content="width=device-width, initial-scale=1.0")
-
-		| {% block head %}{% endblock %}
-
-		link(href='//fonts.googleapis.com/css?family=Roboto:300,400', rel='stylesheet', type='text/css')
-
-		link(href="{{ url_for('static_pillar', filename='assets/css/vendor/bootstrap.min.css') }}", rel="stylesheet")
-		link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css', v=141020161) }}", rel="stylesheet")
-		link(href="{{ url_for('static_pillar', filename='assets/css/base.css', v=171020161) }}", rel="stylesheet")
-		link(href="{{ url_for('static_flamenco', filename='assets/css/main.css') }}", rel="stylesheet")
-		link(href="{{ url_for('static_flamenco', filename='assets/css/plugins/js_select2.css') }}", rel="stylesheet")
-		script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery-3.1.0.min.js')}}")
-		script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.bootstrap-3.3.7.min.js') }}")
-		script(src="{{ url_for('static_pillar', filename='assets/js/tutti.min.js') }}")
-		script(src="{{ url_for('static_flamenco', filename='assets/js/generated/tutti.min.js') }}")
-
-		link(href="{{ url_for('static_flamenco', filename='assets/img/favicon.png') }}", rel="shortcut icon")
-
-		| {% block style %}{% endblock %}
-
-	body("{% block bodyattrs %}{% if project %}data-project-url='{{ project.url }}'{% endif %}{% endblock %}")
-		#app-main
-			#col_sidebar
-				nav.sidebar(role='navigation')
-					ul
-						li
-							a.navbar-item.cloud(href="{% if project %}{{url_for('projects.view', project_url=project.url)}}{% else %}{{ url_for('main.homepage') }}{% endif %}",
-								title='Blender Cloud')
-								i.pi-blender-cloud
-						li
-							a.navbar-item.flamenco(href="{{ url_for('flamenco.index') }}",
-								title='Flamenco')
-								i.pi-flamenco
-						| {% if project %}
-						li
-							a.navbar-item.jobs(href="{{ url_for('flamenco.jobs.perproject.index', project_url=project.url) }}",
-							title='Jobs for project {{ project.name }}') Jobs
-						li
-							a.navbar-item.tasks(href="{{ url_for('flamenco.tasks.perproject.index', project_url=project.url) }}",
-								title='Tasks for project {{ project.name }}') Tasks
-						| {% endif %}
-
-					ul.bottom
-						| {% if project %}
-						li
-							button.js-help(
-								type="button",
-								title="Help",
-								data-url="{{ url_for('flamenco.help', project_url=project.url) }}")
-								i.pi-question
-						| {% endif %}
-
-						| {% if current_user.is_authenticated %}
-
-						| {% if current_user.has_role('demo') %}
-						| {% set subscription = 'demo' %}
-						| {% elif current_user.has_role('subscriber') %}
-						| {% set subscription = 'subscriber' %}
-						| {% else %}
-						| {% set subscription = 'none' %}
-						| {% endif %}
-
-						li.nav-notifications
-							a.navbar-item#notifications-toggle(
-								title="Notifications",
-								data-toggle="tooltip",
-								data-placement="bottom")
-								i.pi-notifications-none.nav-notifications-icon
-								span#notifications-count
-									span
-								.flyout-hat
-
-							#notifications.flyout.notifications
-								.flyout-content
-									span.flyout-title Notifications
-									a#notifications-markallread(
-										title="Mark All as Read",
-										href="/notifications/read-all")
-										| Mark All as Read
-
-									| {% include '_notifications.html' %}
-
-
-						li(class="dropdown{% if title in ['profile', 'billing-address', 'pledges', 'manage-collection']: %} active{% endif %}")
-							a.navbar-item.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_user.email }}")
-								img.gravatar(
-									src="{{ current_user.gravatar }}",
-									class="{{ subscription }}",
-									alt="Avatar")
-								.special(class="{{ subscription }}")
-									| {% if subscription == 'subscriber' %}
-									i.pi-check
-									| {% elif subscription == 'demo' %}
-									i.pi-heart-filled
-									| {% else %}
-									i.pi-attention
-									| {% endif %}
-
-							ul.dropdown-menu
-								| {% if not current_user.has_role('protected') %}
-								li.subscription-status(class="{{ subscription }}")
-									| {% if subscription == 'subscriber' %}
-									a.navbar-item(
-										href="{{url_for('users.settings_billing')}}"
-										title="View subscription info")
-										i.pi-grin
-										span Your subscription is active!
-									| {% elif subscription == 'demo' %}
-									a.navbar-item(
-										href="{{url_for('users.settings_billing')}}"
-										title="View subscription info")
-										i.pi-heart-filled
-										span You have a free account.
-									| {% else %}
-									a.navbar-item(
-										href="https://store.blender.org/product/membership/"
-										title="Renew subscription")
-										i.pi-unhappy
-										span.info Your subscription is not active.
-											span.renew Click here to renew.
-									| {% endif %}
-
-								li
-									a.navbar-item(
-										href="{{ url_for('projects.home_project') }}"
-										title="Home")
-										i.pi-home
-										| Home
-
-								li
-									home_project
-									a.navbar-item(
-										href="{{ url_for('projects.index') }}"
-										title="My Projects")
-										i.pi-star
-										| My Projects
-
-								li
-									a.navbar-item(
-										href="{{ url_for('users.settings_profile') }}"
-										title="Settings")
-										i.pi-cog
-										| Settings
-								li
-									a.navbar-item(
-										href="{{ url_for('users.settings_billing') }}"
-										title="Billing")
-										i.pi-credit-card
-										| Subscription
-								li.divider(role="separator")
-								| {% endif %}
-								li
-									a.navbar-item(
-										href="{{ url_for('users.logout') }}")
-										i.pi-log-out(title="Log Out")
-										| Log out
-
-						| {% else %}
-						li
-							a.navbar-item(
-								href="{{ url_for('users.login') }}",
-								title="Sign in")
-								i.pi-log-in
-						| {% endif %}
-
-			| {% block body %}
-			#col_left
-			#col_main
-				h1 Main
-			#col_right
-				h1 Right
-			| {% endblock %}
-
-		.modal.fade#modal(role="dialog")
-			.modal-dialog
-				.modal-content
-					.modal-header
-						button.close(type="button", data-dismiss="modal", aria-label="Close")
-							i.pi-cancel
-						span.title
-					.modal-body
-
-		script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.select2.min.js') }}", async=true)
-		script.
-			{% if project %}
-			$('.js-help').openModalUrl('Help', "{{ url_for('flamenco.help', project_url=project.url) }}");
-			{% endif %}
-
-			$(document).ready(function() {
-				{% if current_user.is_authenticated %}
-					getNotificationsLoop(); // Check for new notifications in the background
-
-					// Resize #notifications and change overflow for scrollbars
-					$(window).on("resize", function() { notificationsResize(); });
-				{% endif %}
-			});
-
-		| {% block footer_scripts %}{% endblock %}
diff --git a/packages/flamenco/src/templates/flamenco/sidebar.jade b/packages/flamenco/src/templates/flamenco/sidebar.jade
deleted file mode 100644
index 4271e9ea7dea510d517cb21e38e2235aee9a6c71..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/sidebar.jade
+++ /dev/null
@@ -1,6 +0,0 @@
-li.tabs-flamenco(
-	title="Flamenco",
-	data-toggle="tooltip",
-	data-placement="left")
-	a(href="{{url_for('flamenco.project_index', project_url=project.url, _external=True)}}")
-		i.pi-film-thick
diff --git a/packages/flamenco/src/templates/flamenco/tasks/_task_list.jade b/packages/flamenco/src/templates/flamenco/tasks/_task_list.jade
deleted file mode 100644
index 9d510eb579cd6d2e205f95cd43aa43708a39e13b..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/tasks/_task_list.jade
+++ /dev/null
@@ -1,16 +0,0 @@
-| {% macro task_list(task_count, tasks, project) -%}
-.col_header.task-list-header
-	| Tasks ({{ task_count }})
-
-#task-list.col-list
-	| {% for task in tasks %}
-	a.col-list-item.task-list-item(
-	data-task-id="{{ task._id }}",
-	id="task-{{ task._id }}",
-	class="status-{{ task.status }} task-link",
-	href="{{ url_for('flamenco.tasks.perproject.view_task', project_url=project.url, task_id=task._id) }}")
-		span.status-indicator(title="Status: {{ task.status | undertitle }}")
-		span.name {{ task.name }}
-		span.type {{ task.status }} - {{ task.job_type | undertitle }}
-	| {% endfor %}
-| {%- endmacro %}
diff --git a/packages/flamenco/src/templates/flamenco/tasks/list_for_job_embed.jade b/packages/flamenco/src/templates/flamenco/tasks/list_for_job_embed.jade
deleted file mode 100644
index e1b3c4687c1c595903f06d6a42d7ce0d6927e0e2..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/tasks/list_for_job_embed.jade
+++ /dev/null
@@ -1,3 +0,0 @@
-#col_main
-	| {% from "flamenco/tasks/_task_list.html" import task_list %}
-	| {{ task_list(task_count, tasks, project) }}
diff --git a/packages/flamenco/src/templates/flamenco/tasks/list_for_project.jade b/packages/flamenco/src/templates/flamenco/tasks/list_for_project.jade
deleted file mode 100644
index 533fe09f89fc0ea407839e199603bc8dc0570c7f..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/tasks/list_for_project.jade
+++ /dev/null
@@ -1,57 +0,0 @@
-| {% extends 'flamenco/layout.html' %}
-| {% block bodyattrs %}{{ super() }} data-context='task'{% endblock %}
-| {% block page_title %}Tasks - {{ project.name }} {% endblock %}
-| {% block body %}
-#col_main
-	.col_header.task-list-header
-		| Tasks ({{ tasks | count }})
-		a.item-project(href="{{url_for('projects.view', project_url=project.url)}}") {{ project.name }}
-	.item-list.task.col-list.col-scrollable
-		| {% for task in tasks %}
-		a.col-list-item.task-list-item(
-			id="task-{{task._id}}",
-			data-task-id="{{task._id}}",
-			class="status-{{ task.status }} task-link",
-			href="{{ url_for('flamenco.tasks.perproject.view_task', project_url=project.url, task_id=task._id) }}")
-			span.status-indicator(title="Status: {{ task.status | undertitle }}")
-			| {% if task._parent_info %}
-			span.shotname(title="Shot {{ task._parent_info.name }}") {{ task._parent_info.name }}
-			| {% endif %}
-			span.name {{ task.name }}
-			span.status {{ task.status }}
-		| {% endfor %}
-
-.col-splitter
-
-#col_right
-	.col_header
-		span.header_text
-		#status-bar
-	#item-details
-		.item-details-empty
-			| Select a Task
-| {% endblock %}
-
-| {% block footer_scripts %}
-script.
-	{% if open_task_id %}
-		$(function() { item_open('{{ open_task_id }}', 'task', false); });
-	{% endif %}
-
-script(src="{{ url_for('static_flamenco', filename='assets/js/vendor/clipboard.min.js')}}")
-script(src="{{ url_for('static_flamenco', filename='assets/js/vendor/jquery-resizable.min.js')}}")
-
-script.
-	$("#col_main").resizable({
-		handleSelector: ".col-splitter",
-		resizeHeight: false
-	});
-
-	$(window).on('load resize', function(){
-		var window_height = $(window).height() - 50;
-		var task_list = document.getElementById('task-list');
-		$('#task-list').css({'height': window_height});
-		$('#item-details').css({'height': window_height});
-	});
-
-| {% endblock %}
diff --git a/packages/flamenco/src/templates/flamenco/tasks/view_task_embed.jade b/packages/flamenco/src/templates/flamenco/tasks/view_task_embed.jade
deleted file mode 100644
index 59cb1c6ef8204b74919a2efc7012885f576efc5c..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/tasks/view_task_embed.jade
+++ /dev/null
@@ -1,111 +0,0 @@
-.flamenco-box.task.with-status(
-	class="status-{{ task.status }}")
-	form#task_form(onsubmit="return false")
-		input(type='hidden',name='_etag',value='{{ task._etag }}')
-		.input-group
-			span.item-name {{ task.name | hide_none }}
-
-			.dropdown(style='margin-left: auto')
-				button#item-dropdown.btn.btn-default.dropdown-toggle(
-					type='button',
-					data-toggle='dropdown',
-					aria-haspopup='true', aria-expanded='true')
-					i.pi-more-vertical
-				ul.dropdown-menu(aria-labelledby='item-dropdown')
-					li.copy-to-clipboard-id(data-clipboard-text="{{ task._id }}")
-						a(href="javascript:void(0)")
-							i.pi-clipboard-copy
-							| Copy task ID to Clipboard
-					li
-						a(href="{{ url_for('flamenco.tasks.perproject.download_task_log', project_url=project.url, task_id=task._id) }}",
-							target="_blank")
-							i.pi-download
-							| Download Task Log
-		| {% if task.description %}
-		p.item-description {{ task.description | hide_none }}
-		| {% endif %}
-
-		.table.item-properties
-			.table-body
-				.table-row.properties-status.js-help(
-					data-url="{{ url_for('flamenco.help', project_url=project.url) }}")
-					.table-cell Status
-					.table-cell(class="status-{{ task.status }}")
-						| {{ task.status | undertitle }}
-				.table-row
-					.table-cell Priority
-					.table-cell {{ task.priority }}
-				//- .table-row
-				//- 	.table-cell Task progress
-				//- 	.table-cell {{ task.task_progress_percentage }}%
-				.table-row
-					.table-cell Activity
-					.table-cell {{ task.activity }}
-				.table-row
-					.table-cell Worker
-					.table-cell {{ task.worker }}
-
-#item-action-panel
-	button.btn.item-log-load.js-log-load(
-		data-url="{{ url_for('flamenco.tasks.perproject.view_task_log', project_url=project.url, task_id=task._id) }}")
-		i.pi-list
-		| View Log
-
-	.pull-right
-		| {% if can_requeue_task %}
-		button.btn.btn-success.requeue-task(onclick="setTaskStatus('{{ task._id }}', 'queued')")
-			i.pi-refresh
-			| Re-queue task
-		| {% endif %}
-		.action-result-panel
-
-#item-log.task
-
-| {% if config.DEBUG %}
-.debug-info
-	a.debug-info-toggle(role='button',
-		data-toggle='collapse',
-		href='#debug-content-task',
-		aria-expanded='false',
-		aria-controls='debug-content-task')
-		i.pi-info
-		| Debug Info
-	#debug-content-task.collapse
-		pre.
-			{{ task.to_dict() | pprint }}
-	| {% endif %}
-
-script.
-	new Clipboard('.copy-to-clipboard-id')
-	.on('success', function(e) {
-		statusBarSet('info', 'Copied task ID to clipboard', 'pi-check');
-	});
-
-	$('.js-help').openModalUrl('Help', "{{ url_for('flamenco.help', project_url=project.url) }}");
-
-	setupJsJobLinkClickHandlers();
-
-	// Task Logs
-	$('.js-log-load').on('click', function(){
-		var url = $(this).data('url');
-		var container = $('#item-log.task');
-
-		$(container).html('<div class="item-log-loader"><i class="pi-spin spin"></i></div>');
-		getTaskLog(url, $(container)); // on tasks.js
-	});
-
-	// Close Task Details
-	function closeTaskDetails(){
-		clearMainOverlay();
-
-		// Push the correct URL onto the history.
-		push_url = '/flamenco/{{ project.url }}/jobs/{{ task.job }}';
-		var push_state = {itemId: '{{ task._id }}', itemType: 'task'};
-		window.history.pushState(
-						push_state,
-						'task: ' + '{{ task._id }}',
-						push_url
-		);
-	}
-
-	$('#col_main-overlay-close').on('click', closeTaskDetails);
diff --git a/packages/flamenco/src/templates/flamenco/tasks/view_task_log_embed.jade b/packages/flamenco/src/templates/flamenco/tasks/view_task_log_embed.jade
deleted file mode 100644
index e1e62d5cbe25a471a7b2d746d0cae1a71f87cc01..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/tasks/view_task_log_embed.jade
+++ /dev/null
@@ -1,45 +0,0 @@
-.item-log-header
-	span.header-title Task Log
-
-	.item-log-navigation
-
-		a.download-log(href="{{ url_for('flamenco.tasks.perproject.download_task_log', project_url=project.url, task_id=task_id) }}")
-			i.pi-download
-
-		span.log-page Page {{ page_idx }}
-		a.log-navigate.js-log-navigate(
-			class="{% if page_idx == 1 %}active{% endif %}",
-			href="{{ url_for(request.endpoint, project_url=project.url, task_id=task_id, page=1) }}")
-			| first
-
-		a.log-navigate.js-log-navigate(
-			class="{% if not has_prev_page %}disabled{% endif %}",
-			href="{{ url_for(request.endpoint, project_url=project.url, task_id=task_id, page=page_idx-1) }}")
-			| prev
-
-		a.log-navigate.js-log-navigate(
-			class="{% if not has_next_page %}disabled{% endif %}",
-			href="{{ url_for(request.endpoint, project_url=project.url, task_id=task_id, page=page_idx+1) }}")
-			| next
-
-		a.log-navigate.js-log-navigate(
-			class="{% if page_idx == last_page_idx %}active{% endif %}",
-			href="{{ url_for(request.endpoint, project_url=project.url, task_id=task_id, page=last_page_idx) }}")
-			| last
-
-.item-log-content
-	| {% for task_log in logs['_items'] %}
-	|		{% for line in task_log.log.split('\n') %}
-	p.item-log-line {{ line }}
-	|		{% endfor %}
-	| {% endfor %}
-
-script.
-	$('a.js-log-navigate').on('click', function(e){
-		e.preventDefault();
-
-		var url = $(this).attr('href');
-		getTaskLog(url, $('#item-log.task'));
-	});
-
-	$("p.item-log-line:contains('> Warning:')").addClass('log-warning');
diff --git a/packages/flamenco/src/templates/flamenco/view_activities_embed.jade b/packages/flamenco/src/templates/flamenco/view_activities_embed.jade
deleted file mode 100644
index 66a36bd462fc295cfb9187e6d46481e71e456789..0000000000000000000000000000000000000000
--- a/packages/flamenco/src/templates/flamenco/view_activities_embed.jade
+++ /dev/null
@@ -1,11 +0,0 @@
-.d-activity
-	| {% if activities['_meta']['total'] %}
-	ul
-		| {% for act in activities['_items'] %}
-		li
-			img.actor-avatar(src="{{ act['actor_user']['email'] | gravatar }}")
-			span.date(title="{{ act._created }}") {{ act._created | pretty_date_time }}
-			span.actor {{ act['actor_user']['full_name'] }}
-			span.verb {{ act.verb }}
-		| {% endfor %}
-	| {% endif %}
diff --git a/packages/flamenco/tests/abstract_flamenco_test.py b/packages/flamenco/tests/abstract_flamenco_test.py
deleted file mode 100644
index e9c07d015855087d2569ad4921062e374c2655b7..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/abstract_flamenco_test.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-import pillarsdk
-import pillar.tests
-import pillar.auth
-
-from pillar.tests import PillarTestServer, AbstractPillarTest
-from pillar.tests import common_test_data as ctd
-
-
-class FlamencoTestServer(PillarTestServer):
-    def __init__(self, *args, **kwargs):
-        PillarTestServer.__init__(self, *args, **kwargs)
-
-        from flamenco import FlamencoExtension
-        self.load_extension(FlamencoExtension(), '/flamenco')
-
-
-class AbstractFlamencoTest(AbstractPillarTest):
-    pillar_server_class = FlamencoTestServer
-
-    def setUp(self, **kwargs):
-        AbstractPillarTest.setUp(self, **kwargs)
-        self.tmngr = self.flamenco.task_manager
-        self.jmngr = self.flamenco.job_manager
-
-        self.proj_id, self.project = self.ensure_project_exists()
-
-        self.sdk_project = pillarsdk.Project(pillar.tests.mongo_to_sdk(self.project))
-
-    def tearDown(self):
-        self.unload_modules('flamenco')
-        AbstractPillarTest.tearDown(self)
-
-    @property
-    def flamenco(self):
-        return self.app.pillar_extensions['flamenco']
-
-    def ensure_project_exists(self, project_overrides=None):
-        from flamenco.setup import setup_for_flamenco
-
-        project_overrides = dict(
-            picture_header=None,
-            picture_square=None,
-            **(project_overrides or {})
-        )
-        proj_id, project = AbstractPillarTest.ensure_project_exists(
-            self, project_overrides)
-
-        with self.app.test_request_context():
-            flamenco_project = setup_for_flamenco(
-                project['url'], replace=True)
-
-        return proj_id, flamenco_project
-
-    def create_manager_service_account(
-            self,
-            email=u'testmanager@example.com',
-            name=u'tēst mānēgūr',
-            url=u'https://username:password@[fe80::42:99ff:fe66:91bd]:5123/path/to/'):
-        from flamenco.setup import create_manager
-        from pillar.api.utils.authentication import force_cli_user
-
-        # Main project will have a manager, job, and tasks.
-        with self.app.test_request_context():
-            force_cli_user()
-            mngr_doc, account, token = create_manager(email, name, u'descr', url)
-
-        return mngr_doc, account, token
-
-    def assert_job_status(self, expected_status):
-        with self.app.test_request_context():
-            jobs_coll = self.flamenco.db('jobs')
-            job = jobs_coll.find_one(self.job_id, projection={'status': 1})
-        self.assertEqual(job['status'], unicode(expected_status))
-
-    def set_job_status(self, new_status, job_id=None):
-        """Nice, official, ripple-to-task-status approach"""
-
-        if job_id is None:
-            job_id = self.job_id
-
-        with self.app.test_request_context():
-            self.jmngr.api_set_job_status(job_id, new_status)
-
-    def force_job_status(self, new_status):
-        """Directly to MongoDB approach"""
-
-        with self.app.test_request_context():
-            jobs_coll = self.flamenco.db('jobs')
-            result = jobs_coll.update_one({'_id': self.job_id},
-                                          {'$set': {'status': new_status}})
-        self.assertEqual(1, result.matched_count)
-
-    def assert_task_status(self, task_id, expected_status):
-        if isinstance(task_id, basestring):
-            from pillar.api.utils import str2id
-            task_id = str2id(task_id)
-
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-            task = tasks_coll.find_one({'_id': task_id})
-
-        self.assertIsNotNone(task, 'Task %s does not exist in the database' % task_id)
-        self.assertEqual(task['status'], unicode(expected_status),
-                         "Task %s:\n   has status: '%s'\n but expected: '%s'" % (
-                             task_id, task['status'], expected_status))
-        return task
-
-    def force_task_status(self, task_idx, new_status):
-        """Sets the task status directly in MongoDB.
-
-        This should only be used to set up a certain scenario.
-        """
-        from flamenco import current_flamenco
-
-        with self.app.test_request_context():
-            current_flamenco.update_status('tasks', self.task_ids[task_idx], new_status)
diff --git a/packages/flamenco/tests/logging_config.py b/packages/flamenco/tests/logging_config.py
deleted file mode 100644
index 917ce8cfb9481e2182f686adc8e206a3cc665187..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/logging_config.py
+++ /dev/null
@@ -1,26 +0,0 @@
-LOGGING = {
-    'version': 1,
-    'formatters': {
-        'default': {'format': '%(asctime)-15s %(levelname)8s %(name)36s %(message)s'}
-    },
-    'handlers': {
-        'console': {
-            'class': 'logging.StreamHandler',
-            'formatter': 'default',
-            'stream': 'ext://sys.stderr',
-        }
-    },
-    'loggers': {
-        'pillar': {'level': 'DEBUG'},
-        'flamenco': {'level': 'DEBUG'},
-        'werkzeug': {'level': 'INFO'},
-        'eve': {'level': 'WARNING'},
-        # 'requests': {'level': 'DEBUG'},
-    },
-    'root': {
-        'level': 'INFO',
-        'handlers': [
-            'console',
-        ],
-    }
-}
diff --git a/packages/flamenco/tests/test_access.py b/packages/flamenco/tests/test_access.py
deleted file mode 100644
index 16eae3ca602549e241b66f49b6bd392899cdf98f..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_access.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-from pillar.tests import common_test_data as ctd
-from pillar.api.utils.authentication import force_cli_user
-
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class AccessTest(AbstractFlamencoTest):
-    """Creates a manager, job and tasks, to check access by different types of users."""
-
-    def _create_user_with_token(self, roles, token, user_id='cafef00df00df00df00df00d'):
-        user_id = self.create_user(roles=roles, user_id=user_id)
-        self.create_valid_auth_token(user_id, token)
-        return user_id
-
-    def _create_project(self, project_name, token):
-        resp = self.post('/api/p/create',
-                         headers={'Authorization': self.make_header(token)},
-                         expected_status=201,
-                         data={'project_name': project_name})
-        return resp.json()
-
-    def _create_user_and_project(self, roles, user_id='cafef00df00df00df00df00d', token='token',
-                                 project_name=u'Prøject El Niño'):
-        self._create_user_with_token(roles, token, user_id=user_id)
-        return self._create_project(project_name, token)
-
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-
-        from flamenco import current_flamenco
-
-        # Main project will have a manager, job, and tasks.
-        mngr_doc, _, token = self.create_manager_service_account()
-
-        self.mngr_id = mngr_doc['_id']
-        self.mngr_token = token['token']
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.job_id = job['_id']
-
-            tasks_coll = current_flamenco.db('tasks')
-            self.tasks_for_job = list(tasks_coll.find({'job': self.job_id}))
-
-        # Another project, also with manager, job, and tasks.
-        proj2_owner_id = 24 * 'a'
-        self.proj2 = self._create_user_and_project(user_id=proj2_owner_id,
-                                                   roles={u'subscriber'},
-                                                   project_name=u'Prøject 2',
-                                                   token='token-proj2-owner')
-        self.proj2_id = self.proj2['_id']
-
-        mngr_doc, _, token = self.create_manager_service_account(
-            email='manager2@example.com', name='manager 2'
-        )
-        self.mngr2_id = mngr_doc['_id']
-        self.mngr2_token = token['token']
-
-        with self.app.test_request_context():
-            force_cli_user()
-
-            job = self.jmngr.api_create_job(
-                'test job 2',
-                u'Wörk² wørk² w°rk².',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj2_id,
-                proj2_owner_id,
-                self.mngr2_id,
-            )
-            self.job2_id = job['_id']
-
-    def test_manager_account_access(self):
-        """Should have access to own job and tasks, but not project or other managers."""
-
-        from pillar.api.utils import remove_private_keys
-
-        # Own manager doc should be gettable, but other one should not.
-        own_url = '/api/flamenco/managers/%s' % self.mngr_id
-        own_doc = self.get(own_url,
-                           expected_status=200,
-                           auth_token=self.mngr_token).json()
-        other_url = '/api/flamenco/managers/%s' % self.mngr2_id
-        self.get(other_url,
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-
-        # Managers may not create new managers.
-        new_doc = remove_private_keys(own_doc)
-        self.post('/api/flamenco/managers', json=new_doc,
-                  expected_status=403,
-                  auth_token=self.mngr_token)
-
-        # Manager docs should not be modified.
-        self.put(own_url, json=remove_private_keys(own_doc),
-                 headers={'If-Match': own_doc['_etag']},
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-        self.delete(own_url,
-                    expected_status=405,
-                    auth_token=self.mngr_token)
-        self.put(other_url, json=remove_private_keys(own_doc),
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-        self.delete(other_url,
-                    expected_status=405,
-                    auth_token=self.mngr_token)
-
-        # Own job should be GETtable.
-        own_job_url = '/api/flamenco/jobs/%s' % self.job_id
-        own_job = self.get(own_job_url,
-                           expected_status=200,
-                           auth_token=self.mngr_token).json()
-        resp = self.get('/api/flamenco/jobs',
-                        expected_status=200,
-                        auth_token=self.mngr_token).json()
-        jobs = resp['_items']
-        self.assertEqual(1, len(jobs))
-        self.assertEqual(1, resp['_meta']['total'])
-        self.assertEqual(str(self.job_id), jobs[0]['_id'])
-
-        # Own job should not be modifyable.
-        self.put(own_job_url, json=own_job,
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-        self.delete(own_job_url,
-                    expected_status=403,
-                    auth_token=self.mngr_token)
-
-        # Managers may not create new jobs
-        new_job = remove_private_keys(own_job)
-        self.post('/api/flamenco/jobs', json=new_job,
-                  expected_status=403,
-                  auth_token=self.mngr_token)
-
-        # Job of other manager should not be GETtable.
-        self.get('/api/flamenco/jobs/%s' % self.job2_id,
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-
-        # Manager should not have direct access to tasks; only via scheduler.
-        self.get('/api/flamenco/tasks',
-                 expected_status=403,
-                 auth_token=self.mngr_token)
-        # Manager should be able to fetch their own tasks, once the IDs are known.
-        self.get('/api/flamenco/tasks/%s' % self.tasks_for_job[0]['_id'],
-                 expected_status=200,
-                 auth_token=self.mngr_token)
diff --git a/packages/flamenco/tests/test_commands.py b/packages/flamenco/tests/test_commands.py
deleted file mode 100644
index 20887eef076e52a45ba6fb44f7fdc9b6989bf590..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_commands.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from unittest import TestCase
-
-
-class SomeCommandsTest(TestCase):
-    def test_blender_render_name(self):
-        from flamenco.job_compilers.commands import BlenderRender
-
-        self.assertEqual('blender_render', BlenderRender.cmdname())
diff --git a/packages/flamenco/tests/test_depsgraph.py b/packages/flamenco/tests/test_depsgraph.py
deleted file mode 100644
index 1d4584cdeeba2cacbaa5527255eabb17e46d50cd..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_depsgraph.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-from bson import ObjectId
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class DepsgraphTest(AbstractFlamencoTest):
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-
-        from pillar.api.utils.authentication import force_cli_user
-
-        mngr_doc, account, token = self.create_manager_service_account()
-        self.mngr_id = mngr_doc['_id']
-        self.mngr_token = token['token']
-
-        # Create three test jobs, one of which is completed and two are queued.
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job 1',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.jobid1 = job['_id']
-            job = self.jmngr.api_create_job(
-                'test job 2',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.jobid2 = job['_id']
-            job = self.jmngr.api_create_job(
-                'test job 3',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.jobid3 = job['_id']
-            assert isinstance(self.jobid1, ObjectId)
-            assert isinstance(self.jobid2, ObjectId)
-            assert isinstance(self.jobid3, ObjectId)
-
-            self.set_job_status('completed', job_id=self.jobid3)
-
-            self.tasks = list(self.flamenco.db('tasks').find({
-                'job': {'$in': [self.jobid1, self.jobid2]}
-            }))
-            self.task_ids = [t['_id'] for t in self.tasks]
-
-    def test_get_clean_slate(self):
-        from dateutil.parser import parse
-
-        # Just so we have a task that's known to be last-updated.
-        self.force_task_status(0, 'claimed-by-manager')
-
-        resp = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                        auth_token=self.mngr_token)
-        depsgraph = resp.json()['depsgraph']
-        self.assertEqual(len(self.tasks), len(depsgraph))
-        self.assertEqual({unicode(t['_id']) for t in self.tasks},
-                         {t['_id'] for t in depsgraph})
-
-        # Tasks should be returned in full, no projection.
-        task1 = self.tasks[1]
-        depstask1 = next(t for t in depsgraph if t['_id'] == unicode(task1['_id']))
-        self.assertEqual(set(task1.keys()), set(depstask1.keys()))
-
-        # The 'X-Flamenco-Last-Updated' header should contain the last-changed task.
-        last_modified = parse(resp.headers['X-Flamenco-Last-Updated'])
-        with self.app.test_request_context():
-            task0 = self.flamenco.db('tasks').find_one({'_id': self.task_ids[0]})
-        self.assertEqual(task0['_updated'], last_modified)
-
-        # The tasks in the database, as well as the response, should be set to claimed-by-manager
-        with self.app.test_request_context():
-            dbtasks = self.flamenco.db('tasks').find({'_id': {'$in': self.task_ids}})
-            self.assertEqual(8 * [u'claimed-by-manager'], [task['status'] for task in dbtasks])
-        self.assertEqual(8 * [u'claimed-by-manager'], [task['status'] for task in depsgraph])
-
-    def test_get_clean_slate_some_tasks_unrunnable(self):
-        self.force_task_status(0, 'failed')
-        self.force_task_status(1, 'canceled')
-        self.force_task_status(2, 'completed')
-
-        resp = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                        auth_token=self.mngr_token)
-        depsgraph = resp.json()['depsgraph']
-        self.assertEqual(len(self.tasks) - 3, len(depsgraph))
-
-        deps_tids = {t['_id'] for t in depsgraph}
-        self.assertEqual({unicode(tid) for tid in self.task_ids[3:]}, deps_tids)
-
-        # The previously queued tasks in the database, as well as the response,
-        # should be set to claimed-by-manager
-        with self.app.test_request_context():
-            dbtasks = self.flamenco.db('tasks').find({'_id': {'$in': self.task_ids}})
-            self.assertEqual([u'failed', u'canceled', u'completed'] + 5 * [u'claimed-by-manager'],
-                             [task['status'] for task in dbtasks])
-        self.assertEqual(5 * [u'claimed-by-manager'],
-                         [task['status'] for task in depsgraph])
-
-    def test_get_subsequent_call(self):
-        import time
-        from dateutil.parser import parse
-
-        # Get a clean slate first, so that we get the timestamp of last modification
-        resp = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                        auth_token=self.mngr_token)
-        last_modified = resp.headers['X-Flamenco-Last-Updated']
-
-        # Do the subsequent call, it should return nothing.
-        self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                 auth_token=self.mngr_token,
-                 headers={'X-Flamenco-If-Updated-Since': last_modified},
-                 expected_status=304)
-
-        # Change some tasks to see what we get back.
-        time.sleep(0.05)  # sleep a bit to stabilise the test.
-        self.force_task_status(0, 'claimed-by-manager')
-        self.force_task_status(1, 'cancel-requested')
-        self.force_task_status(2, 'queued')
-
-        resp = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                        auth_token=self.mngr_token,
-                        headers={'X-Flamenco-If-Updated-Since': last_modified})
-
-        depsgraph = resp.json()['depsgraph']
-        self.assertEqual(2, len(depsgraph))  # we should not get the cancel-requested task back.
-
-        deps_tids = {t['_id'] for t in depsgraph}
-        self.assertEqual({unicode(self.task_ids[0]),
-                          unicode(self.task_ids[2])},
-                         deps_tids)
-
-        # The 'X-Flamenco-Last-Updated' header should contain the last-changed task.
-        last_modified = parse(resp.headers['X-Flamenco-Last-Updated'])
-        with self.app.test_request_context():
-            task0 = self.flamenco.db('tasks').find_one({'_id': self.task_ids[0]})
-            task2 = self.flamenco.db('tasks').find_one({'_id': self.task_ids[2]})
-        # They should be equal to second precision
-        self.assertEqual(task2['_updated'], last_modified)
-
-        self.assertEqual(task0['status'], u'claimed-by-manager')
-        self.assertEqual(task2['status'], u'claimed-by-manager')
-        self.assertEqual(2 * [u'claimed-by-manager'],
-                         [task['status'] for task in depsgraph])
diff --git a/packages/flamenco/tests/test_job_compilers.py b/packages/flamenco/tests/test_job_compilers.py
deleted file mode 100644
index ce41b328f8b02f5c0aa585d148e9791e272b8a3c..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_job_compilers.py
+++ /dev/null
@@ -1,393 +0,0 @@
-from __future__ import absolute_import
-
-import unittest
-import mock
-from bson import ObjectId
-
-
-class SleepSimpleTest(unittest.TestCase):
-    def test_job_compilation(self):
-        from flamenco.job_compilers import sleep, commands
-
-        job_doc = {
-            '_id': ObjectId(24 * 'f'),
-            'settings': {
-                'frames': '1-30, 40-44',
-                'chunk_size': 13,
-                'time_in_seconds': 3,
-            }
-        }
-        task_manager = mock.Mock()
-        compiler = sleep.Sleep(task_manager=task_manager)
-        compiler.compile(job_doc)
-
-        task_manager.api_create_task.assert_has_calls([
-            mock.call(
-                job_doc,
-                [
-                    commands.Echo(message=u'Preparing to sleep'),
-                    commands.Sleep(time_in_seconds=3),
-                ],
-                'sleep-1-13',
-            ),
-            mock.call(
-                job_doc,
-                [
-                    commands.Echo(message=u'Preparing to sleep'),
-                    commands.Sleep(time_in_seconds=3),
-                ],
-                'sleep-14-26',
-            ),
-            mock.call(
-                job_doc,
-                [
-                    commands.Echo(message=u'Preparing to sleep'),
-                    commands.Sleep(time_in_seconds=3),
-                ],
-                'sleep-27-30,40-44',
-            ),
-        ])
-
-
-class CommandTest(unittest.TestCase):
-    def test_to_dict(self):
-        from flamenco.job_compilers import commands
-
-        cmd = commands.Echo(message=u'Preparing to sleep')
-        self.assertEqual({
-            'name': 'echo',
-            'settings': {
-                'message': u'Preparing to sleep',
-            }
-        }, cmd.to_dict())
-
-
-class BlenderRenderProgressiveTest(unittest.TestCase):
-    def test_nonexr_job(self):
-        from flamenco.job_compilers import blender_render_progressive
-        from flamenco.exceptions import JobSettingError
-
-        job_doc = {
-            u'_id': ObjectId(24 * 'f'),
-            u'settings': {
-                u'frames': u'1-6',
-                u'chunk_size': 2,
-                u'render_output': u'/render/out/frames-######',
-                u'format': u'JPEG',
-                u'filepath': u'/agent327/scenes/someshot/somefile.blend',
-                u'blender_cmd': u'/path/to/blender --enable-new-depsgraph',
-                u'cycles_sample_count': 30,
-                u'cycles_num_chunks': 3,
-            }
-        }
-        task_manager = mock.Mock()
-        compiler = blender_render_progressive.BlenderRenderProgressive(task_manager=task_manager)
-
-        self.assertRaises(JobSettingError, compiler.compile, job_doc)
-
-    def test_small_job(self):
-        from flamenco.job_compilers import blender_render_progressive, commands
-
-        job_doc = {
-            u'_id': ObjectId(24 * 'f'),
-            u'settings': {
-                u'frames': u'1-6',
-                u'chunk_size': 2,
-                u'render_output': u'/render/out/frames-######',
-                u'format': u'EXR',
-                u'filepath': u'/agent327/scenes/someshot/somefile.blend',
-                u'blender_cmd': u'/path/to/blender --enable-new-depsgraph',
-                u'cycles_sample_count': 30,
-                u'cycles_num_chunks': 3,
-            }
-        }
-        task_manager = mock.Mock()
-
-        # We expect:
-        # - 1 move-out-of-way task
-        # - 3 frame chunks of 2 frames each
-        # - 3 progressive renders per frame
-        # - 2 merge tasks per frame chunk
-        # so that's a 9 render tasks and 6 merge tasks, giving 16 tasks in total.
-        task_ids = [ObjectId() for _ in range(16)]
-        task_manager.api_create_task.side_effect = task_ids
-
-        compiler = blender_render_progressive.BlenderRenderProgressive(task_manager=task_manager)
-        compiler.compile(job_doc)
-
-        task_manager.api_create_task.assert_has_calls([
-            mock.call(job_doc,
-                      [commands.MoveOutOfWay(src=u'/render/out')],
-                      u'move-existing-frames'),
-
-            # First Cycles chunk
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-1-10-frm-######',
-                    frames=u'1,2',
-                    cycles_num_chunks=3,
-                    cycles_chunk=1,
-                    cycles_samples_from=1,
-                    cycles_samples_to=10)],
-                u'render-smpl1-10-frm1,2',
-                parents=[task_ids[0]],
-                priority=0),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-1-10-frm-######',
-                    frames=u'3,4',
-                    cycles_num_chunks=3,
-                    cycles_chunk=1,
-                    cycles_samples_from=1,
-                    cycles_samples_to=10)],
-                u'render-smpl1-10-frm3,4',
-                parents=[task_ids[0]],
-                priority=0),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-1-10-frm-######',
-                    frames=u'5,6',
-                    cycles_num_chunks=3,
-                    cycles_chunk=1,
-                    cycles_samples_from=1,
-                    cycles_samples_to=10)],
-                u'render-smpl1-10-frm5,6',
-                parents=[task_ids[0]],
-                priority=0),
-
-            # Second Cycles chunk
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-11-20-frm-######',
-                    frames=u'1,2',
-                    cycles_num_chunks=3,
-                    cycles_chunk=2,
-                    cycles_samples_from=11,
-                    cycles_samples_to=20)],
-                u'render-smpl11-20-frm1,2',
-                parents=[task_ids[0]],
-                priority=-10),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-11-20-frm-######',
-                    frames=u'3,4',
-                    cycles_num_chunks=3,
-                    cycles_chunk=2,
-                    cycles_samples_from=11,
-                    cycles_samples_to=20)],
-                u'render-smpl11-20-frm3,4',
-                parents=[task_ids[0]],
-                priority=-10),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-11-20-frm-######',
-                    frames=u'5,6',
-                    cycles_num_chunks=3,
-                    cycles_chunk=2,
-                    cycles_samples_from=11,
-                    cycles_samples_to=20)],
-                u'render-smpl11-20-frm5,6',
-                parents=[task_ids[0]],
-                priority=-10),
-
-            # First merge pass
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000001.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000001.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000001.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000002.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000002.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000002.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl20-frm1,2',
-                parents=[task_ids[1], task_ids[4]],
-                priority=-11),
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000003.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000003.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000003.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000004.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000004.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000004.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl20-frm3,4',
-                parents=[task_ids[2], task_ids[5]],
-                priority=-11),
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000005.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000005.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000005.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/render-smpl-1-10-frm-000006.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-11-20-frm-000006.exr',
-                        output=u'/render/out/_intermediate/merge-smpl-20-frm-000006.exr',
-                        weight1=10,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl20-frm5,6',
-                parents=[task_ids[3], task_ids[6]],
-                priority=-11),
-
-            # Third Cycles chunk
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-21-30-frm-######',
-                    frames=u'1,2',
-                    cycles_num_chunks=3,
-                    cycles_chunk=3,
-                    cycles_samples_from=21,
-                    cycles_samples_to=30)],
-                u'render-smpl21-30-frm1,2',
-                parents=[task_ids[0]],
-                priority=-20),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-21-30-frm-######',
-                    frames=u'3,4',
-                    cycles_num_chunks=3,
-                    cycles_chunk=3,
-                    cycles_samples_from=21,
-                    cycles_samples_to=30)],
-                u'render-smpl21-30-frm3,4',
-                parents=[task_ids[0]],
-                priority=-20),
-            mock.call(
-                job_doc,
-                [commands.BlenderRenderProgressive(
-                    blender_cmd=u'/path/to/blender --enable-new-depsgraph',
-                    filepath=u'/agent327/scenes/someshot/somefile.blend',
-                    format=u'EXR',
-                    render_output=u'/render/out/_intermediate/render-smpl-21-30-frm-######',
-                    frames=u'5,6',
-                    cycles_num_chunks=3,
-                    cycles_chunk=3,
-                    cycles_samples_from=21,
-                    cycles_samples_to=30)],
-                u'render-smpl21-30-frm5,6',
-                parents=[task_ids[0]],
-                priority=-20),
-
-            # Final merge pass
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000001.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000001.exr',
-                        output=u'/render/out/frames-000001.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000002.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000002.exr',
-                        output=u'/render/out/frames-000002.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl30-frm1,2',
-                parents=[task_ids[7], task_ids[10]],
-                priority=-21),
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000003.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000003.exr',
-                        output=u'/render/out/frames-000003.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000004.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000004.exr',
-                        output=u'/render/out/frames-000004.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl30-frm3,4',
-                parents=[task_ids[8], task_ids[11]],
-                priority=-21),
-            mock.call(
-                job_doc,
-                [
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000005.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000005.exr',
-                        output=u'/render/out/frames-000005.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                    commands.MergeProgressiveRenders(
-                        input1=u'/render/out/_intermediate/merge-smpl-20-frm-000006.exr',
-                        input2=u'/render/out/_intermediate/render-smpl-21-30-frm-000006.exr',
-                        output=u'/render/out/frames-000006.exr',
-                        weight1=20,
-                        weight2=10,
-                    ),
-                ],
-                u'merge-to-smpl30-frm5,6',
-                parents=[task_ids[9], task_ids[12]],
-                priority=-21),
-        ])
diff --git a/packages/flamenco/tests/test_job_manager.py b/packages/flamenco/tests/test_job_manager.py
deleted file mode 100644
index f2a266d2bd859cfa288d5d28589e4c3913b6d84e..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_job_manager.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-import mock
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class JobManagerTest(AbstractFlamencoTest):
-    def test_create_job(self):
-        from pillar.api.utils.authentication import force_cli_user
-
-        manager, _, _ = self.create_manager_service_account()
-
-        with self.app.test_request_context():
-            force_cli_user()
-            self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 5,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                manager['_id'],
-            )
-
-        # Test the jobs
-        with self.app.test_request_context():
-            jobs_coll = self.flamenco.db('jobs')
-
-            jobs = list(jobs_coll.find())
-            self.assertEqual(1, len(jobs))
-            job = jobs[0]
-
-            self.assertEqual(u'Wörk wørk w°rk.', job['description'])
-            self.assertEqual(u'sleep', job['job_type'])
-
-        # Test the tasks
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-
-            tasks = list(tasks_coll.find())
-            self.assertEqual(2, len(tasks))
-            task = tasks[0]
-
-            self.assertEqual(u'sleep-12-16', task['name'])
-            self.assertEqual({
-                u'name': u'echo',
-                u'settings': {
-                    u'message': u'Preparing to sleep',
-                }
-            }, task['commands'][0])
-
-            self.assertEqual({
-                u'name': u'sleep',
-                u'settings': {
-                    u'time_in_seconds': 3,
-                }
-            }, task['commands'][1])
-
-
-class JobStatusChangeTest(AbstractFlamencoTest):
-    def setUp(self, **kwargs):
-        super(JobStatusChangeTest, self).setUp(**kwargs)
-
-        # Create a job with the same number of tasks as there are task statuses.
-        from pillar.api.utils.authentication import force_cli_user
-        from flamenco.eve_settings import tasks_schema
-
-        manager, _, token = self.create_manager_service_account()
-        self.mngr_token = token['token']
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'blender-render',
-                {
-                    'blender_cmd': u'{blender}',
-                    'filepath': u'/my/blend.file',
-                    'frames': u'12-18, 20-25',
-                    'chunk_size': 2,
-                    'time_in_seconds': 3,
-                    'render_output': u'/not-relevant-now/####',
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                manager['_id'],
-            )
-            self.job_id = job['_id']
-
-            # Fetch the task IDs and set the task statuses to a fixed list.
-            tasks_coll = self.flamenco.db('tasks')
-            tasks = tasks_coll.find({
-                'job': self.job_id,
-                'name': {'$regex': '^blender-render-'},  # don't consider move-out-of-way task.
-            }, projection={'_id': 1})
-            self.task_ids = [task['_id'] for task in tasks]
-
-        self.assertEqual(len(tasks_schema['status']['allowed']), len(self.task_ids))
-        self.force_task_status(0, 'queued')
-        self.force_task_status(1, 'claimed-by-manager')
-        self.force_task_status(2, 'completed')
-        self.force_task_status(3, 'active')
-        self.force_task_status(4, 'canceled')
-        self.force_task_status(5, 'failed')
-        self.force_task_status(6, 'cancel-requested')
-
-    def assert_task_status(self, task_idx, expected_status):
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-            task = tasks_coll.find_one({'_id': self.task_ids[task_idx]},
-                                       projection={'status': 1})
-
-        self.assertIsNotNone(task)
-        self.assertEqual(task['status'], unicode(expected_status),
-                         "Task %i:\n   has status: '%s'\n but expected: '%s'" % (
-                             task_idx, task['status'], expected_status))
-
-    def test_status_from_queued_to_active(self):
-        # This shouldn't change any of the tasks.
-        self.force_job_status('queued')
-        self.set_job_status('active')
-
-        self.assert_task_status(0, 'queued')  # was: queued
-        self.assert_task_status(1, 'claimed-by-manager')  # was: claimed-by-manager
-        self.assert_task_status(2, 'completed')  # was: completed
-        self.assert_task_status(3, 'active')  # was: active
-        self.assert_task_status(4, 'canceled')  # was: canceled
-        self.assert_task_status(5, 'failed')  # was: failed
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    def test_status_from_active_to_cancel_requested(self):
-        # This should cancel all tasks that could possibly still run.
-        self.force_job_status('active')
-        self.set_job_status('cancel-requested')
-
-        self.assert_task_status(0, 'canceled')  # was: queued
-        self.assert_task_status(1, 'cancel-requested')  # was: claimed-by-manager
-        self.assert_task_status(2, 'completed')  # was: completed
-        self.assert_task_status(3, 'cancel-requested')  # was: active
-        self.assert_task_status(4, 'canceled')  # was: canceled
-        self.assert_task_status(5, 'failed')  # was: failed
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    def test_status_from_canceled_to_queued(self):
-        # This should re-queue all non-completed tasks.
-        self.force_job_status('canceled')
-        self.set_job_status('queued')
-
-        self.assert_task_status(0, 'queued')  # was: queued
-        self.assert_task_status(1, 'queued')  # was: claimed-by-manager
-        self.assert_task_status(2, 'completed')  # was: completed
-        self.assert_task_status(3, 'queued')  # was: active
-        self.assert_task_status(4, 'queued')  # was: canceled
-        self.assert_task_status(5, 'queued')  # was: failed
-
-        # Cancel-requested tasks are not allowed to be re-queued; it would create race conditions.
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    def test_status_from_completed_to_queued(self):
-        # This should re-queue all tasks.
-        self.force_job_status('completed')
-        self.set_job_status('queued')
-
-        self.assert_task_status(0, 'queued')  # was: queued
-        self.assert_task_status(1, 'queued')  # was: claimed-by-manager
-        self.assert_task_status(2, 'queued')  # was: completed
-        self.assert_task_status(3, 'queued')  # was: active
-        self.assert_task_status(4, 'queued')  # was: canceled
-        self.assert_task_status(5, 'queued')  # was: failed
-
-        # Cancel-requested tasks are not allowed to be re-queued; it would create race conditions.
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    def test_status_from_active_to_failed(self):
-        # If the job fails, it cancels all remaining tasks.
-        self.force_job_status('active')
-        self.set_job_status('failed')
-
-        self.assert_task_status(0, 'canceled')  # was: queued
-        self.assert_task_status(1, 'cancel-requested')  # was: claimed-by-manager
-        self.assert_task_status(2, 'completed')  # was: completed
-        self.assert_task_status(3, 'cancel-requested')  # was: active
-        self.assert_task_status(4, 'canceled')  # was: canceled
-        self.assert_task_status(5, 'failed')  # was: failed
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    def test_status_from_active_to_completed(self):
-        # Shouldn't do anything, as going to completed is a result of all tasks being completed.
-        self.force_job_status('active')
-        self.set_job_status('completed')
-
-        self.assert_task_status(0, 'queued')  # was: queued
-        self.assert_task_status(1, 'claimed-by-manager')  # was: claimed-by-manager
-        self.assert_task_status(2, 'completed')  # was: completed
-        self.assert_task_status(3, 'active')  # was: active
-        self.assert_task_status(4, 'canceled')  # was: canceled
-        self.assert_task_status(5, 'failed')  # was: failed
-        self.assert_task_status(6, 'cancel-requested')  # was: cancel-requested
-
-    @mock.patch('flamenco.jobs.JobManager.handle_job_status_change')
-    def test_put_job(self, handle_job_status_change):
-        """Test that flamenco.jobs.JobManager.handle_job_status_change is called when we PUT."""
-
-        from pillar.api.utils import remove_private_keys
-
-        self.create_user(24 * 'a', roles=('admin',))
-        self.create_valid_auth_token(24 * 'a', token='admin-token')
-
-        json_job = self.get('/api/flamenco/jobs/%s' % self.job_id,
-                            auth_token='admin-token').json()
-
-        json_job['status'] = 'canceled'
-
-        self.put('/api/flamenco/jobs/%s' % self.job_id,
-                 json=remove_private_keys(json_job),
-                 headers={'If-Match': json_job['_etag']},
-                 auth_token='admin-token')
-
-        handle_job_status_change.assert_called_once_with(self.job_id, 'queued', 'canceled')
diff --git a/packages/flamenco/tests/test_job_patch.py b/packages/flamenco/tests/test_job_patch.py
deleted file mode 100644
index 19d589a5fbfdb28378219e03da5b1f722eee7198..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_job_patch.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-import mock
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class JobPatchingTest(AbstractFlamencoTest):
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-
-        from pillar.api.utils.authentication import force_cli_user
-
-        mngr_doc, account, token = self.create_manager_service_account()
-        self.mngr_id = mngr_doc['_id']
-        self.mngr_token = token['token']
-
-        self.create_user(user_id=24 * 'f', roles={u'flamenco-admin'})
-        self.create_valid_auth_token(24 * 'f', u'fladmin-token')
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.job_id = job['_id']
-
-    def test_set_job_invalid_status(self):
-        self.patch(
-            '/api/flamenco/jobs/%s' % self.job_id,
-            json={'op': 'set-job-status',
-                  'status': 'finished'},
-            auth_token='fladmin-token',
-            expected_status=422,
-        )
-
-        # Check that the status in the database didn't change.
-        with self.app.test_request_context():
-            jobs_coll = self.flamenco.db('jobs')
-            job = jobs_coll.find_one({'_id': self.job_id})
-            self.assertEqual('queued', job['status'])
-
-    def test_set_job_valid_status(self):
-        self.patch(
-            '/api/flamenco/jobs/%s' % self.job_id,
-            json={'op': 'set-job-status',
-                  'status': 'completed'},
-            auth_token='fladmin-token',
-            expected_status=204,
-        )
-
-        # Check that the status in the database changed too.
-        with self.app.test_request_context():
-            jobs_coll = self.flamenco.db('jobs')
-            job = jobs_coll.find_one({'_id': self.job_id})
-            self.assertEqual('completed', job['status'])
-
-    @mock.patch('flamenco.jobs.JobManager.handle_job_status_change')
-    def test_task_status_change_due_to_job_patch(self, mock_handle_job_status_change):
-        self.assert_job_status('queued')
-
-        self.patch(
-            '/api/flamenco/jobs/%s' % self.job_id,
-            json={'op': 'set-job-status',
-                  'status': 'completed'},
-            auth_token='fladmin-token',
-            expected_status=204,
-        )
-
-        mock_handle_job_status_change.assert_called_with(
-            self.job_id, 'queued', 'completed')
diff --git a/packages/flamenco/tests/test_setup_for_flamenco.py b/packages/flamenco/tests/test_setup_for_flamenco.py
deleted file mode 100644
index 06cee82f67ae78a4c1a08204e28868919451d850..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_setup_for_flamenco.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import pillar.tests.common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class TaskWorkflowTest(AbstractFlamencoTest):
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-        self.project_id, _ = self.ensure_project_exists()
-        self.create_valid_auth_token(ctd.EXAMPLE_PROJECT_OWNER_ID, 'token')
-
-    def test_custom_properties(self):
-        """Projects should get their properties dict."""
-
-        with self.app.test_request_context():
-            proj_coll = self.app.data.driver.db['projects']
-            project = proj_coll.find_one({'_id': self.project_id})
-            aprops = project['extension_props']['flamenco']
-            self.assertIsInstance(aprops, dict)
-
-    def test_saving_api(self):
-        """Ensures that Eve accepts a Flamenco project as valid."""
-
-        import pillar.api.utils
-
-        url = '/api/projects/%s' % self.project_id
-
-        resp = self.get(url)
-        proj = resp.json()
-
-        put_proj = pillar.api.utils.remove_private_keys(proj)
-
-        self.put(url,
-                 json=put_proj,
-                 auth_token='token',
-                 headers={'If-Match': proj['_etag']})
diff --git a/packages/flamenco/tests/test_task_manager.py b/packages/flamenco/tests/test_task_manager.py
deleted file mode 100644
index 2a7570bc3ebe012b7f55e516d21ca344db07fe38..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_task_manager.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class TaskManagerTest(AbstractFlamencoTest):
-    def test_create_task(self):
-        from pillar.api.utils.authentication import force_cli_user
-        from flamenco.job_compilers import commands
-
-        manager, _, _ = self.create_manager_service_account()
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job_doc = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep', {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 7,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                manager['_id'],
-            )
-
-            self.tmngr.api_create_task(
-                job_doc,
-                [
-                    commands.Echo(message=u'ẑžƶźz'),
-                    commands.Sleep(time_in_seconds=3),
-                ],
-                'sleep-1-13',
-            )
-
-        # Now test the database contents.
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-            dbtasks = list(tasks_coll.find())
-            self.assertEqual(3, len(dbtasks))  # 2 of compiled job + the one we added after.
-
-            dbtask = dbtasks[-1]
-
-            self.assertEqual({
-                u'name': u'echo',
-                u'settings': {
-                    u'message': u'ẑžƶźz',
-                }
-            }, dbtask['commands'][0])
-
-            self.assertEqual({
-                u'name': u'sleep',
-                u'settings': {
-                    u'time_in_seconds': 3,
-                }
-            }, dbtask['commands'][1])
-
-    def test_api_find_jobfinal_tasks(self):
-        from pillar.api.utils.authentication import force_cli_user
-        from flamenco.job_compilers import commands
-
-        manager, _, _ = self.create_manager_service_account()
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job_doc = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep', {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 7,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                manager['_id'],
-            )
-            job_id = job_doc['_id']
-
-            # Find the tasks created so far, use them as parents.
-            tasks = self.flamenco.db('tasks').find({'job': job_id},
-                                                   projection={'_id': 1})
-            task_ids = [t['_id'] for t in tasks]
-
-            # dependent task that is used as a single parent.
-            taskid1 = self.tmngr.api_create_task(
-                job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 1', parents=task_ids,
-            )
-
-            # task dependent on multiple tasks that is not used as a parent.
-            taskid2 = self.tmngr.api_create_task(
-                job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 2', parents=task_ids,
-            )
-
-            # task dependent on a single task that is not used as a parent.
-            taskid3 = self.tmngr.api_create_task(
-                job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 3', parents=[taskid1],
-            )
-
-            # independent task
-            taskid4 = self.tmngr.api_create_task(
-                job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 4',
-            )
-
-            job_enders = self.tmngr.api_find_job_enders(job_id)
-            self.assertEqual({taskid2, taskid3, taskid4}, set(job_enders))
diff --git a/packages/flamenco/tests/test_task_patch.py b/packages/flamenco/tests/test_task_patch.py
deleted file mode 100644
index bfd7c26284223d16cd739c9da496e82b1d843df2..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_task_patch.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-from bson import ObjectId
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class TaskPatchingTest(AbstractFlamencoTest):
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-
-        from pillar.api.utils.authentication import force_cli_user
-
-        mngr_doc, account, token = self.create_manager_service_account()
-        self.mngr_id = mngr_doc['_id']
-        self.mngr_token = token['token']
-
-        self.create_user(user_id=24 * 'f', roles={u'flamenco-admin'})
-        self.create_valid_auth_token(24 * 'f', u'fladmin-token')
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.job_id = job['_id']
-
-    def test_set_task_invalid_status(self):
-        chunk = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        task = chunk[0]
-        task_url = '/api/flamenco/tasks/%s' % task['_id']
-
-        self.patch(
-            task_url,
-            json={'op': 'set-task-status',
-                  'status': 'finished',
-                  },
-            auth_token='fladmin-token',
-            expected_status=422,
-        )
-
-        # Check that the status in the database didn't change.
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-            task = tasks_coll.find_one({'_id': ObjectId(task['_id'])})
-            self.assertEqual('claimed-by-manager', task['status'])
-
-    def test_set_task_valid_status(self):
-        chunk = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        task = chunk[0]
-        task_url = '/api/flamenco/tasks/%s' % task['_id']
-
-        self.patch(
-            task_url,
-            json={'op': 'set-task-status',
-                  'status': 'completed',
-                  },
-            auth_token='fladmin-token',
-            expected_status=204,
-        )
-
-        # Check that the status in the database changed too.
-        with self.app.test_request_context():
-            tasks_coll = self.flamenco.db('tasks')
-            task = tasks_coll.find_one({'_id': ObjectId(task['_id'])})
-            self.assertEqual('completed', task['status'])
-
-    def test_job_status_change_due_to_task_patch(self):
-        """A job should be marked as completed after all tasks are completed."""
-
-        self.assert_job_status('queued')
-
-        # The test job consists of 4 tasks; get their IDs through the scheduler.
-        # This should set the job status to active.
-        tasks = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        self.assertEqual(4, len(tasks))
-
-        # After setting tasks 1-3 to 'completed' the job should still not be completed.
-        for task in tasks[:-1]:
-            self.patch(
-                '/api/flamenco/tasks/%s' % task['_id'],
-                json={'op': 'set-task-status', 'status': 'completed'},
-                auth_token='fladmin-token',
-                expected_status=204,
-            )
-        self.assert_job_status('active')
-
-        self.patch(
-            '/api/flamenco/tasks/%s' % tasks[-1]['_id'],
-            json={'op': 'set-task-status', 'status': 'completed'},
-            auth_token='fladmin-token',
-            expected_status=204,
-        )
-        self.assert_job_status('completed')
diff --git a/packages/flamenco/tests/test_task_update_batch.py b/packages/flamenco/tests/test_task_update_batch.py
deleted file mode 100644
index a8996289459f2817045f07a7aa3f4ea2e717ae1b..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_task_update_batch.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# -*- encoding: utf-8 -*-
-from __future__ import absolute_import
-
-from bson import ObjectId
-
-from pillar.tests import common_test_data as ctd
-from abstract_flamenco_test import AbstractFlamencoTest
-
-
-class AbstractTaskBatchUpdateTest(AbstractFlamencoTest):
-    TASK_COUNT = 0
-
-    def setUp(self, **kwargs):
-        AbstractFlamencoTest.setUp(self, **kwargs)
-
-        mngr_doc, account, token = self.create_manager_service_account()
-        self.mngr_id = mngr_doc['_id']
-        self.mngr_token = token['token']
-
-    def do_schedule_tasks(self):
-        # The test job consists of 4 tasks; get their IDs through the scheduler.
-        # This should set the task status to claimed-by-manager.
-        tasks = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        # TODO: maybe claimed-by-manager?
-        # self.assert_job_status('active')
-        self.assertEqual(self.TASK_COUNT, len(tasks))
-        return tasks
-
-    def do_batch_update(self, tasks, task_indices, task_statuses, expect_cancel_task_ids=()):
-        assert len(task_indices) == len(task_statuses)
-        update_batch = [{'_id': str(ObjectId()),
-                         'task_id': tasks[idx]['_id'],
-                         'task_status': status}
-                        for idx, status in zip(task_indices, task_statuses)
-                        ]
-        resp = self.post('/api/flamenco/managers/%s/task-update-batch' % self.mngr_id,
-                         json=update_batch,
-                         auth_token=self.mngr_token)
-        resp_json = resp.json()
-
-        self.assertEqual({item['_id'] for item in update_batch},
-                         set(resp_json['handled_update_ids']))
-        if expect_cancel_task_ids:
-            self.assertEqual(set(expect_cancel_task_ids), set(resp_json['cancel_task_ids']))
-        else:
-            self.assertNotIn('cancel_task_ids', resp_json)
-
-
-class TaskBatchUpdateTest(AbstractTaskBatchUpdateTest):
-    TASK_COUNT = 4
-
-    def setUp(self, **kwargs):
-        AbstractTaskBatchUpdateTest.setUp(self, **kwargs)
-
-        from pillar.api.utils.authentication import force_cli_user
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '12-18, 20-22',
-                    'chunk_size': 3,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.job_id = job['_id']
-
-    def test_set_task_invalid_status(self):
-        chunk = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        task = chunk[0]
-
-        # A warning should be logged and the status should be rejected.
-        # The rest of the update should be handled correctly, though.
-        task_update_id = 24 * '0'
-        resp = self.post('/api/flamenco/managers/%s/task-update-batch' % self.mngr_id,
-                         auth_token=self.mngr_token,
-                         json=[{
-                             '_id': task_update_id,
-                             'task_id': task['_id'],
-                             'task_status': 'je-moeder',
-                             'activity': 'testing stuff',
-                         }])
-
-        self.assertEqual(resp.json()['handled_update_ids'], [task_update_id])
-
-        db_task = self.assert_task_status(task['_id'], 'claimed-by-manager')
-        self.assertEqual(db_task['activity'], 'testing stuff')
-
-    def test_illegal_active_after_cancel_requested(self):
-        from flamenco import current_flamenco
-
-        chunk = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        task = chunk[0]
-
-        # Request task cancellation after it was received by the manager.
-        task_id = ObjectId(task['_id'])
-        with self.app.test_request_context():
-            current_flamenco.update_status('tasks', task_id, 'cancel-requested')
-
-        # A warning should be logged, the update should be accepted, but the status not changed.
-        task_update_id = 24 * '0'
-        resp = self.post('/api/flamenco/managers/%s/task-update-batch' % self.mngr_id,
-                         auth_token=self.mngr_token,
-                         json=[{
-                             '_id': task_update_id,
-                             'task_id': task['_id'],
-                             'task_status': 'active',
-                         }])
-
-        resp_json = resp.json()
-        self.assertEqual(resp_json['handled_update_ids'], [task_update_id])
-        self.assertEqual(resp_json['cancel_task_ids'], [task['_id']])
-
-        self.assert_task_status(task_id, 'cancel-requested')
-
-    def test_canceled_after_cancel_requested(self):
-        from flamenco import current_flamenco
-
-        chunk = self.get('/api/flamenco/managers/%s/depsgraph' % self.mngr_id,
-                         auth_token=self.mngr_token).json()['depsgraph']
-        task = chunk[0]
-
-        # Request task cancellation after it was received by the manager.
-        task_id = ObjectId(task['_id'])
-        with self.app.test_request_context():
-            current_flamenco.update_status('tasks', task_id, 'cancel-requested')
-
-        # The manager should be able to set the task status to 'canceled'
-        task_update_id = 24 * '0'
-        resp = self.post('/api/flamenco/managers/%s/task-update-batch' % self.mngr_id,
-                         auth_token=self.mngr_token,
-                         json=[{
-                             '_id': task_update_id,
-                             'task_id': task['_id'],
-                             'task_status': 'canceled',
-                         }])
-        resp_json = resp.json()
-        self.assertEqual(resp_json['handled_update_ids'], [task_update_id])
-
-        # The task should no longer be cancel-requested due to the update we just pushed.
-        self.assertNotIn('cancel_task_ids', resp_json)
-        self.assert_task_status(task_id, 'canceled')
-
-    def test_job_status_complete_due_to_task_update(self):
-        """A task update batch should influence the job status."""
-
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # After setting tasks 0-2 to 'completed' the job should still not be completed.
-        self.do_batch_update(tasks, [0, 1, 2], 3 * ['completed'])
-        self.assert_job_status('active')
-
-        # In the final batch we complete the remaining task.
-        self.do_batch_update(tasks, [3], ['completed'])
-        self.assert_job_status('completed')
-
-    def test_job_status_failed_due_to_task_update(self):
-        """A task update batch should influence the job status."""
-
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # After setting a single task to 'failed', the job should be 'failed', and the remaining
-        # tasks should be canceled. This is only true in this test because a single task is more
-        # than the threshold of nr of tasks that are allowed to fail.
-        self.maxDiff = None
-        self.do_batch_update(
-            tasks, [1], ['failed'],
-            expect_cancel_task_ids={tasks[0]['_id'], tasks[2]['_id'], tasks[3]['_id']})
-        self.assert_job_status('failed')
-
-    def test_job_status_active_after_task_update(self):
-        """A job should go to active when its tasks are being updated.
-        """
-
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # Any of these statuses should set the job to active.
-        for status in (u'active', u'completed'):
-            self.force_job_status('queued')
-            self.do_batch_update(tasks, [0], [status])
-            self.assert_job_status('active')
-
-    def test_job_status_canceled_due_to_task_update(self):
-        """When the last cancel-requested task goes to canceled, a cancel-requested job should too.
-        """
-
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # We complete one task before attempting a cancel at the job level.
-        self.do_batch_update(tasks, [0], ['completed'])
-        self.assert_job_status('active')
-
-        self.set_job_status('cancel-requested')
-
-        # This should have cancel-requested the remaining tasks.
-        self.assert_task_status(tasks[0]['_id'], 'completed')
-        self.assert_task_status(tasks[1]['_id'], 'cancel-requested')
-        self.assert_task_status(tasks[2]['_id'], 'cancel-requested')
-        self.assert_task_status(tasks[3]['_id'], 'cancel-requested')
-
-        # Once all tasks are confirmed to be canceled, the job should go to canceled too.
-        self.do_batch_update(tasks, [1, 2, 3], 3 * ['canceled'])
-        self.assert_job_status('canceled')
-
-    def test_job_status_canceled_after_request_with_all_tasks_canceled(self):
-        """Same as test_job_status_canceled_due_to_task_update(), except that in this test
-        all tasks are in a state that can be immediately cancelled without waiting for the
-        manager. As a result, there won't be any incoming task updates that trigger the
-        cancel-requested to canceled state transition.
-        """
-
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # All tasks are queued when we request cancellation of the job.
-        self.do_batch_update(tasks, [0, 1, 2, 3], 4 * ['queued'])
-        self.assert_job_status('queued')
-
-        self.set_job_status('cancel-requested')
-
-        # This should have cancel-requested the remaining tasks.
-        self.assert_task_status(tasks[0]['_id'], 'canceled')
-        self.assert_task_status(tasks[1]['_id'], 'canceled')
-        self.assert_task_status(tasks[2]['_id'], 'canceled')
-        self.assert_task_status(tasks[3]['_id'], 'canceled')
-
-        # Without confirmation from the Manager, the job should go to canceled.
-        self.assert_job_status('canceled')
-
-
-class LargeTaskBatchUpdateTest(AbstractTaskBatchUpdateTest):
-    """Similar tests to TaskBatchUpdateTest, but with a job consisting of many more tasks."""
-
-    TASK_COUNT = 100
-
-    def setUp(self, **kwargs):
-        AbstractTaskBatchUpdateTest.setUp(self, **kwargs)
-
-        from pillar.api.utils.authentication import force_cli_user
-
-        with self.app.test_request_context():
-            force_cli_user()
-            job = self.jmngr.api_create_job(
-                'test job',
-                u'Wörk wørk w°rk.',
-                'sleep',
-                {
-                    'frames': '1-100',
-                    'chunk_size': 1,
-                    'time_in_seconds': 3,
-                },
-                self.proj_id,
-                ctd.EXAMPLE_PROJECT_OWNER_ID,
-                self.mngr_id,
-            )
-            self.job_id = job['_id']
-
-    def test_job_status_not_failed_due_to_few_task_failures(self):
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # After setting a single task to 'failed', the job should not be 'failed' yet.
-        self.maxDiff = None
-        self.do_batch_update(
-            tasks, [1], ['failed'],
-            expect_cancel_task_ids=set())
-        self.assert_job_status('active')
-
-        # After setting 8 more, job should still be 'active'
-        self.do_batch_update(
-            tasks, [2, 3, 4, 5, 6, 7, 8, 9], 8 * ['failed'],
-            expect_cancel_task_ids=set())
-        self.assert_job_status('active')
-
-    def test_job_status_failed_due_to_many_task_failures(self):
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        # After setting 10 tasks to failed, job should be 'failed' and other tasks should cancel.
-        self.do_batch_update(
-            tasks, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10 * ['failed'],
-            expect_cancel_task_ids={t['_id'] for t in tasks[10:]})
-        self.assert_job_status('failed')
-
-    def test_job_status_failed_with_mixture_of_canceled_and_failed_tasks(self):
-        self.force_job_status('queued')
-        tasks = self.do_schedule_tasks()
-
-        self.do_batch_update(
-            tasks, range(14), 14 * ['claimed-by-manager'])
-
-        self.do_batch_update(
-            tasks, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10 * ['failed'],
-            expect_cancel_task_ids={t['_id'] for t in tasks[10:]})
-        self.assert_job_status('failed')
-
-        self.do_batch_update(
-            tasks, [10, 11, 12, 13], 4 * ['canceled'],
-            expect_cancel_task_ids={t['_id'] for t in tasks[14:]})
-        self.assert_job_status('failed')
diff --git a/packages/flamenco/tests/test_utils.py b/packages/flamenco/tests/test_utils.py
deleted file mode 100644
index 34da6e36dbcf573f524fc70000f3beb5c38ff7fe..0000000000000000000000000000000000000000
--- a/packages/flamenco/tests/test_utils.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from __future__ import absolute_import
-
-import unittest
-
-
-class FrameRangeTest(unittest.TestCase):
-    def test_frame_range_parse(self):
-        from flamenco.utils import frame_range_parse
-
-        self.assertEqual([], frame_range_parse(None))
-        self.assertEqual([], frame_range_parse(''))
-        self.assertEqual([1], frame_range_parse('1'))
-        self.assertEqual([1, 2, 3], frame_range_parse('1, 2, 3'))
-        self.assertEqual([1, 2, 3], frame_range_parse('1-3'))
-        self.assertEqual([1, 2, 3, 4], frame_range_parse('1, 2-4'))
-        self.assertEqual([1, 2, 3, 4], frame_range_parse('1,2-4'))
-        self.assertEqual([0, 531443, 5315886, 9999993414, 9999993415, 9999993416],
-                         frame_range_parse('0,531443,    5315886,  9999993414 - 9999993416'))
-
-    def test_frame_range_merge(self):
-        from flamenco.utils import frame_range_merge
-
-        self.assertEqual('', frame_range_merge(None))
-        self.assertEqual('', frame_range_merge([]))
-        self.assertEqual('1', frame_range_merge([1]))
-        self.assertEqual('18,20,21', frame_range_merge([18, 20, 21]))
-        self.assertEqual('18,20,21,23-25', frame_range_merge([18, 20, 21, 23, 24, 25]))
-        self.assertEqual('1-3', frame_range_merge([1, 2, 3]))
-        self.assertEqual('51,66-103', frame_range_merge([51] + list(range(66, 104))))
-        self.assertEqual('0,531443,5315886,9999993414-9999993416',
-                         frame_range_merge(
-                             [0, 531443, 5315886, 9999993414, 9999993415, 9999993416]))
-
-    def test_frame_range_merge_blender_style(self):
-        from flamenco.utils import frame_range_merge
-
-        self.assertEqual('', frame_range_merge(None, blender_style=True))
-        self.assertEqual('', frame_range_merge([], blender_style=True))
-        self.assertEqual('1', frame_range_merge([1], blender_style=True))
-        self.assertEqual('18,20,21', frame_range_merge([18, 20, 21], blender_style=True))
-        self.assertEqual('18,20,21,23..25',
-                         frame_range_merge([18, 20, 21, 23, 24, 25], blender_style=True))
-        self.assertEqual('1..3', frame_range_merge([1, 2, 3], blender_style=True))
-        self.assertEqual('51,66..103',
-                         frame_range_merge([51] + list(range(66, 104)), blender_style=True))
-        self.assertEqual('0,531443,5315886,9999993414..9999993416',
-                         frame_range_merge(
-                             [0, 531443, 5315886, 9999993414, 9999993415, 9999993416],
-                             blender_style=True))
-
-    def test_iter_frame_range(self):
-        from flamenco.utils import iter_frame_range
-
-        self.assertEqual([], list(iter_frame_range(None, 1)))
-        self.assertEqual(
-            [
-                [4, 5, 6, 7],
-                [8, 9, 10, 13],
-                [14, 15, 16],
-            ],
-            list(iter_frame_range('4-10, 13-16', 4)))
-
-    def test_camel_case_to_lower_case_underscore(self):
-        from flamenco.utils import camel_case_to_lower_case_underscore as cctlcu
-
-        self.assertIsInstance(cctlcu(u'word'), unicode)
-        self.assertIsInstance(cctlcu('word'), str)
-
-        self.assertEqual('word', cctlcu('word'))
-        self.assertEqual(u'word', cctlcu(u'word'))
-        self.assertEqual('camel_case', cctlcu('CamelCase'))
-        self.assertEqual('camel_case', cctlcu('camelCase'))
-        self.assertEqual('camel_case_with_many_words', cctlcu('CamelCaseWithManyWords'))
-        self.assertEqual('', cctlcu(''))
-        self.assertIs(None, cctlcu(None))
diff --git a/packages/flamenco-worker-python/requirements-dev.txt b/requirements-dev.txt
similarity index 100%
rename from packages/flamenco-worker-python/requirements-dev.txt
rename to requirements-dev.txt
diff --git a/packages/flamenco-worker-python/requirements-test.txt b/requirements-test.txt
similarity index 100%
rename from packages/flamenco-worker-python/requirements-test.txt
rename to requirements-test.txt
diff --git a/packages/flamenco-worker-python/requirements.txt b/requirements.txt
similarity index 100%
rename from packages/flamenco-worker-python/requirements.txt
rename to requirements.txt
diff --git a/packages/flamenco-worker-python/setup.cfg b/setup.cfg
similarity index 100%
rename from packages/flamenco-worker-python/setup.cfg
rename to setup.cfg
diff --git a/packages/flamenco-worker-python/setup.py b/setup.py
similarity index 100%
rename from packages/flamenco-worker-python/setup.py
rename to setup.py
diff --git a/packages/flamenco-worker-python/system-integration/systemd/crontab b/system-integration/systemd/crontab
similarity index 100%
rename from packages/flamenco-worker-python/system-integration/systemd/crontab
rename to system-integration/systemd/crontab
diff --git a/packages/flamenco-worker-python/system-integration/systemd/flamenco-worker.service b/system-integration/systemd/flamenco-worker.service
similarity index 100%
rename from packages/flamenco-worker-python/system-integration/systemd/flamenco-worker.service
rename to system-integration/systemd/flamenco-worker.service
diff --git a/packages/flamenco-worker-python/system-integration/sysv/crontab b/system-integration/sysv/crontab
similarity index 100%
rename from packages/flamenco-worker-python/system-integration/sysv/crontab
rename to system-integration/sysv/crontab
diff --git a/packages/flamenco-worker-python/system-integration/sysv/flamenco-worker b/system-integration/sysv/flamenco-worker
similarity index 100%
rename from packages/flamenco-worker-python/system-integration/sysv/flamenco-worker
rename to system-integration/sysv/flamenco-worker
diff --git a/packages/flamenco-worker-python/tests/Corn field-1k.exr b/tests/Corn field-1k.exr
similarity index 100%
rename from packages/flamenco-worker-python/tests/Corn field-1k.exr
rename to tests/Corn field-1k.exr
diff --git a/packages/flamenco-worker-python/tests/Deventer-1k.exr b/tests/Deventer-1k.exr
similarity index 100%
rename from packages/flamenco-worker-python/tests/Deventer-1k.exr
rename to tests/Deventer-1k.exr
diff --git a/packages/flamenco-worker-python/tests/abstract_worker_test.py b/tests/abstract_worker_test.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/abstract_worker_test.py
rename to tests/abstract_worker_test.py
diff --git a/packages/flamenco-worker-python/tests/mock_responses.py b/tests/mock_responses.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/mock_responses.py
rename to tests/mock_responses.py
diff --git a/packages/flamenco-worker-python/tests/test_coro_mock.py b/tests/test_coro_mock.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_coro_mock.py
rename to tests/test_coro_mock.py
diff --git a/packages/flamenco-worker-python/tests/test_may_i_run.py b/tests/test_may_i_run.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_may_i_run.py
rename to tests/test_may_i_run.py
diff --git a/packages/flamenco-worker-python/tests/test_runner.py b/tests/test_runner.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_runner.py
rename to tests/test_runner.py
diff --git a/packages/flamenco-worker-python/tests/test_runner_blender_render.py b/tests/test_runner_blender_render.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_runner_blender_render.py
rename to tests/test_runner_blender_render.py
diff --git a/packages/flamenco-worker-python/tests/test_runner_merge_exr.py b/tests/test_runner_merge_exr.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_runner_merge_exr.py
rename to tests/test_runner_merge_exr.py
diff --git a/packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py b/tests/test_runner_move_out_of_way.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py
rename to tests/test_runner_move_out_of_way.py
diff --git a/packages/flamenco-worker-python/tests/test_upstream_update_queue.py b/tests/test_upstream_update_queue.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_upstream_update_queue.py
rename to tests/test_upstream_update_queue.py
diff --git a/packages/flamenco-worker-python/tests/test_worker.py b/tests/test_worker.py
similarity index 100%
rename from packages/flamenco-worker-python/tests/test_worker.py
rename to tests/test_worker.py
diff --git a/update_version.sh b/update_version.sh
index 17f488490e5730406cfb2cdaa4bd019f5a93608e..9c4b2b5348933c25ba19d8f241631e9e1fa78a28 100755
--- a/update_version.sh
+++ b/update_version.sh
@@ -5,9 +5,7 @@ if [ -z "$1" ]; then
     exit 1
 fi
 
-sed "s/version='[^']*'/version='$1'/" -i packages/flamenco/setup.py
-sed "s/version='[^']*'/version='$1'/" -i packages/flamenco-worker-python/setup.py
-sed "s/FLAMENCO_VERSION = \"[^\"]*\"/FLAMENCO_VERSION = \"$1\"/" -i packages/flamenco-manager-go/src/flamenco-manager/main.go
+sed "s/version='[^']*'/version='$1'/" -i setup.py
 
 git diff
 echo