diff --git a/node_modules/mdl-ext/src/menu-button/menu-button.js b/node_modules/mdl-ext/src/menu-button/menu-button.js
new file mode 100644
index 0000000..e7e37d8
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/menu-button.js
@@ -0,0 +1,758 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+/**
+ * A menu button is a button that opens a menu. It is often styled as a
+ * typical push button with a downward pointing arrow or triangle to hint
+ * that activating the button will display a menu.
+ */
+import { randomString } from '../utils/string-utils';
+import fullThrottle from '../utils/full-throttle';
+import {
+  VK_TAB,
+  VK_ENTER,
+  VK_ESC,
+  VK_SPACE,
+  VK_END,
+  VK_HOME,
+  VK_ARROW_LEFT,
+  VK_ARROW_UP,
+  VK_ARROW_RIGHT,
+  VK_ARROW_DOWN,
+  IS_UPGRADED,
+} from '../utils/constants';
+
+import { getScrollParents, tether } from '../utils/dom-utils';
+
+const JS_MENU_BUTTON = 'mdlext-js-menu-button';
+const MENU_BUTTON_MENU = 'mdlext-menu';
+const MENU_BUTTON_MENU_ITEM = 'mdlext-menu__item';
+const MENU_BUTTON_MENU_ITEM_SEPARATOR = 'mdlext-menu__item-separator';
+//const MDL_LAYOUT_CONTENT = 'mdl-layout__content';
+
+/**
+ * Creates the menu controlled by the menu button
+ * @param element
+ * @return {{element: Element, selected: Element, open: (function(*=)), removeListeners: (function()), downgrade: (function())}}
+ */
+
+const menuFactory = element => {
+
+  let ariaControls = null;
+  let parentNode = null;
+
+  const removeAllSelected = () => {
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`)]
+      .forEach(selectedItem => selectedItem.removeAttribute('aria-selected'));
+  };
+
+  const setSelected = (item, force=false) => {
+    if(force || (item && !item.hasAttribute('aria-selected'))) {
+      removeAllSelected();
+      if(item) {
+        item.setAttribute('aria-selected', 'true');
+      }
+    }
+  };
+
+  const getSelected = () => {
+    return element.querySelector(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`);
+  };
+
+  const isDisabled = item => item && item.hasAttribute('disabled');
+
+  const isSeparator = item => item && item.classList.contains(MENU_BUTTON_MENU_ITEM_SEPARATOR);
+
+  const focus = item => {
+    if(item) {
+      item = item.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+    }
+    if(item) {
+      item.focus();
+    }
+  };
+
+  const nextItem = current => {
+    let n = current.nextElementSibling;
+    if(!n) {
+      n = element.firstElementChild;
+    }
+    if(!isDisabled(n) && !isSeparator(n)) {
+      focus(n);
+    }
+    else {
+      let i = element.children.length;
+      while(n && i-- > 0) {
+        if(isDisabled(n) || isSeparator(n)) {
+          n = n.nextElementSibling;
+          if(!n) {
+            n = element.firstElementChild;
+          }
+        }
+        else {
+          focus(n);
+          break;
+        }
+      }
+    }
+  };
+
+  const previousItem = current => {
+    let p = current.previousElementSibling;
+    if(!p) {
+      p = element.lastElementChild;
+    }
+    if(!isDisabled(p) && !isSeparator(p)) {
+      focus(p);
+    }
+    else {
+      let i = element.children.length;
+      while(p && i-- > 0) {
+        if(isDisabled(p) || isSeparator(p)) {
+          p = p.previousElementSibling;
+          if(!p) {
+            p = element.lastElementChild;
+          }
+        }
+        else {
+          focus(p);
+          break;
+        }
+      }
+    }
+  };
+
+  const firstItem = () => {
+    const item = element.firstElementChild;
+    if(isDisabled(item) || isSeparator(item) ) {
+      nextItem(item);
+    }
+    else {
+      focus(item);
+    }
+  };
+
+  const lastItem = () => {
+    const item = element.lastElementChild;
+    if(isDisabled(item) || isSeparator(item)) {
+      previousItem(item);
+    }
+    else {
+      focus(item);
+    }
+  };
+
+  const selectItem = item => {
+    if(item && !isDisabled(item) && !isSeparator(item)) {
+      setSelected(item);
+      close(true, item);
+    }
+  };
+
+  const keyDownHandler = event => {
+
+    const item = event.target.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+
+    switch (event.keyCode) {
+      case VK_ARROW_UP:
+      case VK_ARROW_LEFT:
+        if(item) {
+          previousItem(item);
+        }
+        else {
+          firstItem();
+        }
+        break;
+
+      case VK_ARROW_DOWN:
+      case VK_ARROW_RIGHT:
+        if(item) {
+          nextItem(item);
+        }
+        else {
+          lastItem();
+        }
+        break;
+
+      case VK_HOME:
+        firstItem();
+        break;
+
+      case VK_END:
+        lastItem();
+        break;
+
+      case VK_SPACE:
+      case VK_ENTER:
+        selectItem(item);
+        break;
+
+      case VK_ESC:
+        close(true);
+        break;
+
+      case VK_TAB:
+        // We do not have a "natural" tab order from menu, so the best we can do is to set focus back to the button
+        close(true);
+        break;
+
+      default:
+        return;
+    }
+    event.preventDefault();
+  };
+
+
+  const blurHandler = event => {
+
+    // See: https://github.com/facebook/react/issues/2011
+    const t = event.relatedTarget ||
+      event.explicitOriginalTarget || // FF
+      document.activeElement;         // IE11
+
+    //console.log('***** blur, target, relatedTarget', event.target, t);
+
+    try {
+      if (t) {
+        if (t.closest(`.${MENU_BUTTON_MENU}`) !== element && shouldClose(t)) {
+          close();
+        }
+      }
+      else {
+        close();
+      }
+    }
+    catch(err) {
+      // FF throws error: "TypeError: n.closest is not a function" if related target is a text node
+      close();
+    }
+  };
+
+  const clickHandler = event => {
+    //console.log('***** click, target', event.target);
+
+    event.preventDefault();
+    const t = event.target;
+    if (t && t.closest(`.${MENU_BUTTON_MENU}`) === element) {
+      const item = t.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+      if (item) {
+        selectItem(item);
+      }
+    }
+    else {
+      if (shouldClose(t)) {
+        close();
+      }
+    }
+  };
+
+  const touchStartHandler = event => {
+    //console.log('***** touchStart, target', event.target);
+
+    const t = event.target;
+    if(!(t && t.closest(`.${MENU_BUTTON_MENU}`) === element)) {
+      if (event.type === 'touchstart') {
+        event.preventDefault();
+      }
+      close();
+    }
+  };
+
+  const addListeners = () => {
+    element.addEventListener('keydown', keyDownHandler, false);
+    element.addEventListener('blur', blurHandler, true);
+    element.addEventListener('click', clickHandler, true);
+    document.documentElement.addEventListener('touchstart', touchStartHandler, true);
+  };
+
+  const removeListeners = () => {
+    element.removeEventListener('keydown', keyDownHandler, false);
+    element.removeEventListener('blur', blurHandler, true);
+    element.removeEventListener('click', clickHandler, true);
+    document.documentElement.removeEventListener('touchstart', touchStartHandler, true);
+  };
+
+  const open = (controlElement, position='first') => {
+
+    ariaControls = controlElement.closest(`.${JS_MENU_BUTTON}`);
+
+    element.style['min-width'] = `${Math.max(124, controlElement.getBoundingClientRect().width)}px`;
+    element.removeAttribute('hidden');
+    tether(controlElement, element);
+
+    let item;
+    switch (position.toLowerCase()) {
+      case 'first':
+        firstItem();
+        break;
+
+      case 'last':
+        lastItem();
+        break;
+
+      case 'selected':
+        item = getSelected();
+        if(item && !item.hasAttribute('disabled')) {
+          focus(item);
+        }
+        else {
+          firstItem();
+        }
+        break;
+    }
+
+    addListeners();
+  };
+
+
+  const shouldClose = target => {
+    //console.log('***** shouldClose');
+
+    let result = false;
+    const btn = (target && target.closest(`.${JS_MENU_BUTTON}`)) || null;
+    if(!btn) {
+      result = true;
+    }
+    else if(btn.getAttribute('aria-controls') === element.id) {
+      if(btn !== ariaControls) {
+        result = true;
+      }
+    }
+    else {
+      result = true;
+    }
+    return result;
+  };
+
+  const close = (forceFocus = false, item = null) => {
+    removeListeners();
+
+    element.dispatchEvent(
+      new CustomEvent('_closemenu', {
+        bubbles: true,
+        cancelable: true,
+        detail: { forceFocus: forceFocus, item: item }
+      })
+    );
+  };
+
+  const addWaiAria = () => {
+    if (!element.hasAttribute('id')) {
+      // Generate a random id
+      element.id = `menu-button-${randomString()}`;
+    }
+    element.setAttribute('tabindex', '-1');
+    element.setAttribute('role', 'menu');
+    element.setAttribute('hidden', '');
+
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}`)].forEach( menuitem => {
+      menuitem.setAttribute('tabindex', '-1');
+      menuitem.setAttribute('role', 'menuitem');
+    });
+
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM_SEPARATOR}`)].forEach( menuitem => {
+      menuitem.setAttribute('role', 'separator');
+    });
+  };
+
+  const init = () => {
+    addWaiAria();
+    parentNode = element.parentNode;
+    element.classList.add('is-upgraded');
+  };
+
+  const downgrade = () => {
+    removeListeners();
+    if(element.parentNode !== parentNode) {
+      parentNode.appendChild(element);
+    }
+    element.classList.remove('is-upgraded');
+  };
+
+  init();
+
+  return {
+    /**
+     * Get the menu element
+     * @returns {Element} the menu element
+     */
+    get element() {
+      return element;
+    },
+
+    /**
+     * Set selected menu item
+     * @param item
+     */
+    set selected(item) {
+      setSelected(item, true);
+    },
+
+    /**
+     * Open menu
+     * @param {Element} controlElement the element where the menu should be aligned to
+     * @param {String} position menuElement item to receive focus after menu element is opened
+     */
+    open: (controlElement, position='first') => open(controlElement, position),
+
+    /**
+     * Remove event listeners.
+     */
+    removeListeners: () => removeListeners(),
+
+    /**
+     * Downgrade menu
+     */
+    downgrade: () => downgrade(),
+  };
+};
+
+
+/**
+ * The menubutton component
+ */
+
+class MenuButton {
+
+  constructor(element) {
+    this.element = element;
+    this.focusElement = undefined;
+    this.focusElementLastScrollPosition = undefined;
+    this.scrollElements = [];
+    this.menu = undefined;
+    this.selectedItem = null;
+    this.init();
+  }
+
+  keyDownHandler = event => {
+    if(!this.isDisabled()) {
+      switch (event.keyCode) {
+        case VK_ARROW_UP:
+          this.openMenu('last');
+          break;
+
+        case VK_ARROW_DOWN:
+          this.openMenu();
+          break;
+
+        case VK_SPACE:
+        case VK_ENTER:
+          this.openMenu('selected');
+          break;
+
+        case VK_ESC:
+          this.closeMenu();
+          break;
+
+        case VK_TAB:
+          this.closeMenu();
+          return;
+
+        default:
+          return;
+      }
+    }
+    //event.stopPropagation();
+    event.preventDefault();
+  };
+
+  clickHandler = () => {
+    if(!this.isDisabled()) {
+      if(this.element.getAttribute('aria-expanded').toLowerCase() === 'true') {
+        this.closeMenu(true);
+      }
+      else {
+        this.openMenu('selected');
+      }
+    }
+  };
+
+  /**
+   * Re-position menu if content is scrolled, window is resized or orientation change
+   * @see https://javascriptweblog.wordpress.com/2015/11/02/of-classes-and-arrow-functions-a-cautionary-tale/
+   */
+  recalcMenuPosition = fullThrottle( () => {
+    const c = this.focusElement.getBoundingClientRect();
+    const dx = this.focusElementLastScrollPosition.left - c.left;
+    const dy = this.focusElementLastScrollPosition.top - c.top;
+    const left = (parseFloat(this.menu.element.style.left) || 0) - dx;
+    const top = (parseFloat(this.menu.element.style.top) || 0) - dy;
+
+    this.menu.element.style.left = `${left}px`;
+    this.menu.element.style.top = `${top}px`;
+    this.focusElementLastScrollPosition = c;
+  });
+
+
+  positionChangeHandler = () => {
+    this.recalcMenuPosition(this);
+  };
+
+  closeMenuHandler = event => {
+    if(event && event.detail) {
+      if(event.detail.item && event.detail.item !== this.selectedItem) {
+        this.selectedItem = event.detail.item;
+        this.dispatchMenuSelect();
+      }
+      this.closeMenu(event.detail.forceFocus);
+    }
+  };
+
+  dispatchMenuSelect() {
+    this.element.dispatchEvent(
+      new CustomEvent('menuselect', {
+        bubbles: true,
+        cancelable: true,
+        detail: { source: this.selectedItem }
+      })
+    );
+  }
+
+  isDisabled() {
+    return this.element.hasAttribute('disabled');
+  }
+
+  removeListeners() {
+    this.element.removeEventListener('keydown', this.keyDownHandler);
+    this.element.removeEventListener('click', this.clickHandler);
+  }
+
+  openMenu(position='first') {
+
+    if(!this.isDisabled() && this.menu) {
+
+      // Close the menu if button position change
+      this.scrollElements = getScrollParents(this.element);
+      this.scrollElements.forEach(el => el.addEventListener('scroll', this.positionChangeHandler));
+
+      window.addEventListener('resize', this.positionChangeHandler);
+      window.addEventListener('orientationchange', this.positionChangeHandler);
+      this.menu.element.addEventListener('_closemenu', this.closeMenuHandler);
+
+      this.menu.selected = this.selectedItem;
+      this.menu.open(this.focusElement, position);
+      this.element.setAttribute('aria-expanded', 'true');
+
+      this.focusElementLastScrollPosition = this.focusElement.getBoundingClientRect();
+    }
+  }
+
+  closeMenu(forceFocus = false) {
+    if(this.menu) {
+      this.menu.removeListeners();
+      this.scrollElements.forEach(el => el.removeEventListener('scroll', this.positionChangeHandler));
+      window.removeEventListener('resize', this.positionChangeHandler);
+      window.removeEventListener('orientationchange', this.positionChangeHandler);
+      this.menu.element.removeEventListener('_closemenu', this.closeMenuHandler);
+
+      if (forceFocus) {
+        this.focus();
+      }
+      this.element.setAttribute('aria-expanded', 'false');
+      this.menu.element.setAttribute('hidden', '');
+    }
+  }
+
+  focus() {
+    if(!this.isDisabled()) {
+      this.focusElement.focus();
+    }
+  }
+
+  init() {
+    const addListeners = () => {
+      this.element.addEventListener('keydown', this.keyDownHandler);
+      this.element.addEventListener('click', this.clickHandler);
+    };
+
+    const addWaiAria = () => {
+      this.element.setAttribute('role', 'button');
+      this.element.setAttribute('aria-expanded', 'false');
+      this.element.setAttribute('aria-haspopup', 'true');
+    };
+
+    const addFocusElement = () => {
+      this.focusElement = this.element.querySelector('input[type="text"]');
+      if(!this.focusElement) {
+        this.focusElement = this.element;
+
+        if(!(this.focusElement.tagName.toLowerCase() === 'button' || this.focusElement.tagName.toLowerCase() === 'input')) {
+          if (!this.focusElement.hasAttribute('tabindex')) {
+            this.focusElement.setAttribute('tabindex', '0');
+          }
+        }
+      }
+    };
+
+    const moveElementToDocumentBody = (element) => {
+      // To position an element on top of all other z-indexed elements, the element should be moved to document.body
+      //       See: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
+
+      if(element.parentNode !== document.body) {
+        return document.body.appendChild(element);
+      }
+      return element;
+    };
+
+    const findMenuElement = () => {
+      let menuElement;
+      const menuElementId = this.element.getAttribute('aria-controls');
+      if(menuElementId !== null) {
+        menuElement = document.querySelector(`#${menuElementId }`);
+      }
+      else {
+        menuElement = this.element.parentNode.querySelector(`.${MENU_BUTTON_MENU}`);
+      }
+      return menuElement;
+    };
+
+    const addMenu = () => {
+      const menuElement = findMenuElement();
+      if(menuElement) {
+        if(menuElement.componentInstance) {
+          this.menu = menuElement.componentInstance;
+        }
+        else {
+          this.menu = menuFactory(menuElement);
+          menuElement.componentInstance = this.menu;
+          moveElementToDocumentBody(menuElement);
+        }
+        this.element.setAttribute('aria-controls', this.menu.element.id);
+      }
+    };
+
+    addFocusElement();
+    addWaiAria();
+    addMenu();
+    this.removeListeners();
+    addListeners();
+  }
+
+  downgrade() {
+    if(this.menu) {
+      // Do not downgrade menu if there are other buttons sharing this menu
+      const related = [...document.querySelectorAll(`.${JS_MENU_BUTTON}[aria-controls="${this.element.getAttribute('aria-controls')}"]`)];
+      if(related.filter( c => c !== this.element && c.getAttribute('data-upgraded').indexOf('MaterialExtMenuButton') >= 0).length === 0) {
+        this.menu.downgrade();
+      }
+    }
+    this.removeListeners();
+  }
+
+}
+
+(function() {
+  'use strict';
+
+  /**
+   * https://github.com/google/material-design-lite/issues/4205
+   * @constructor
+   * @param {Element} element The element that will be upgraded.
+   */
+  const MaterialExtMenuButton = function MaterialExtMenuButton(element) {
+    this.element_ = element;
+    this.menuButton_ = null;
+
+    // Initialize instance.
+    this.init();
+  };
+  window['MaterialExtMenuButton'] = MaterialExtMenuButton;
+
+
+  // Public methods.
+
+  /**
+   * Get the menu element controlled by this button, null if no menu is controlled by this button
+   * @public
+   */
+  MaterialExtMenuButton.prototype.getMenuElement = function() {
+    return this.menuButton_.menu ? this.menuButton_.menu.element : null;
+  };
+  MaterialExtMenuButton.prototype['getMenuElement'] = MaterialExtMenuButton.prototype.getMenuElement;
+
+  /**
+   * Open menu
+   * @public
+   * @param {String} position one of "first", "last" or "selected"
+   */
+  MaterialExtMenuButton.prototype.openMenu = function(position) {
+    this.menuButton_.openMenu(position);
+  };
+  MaterialExtMenuButton.prototype['openMenu'] = MaterialExtMenuButton.prototype.openMenu;
+
+  /**
+   * Close menu
+   * @public
+   */
+  MaterialExtMenuButton.prototype.closeMenu = function() {
+    this.menuButton_.closeMenu(true);
+  };
+  MaterialExtMenuButton.prototype['closeMenu'] = MaterialExtMenuButton.prototype.closeMenu;
+
+  /**
+   * Get selected menu item
+   * @public
+   * @returns {Element} The selected menu item or null if no item selected
+   */
+  MaterialExtMenuButton.prototype.getSelectedMenuItem = function() {
+    return this.menuButton_.selectedItem;
+  };
+  MaterialExtMenuButton.prototype['getSelectedMenuItem'] = MaterialExtMenuButton.prototype.getSelectedMenuItem;
+
+
+  /**
+   * Set (default) selected menu item
+   * @param {Element} item
+   */
+  MaterialExtMenuButton.prototype.setSelectedMenuItem = function(item) {
+    this.menuButton_.selectedItem = item;
+  };
+  MaterialExtMenuButton.prototype['setSelectedMenuItem'] = MaterialExtMenuButton.prototype.setSelectedMenuItem;
+
+  /**
+   * Initialize component
+   */
+  MaterialExtMenuButton.prototype.init = function() {
+    if (this.element_) {
+      this.menuButton_ = new MenuButton(this.element_);
+      this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+      this.element_.classList.add(IS_UPGRADED);
+    }
+  };
+
+  /**
+   * Downgrade component
+   * E.g remove listeners and clean up resources
+   */
+  MaterialExtMenuButton.prototype.mdlDowngrade_ = function() {
+    this.menuButton_.downgrade();
+  };
+
+  // The component registers itself. It can assume componentHandler is available
+  // in the global scope.
+  /* eslint no-undef: 0 */
+  componentHandler.register({
+    constructor: MaterialExtMenuButton,
+    classAsString: 'MaterialExtMenuButton',
+    cssClass: JS_MENU_BUTTON,
+    widget: true
+  });
+})();
