Convert legacy Polyemer elements to class-based

This commit converts almost all Polymer elements from Polymer-function
based components to class-based components. There are few files which
should be converted manually after this commit.

Change-Id: I9e597e79053e0a6b5d5c0f1b54676d11b9d81db7
diff --git a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
index ed96bb2..ce9db61 100644
--- a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
+++ b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
@@ -17,23 +17,28 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-default-editor',
-
+  class GrDefaultEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-default-editor'; }
     /**
      * Fired when the content of the editor changes.
      *
      * @event content-change
      */
 
-    properties: {
-      fileContent: String,
-    },
+    static get properties() {
+      return {
+        fileContent: String,
+      };
+    }
 
     _handleTextareaInput(e) {
       this.dispatchEvent(new CustomEvent(
           'content-change',
           {detail: {value: e.target.value}, bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDefaultEditor.is, GrDefaultEditor);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
index 32aad5a..6a585e1 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
@@ -17,47 +17,52 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-edit-controls',
+  /**
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrEditControls extends Polymer.mixinBehaviors( [
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-edit-controls'; }
 
-    properties: {
-      change: Object,
-      patchNum: String,
+    static get properties() {
+      return {
+        change: Object,
+        patchNum: String,
 
-      /**
+        /**
        * TODO(kaspern): by default, the RESTORE action should be hidden in the
        * file-list as it is a per-file action only. Remove this default value
        * when the Actions dictionary is moved to a shared constants file and
        * use the hiddenActions property in the parent component.
        */
-      hiddenActions: {
-        type: Array,
-        value() { return [GrEditConstants.Actions.RESTORE.id]; },
-      },
-
-      _actions: {
-        type: Array,
-        value() { return Object.values(GrEditConstants.Actions); },
-      },
-      _path: {
-        type: String,
-        value: '',
-      },
-      _newPath: {
-        type: String,
-        value: '',
-      },
-      _query: {
-        type: Function,
-        value() {
-          return this._queryFiles.bind(this);
+        hiddenActions: {
+          type: Array,
+          value() { return [GrEditConstants.Actions.RESTORE.id]; },
         },
-      },
-    },
 
-    behaviors: [
-      Gerrit.PatchSetBehavior,
-    ],
+        _actions: {
+          type: Array,
+          value() { return Object.values(GrEditConstants.Actions); },
+        },
+        _path: {
+          type: String,
+          value: '',
+        },
+        _newPath: {
+          type: String,
+          value: '',
+        },
+        _query: {
+          type: Function,
+          value() {
+            return this._queryFiles.bind(this);
+          },
+        },
+      };
+    }
 
     _handleTap(e) {
       e.preventDefault();
@@ -76,7 +81,7 @@
           this.openRestoreDialog();
           return;
       }
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -84,7 +89,7 @@
     openOpenDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.openDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -92,7 +97,7 @@
     openDeleteDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.deleteDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -100,7 +105,7 @@
     openRenameDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.renameDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -108,7 +113,7 @@
     openRestoreDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.restoreDialog);
-    },
+    }
 
     /**
      * Given a path string, checks that it is a valid file path.
@@ -118,11 +123,11 @@
     _isValidPath(path) {
       // Double negation needed for strict boolean return type.
       return !!path.length && !path.endsWith('/');
-    },
+    }
 
     _computeRenameDisabled(path, newPath) {
       return this._isValidPath(path) && this._isValidPath(newPath);
-    },
+    }
 
     /**
      * Given a dom event, gets the dialog that lies along this event path.
@@ -134,7 +139,7 @@
         if (!element.classList) { return false; }
         return element.classList.contains('dialog');
       });
-    },
+    }
 
     _showDialog(dialog) {
       // Some dialogs may not fire their on-close event when closed in certain
@@ -148,12 +153,12 @@
         if (autocomplete) { autocomplete.focus(); }
         this.async(() => { this.$.overlay.center(); }, 1);
       });
-    },
+    }
 
     _hideAllDialogs() {
       const dialogs = Polymer.dom(this.root).querySelectorAll('.dialog');
       for (const dialog of dialogs) { this._closeDialog(dialog); }
-    },
+    }
 
     /**
      * @param {Element|undefined} dialog
@@ -175,18 +180,18 @@
 
       dialog.classList.toggle('invisible', true);
       return this.$.overlay.close();
-    },
+    }
 
     _handleDialogCancel(e) {
       this._closeDialog(this._getDialogFromEvent(e));
-    },
+    }
 
     _handleOpenConfirm(e) {
       const url = Gerrit.Nav.getEditUrlForDiff(this.change, this._path,
           this.patchNum);
       Gerrit.Nav.navigateToRelativeUrl(url);
       this._closeDialog(this._getDialogFromEvent(e), true);
-    },
+    }
 
     _handleDeleteConfirm(e) {
       // Get the dialog before the api call as the event will change during bubbling
@@ -198,7 +203,7 @@
             this._closeDialog(dialog, true);
             Gerrit.Nav.navigateToChange(this.change);
           });
-    },
+    }
 
     _handleRestoreConfirm(e) {
       const dialog = this._getDialogFromEvent(e);
@@ -208,7 +213,7 @@
             this._closeDialog(dialog, true);
             Gerrit.Nav.navigateToChange(this.change);
           });
-    },
+    }
 
     _handleRenameConfirm(e) {
       const dialog = this._getDialogFromEvent(e);
@@ -218,17 +223,19 @@
         this._closeDialog(dialog, true);
         Gerrit.Nav.navigateToChange(this.change);
       });
-    },
+    }
 
     _queryFiles(input) {
       return this.$.restAPI.queryChangeFiles(this.change._number,
           this.patchNum, input).then(res => res.map(file => {
         return {name: file};
       }));
-    },
+    }
 
     _computeIsInvisible(id, hiddenActions) {
       return hiddenActions.includes(id) ? 'invisible' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditControls.is, GrEditControls);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
index 250816b..ddd2d29 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
+++ b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
@@ -17,38 +17,41 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-edit-file-controls',
-
+  class GrEditFileControls extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-edit-file-controls'; }
     /**
      * Fired when an action in the overflow menu is tapped.
      *
      * @event file-action-tap
      */
 
-    properties: {
-      filePath: String,
-      _allFileActions: {
-        type: Array,
-        value: () => Object.values(GrEditConstants.Actions),
-      },
-      _fileActions: {
-        type: Array,
-        computed: '_computeFileActions(_allFileActions)',
-      },
-    },
+    static get properties() {
+      return {
+        filePath: String,
+        _allFileActions: {
+          type: Array,
+          value: () => Object.values(GrEditConstants.Actions),
+        },
+        _fileActions: {
+          type: Array,
+          computed: '_computeFileActions(_allFileActions)',
+        },
+      };
+    }
 
     _handleActionTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this._dispatchFileAction(e.detail.id, this.filePath);
-    },
+    }
 
     _dispatchFileAction(action, path) {
       this.dispatchEvent(new CustomEvent(
           'file-action-tap',
           {detail: {action, path}, bubbles: true, composed: true}));
-    },
+    }
 
     _computeFileActions(actions) {
       // TODO(kaspern): conditionally disable some actions based on file status.
@@ -58,6 +61,8 @@
           id: action.id,
         };
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditFileControls.is, GrEditFileControls);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
index bbcb90c..ab50921 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
@@ -24,9 +24,21 @@
 
   const STORAGE_DEBOUNCE_INTERVAL_MS = 100;
 
-  Polymer({
-    is: 'gr-editor-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.PathListMixin
+    */
+  class GrEditorView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.PathListBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-editor-view'; }
     /**
      * Fired when the title of the page should change.
      *
@@ -39,69 +51,69 @@
      * @event show-alert
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      _change: Object,
-      _changeEditDetail: Object,
-      _changeNum: String,
-      _patchNum: String,
-      _path: String,
-      _type: String,
-      _content: String,
-      _newContent: String,
-      _saving: {
-        type: Boolean,
-        value: false,
-      },
-      _successfulSave: {
-        type: Boolean,
-        value: false,
-      },
-      _saveDisabled: {
-        type: Boolean,
-        value: true,
-        computed: '_computeSaveDisabled(_content, _newContent, _saving)',
-      },
-      _prefs: Object,
-    },
+        _change: Object,
+        _changeEditDetail: Object,
+        _changeNum: String,
+        _patchNum: String,
+        _path: String,
+        _type: String,
+        _content: String,
+        _newContent: String,
+        _saving: {
+          type: Boolean,
+          value: false,
+        },
+        _successfulSave: {
+          type: Boolean,
+          value: false,
+        },
+        _saveDisabled: {
+          type: Boolean,
+          value: true,
+          computed: '_computeSaveDisabled(_content, _newContent, _saving)',
+        },
+        _prefs: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.PathListBehavior,
-    ],
+    get keyBindings() {
+      return {
+        'ctrl+s meta+s': '_handleSaveShortcut',
+      };
+    }
 
-    listeners: {
-      'content-change': '_handleContentChange',
-    },
-
-    keyBindings: {
-      'ctrl+s meta+s': '_handleSaveShortcut',
-    },
+    created() {
+      super.created();
+      this.addEventListener('content-change',
+          e => this._handleContentChange(e));
+    }
 
     attached() {
+      super.attached();
       this._getEditPrefs().then(prefs => { this._prefs = prefs; });
-    },
+    }
 
     get storageKey() {
       return `c${this._changeNum}_ps${this._patchNum}_${this._path}`;
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getEditPrefs() {
       return this.$.restAPI.getEditPreferences();
-    },
+    }
 
     _paramsChanged(value) {
       if (value.view !== Gerrit.Nav.View.EDIT) {
@@ -126,13 +138,13 @@
       promises.push(
           this._getFileData(this._changeNum, this._path, this._patchNum));
       return Promise.all(promises);
-    },
+    }
 
     _getChangeDetail(changeNum) {
       return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
         this._change = change;
       });
-    },
+    }
 
     _handlePathChanged(e) {
       const path = e.detail;
@@ -146,13 +158,13 @@
         this._successfulSave = true;
         this._viewEditInChangeView();
       });
-    },
+    }
 
     _viewEditInChangeView() {
       const patch = this._successfulSave ? this.EDIT_NAME : this._patchNum;
       Gerrit.Nav.navigateToChange(this._change, patch, null,
           patch !== this.EDIT_NAME);
-    },
+    }
 
     _getFileData(changeNum, path, patchNum) {
       const storedContent =
@@ -183,7 +195,7 @@
               this._type = '';
             }
           });
-    },
+    }
 
     _saveEdit() {
       this._saving = true;
@@ -198,7 +210,7 @@
         this._content = this._newContent;
         this._successfulSave = true;
       });
-    },
+    }
 
     _showAlert(message) {
       this.dispatchEvent(new CustomEvent('show-alert', {
@@ -206,7 +218,7 @@
         bubbles: true,
         composed: true,
       }));
-    },
+    }
 
     _computeSaveDisabled(content, newContent, saving) {
       // Polymer 2: check for undefined
@@ -222,12 +234,12 @@
         return true;
       }
       return content === newContent;
-    },
+    }
 
     _handleCloseTap() {
       // TODO(kaspern): Add a confirm dialog if there are unsaved changes.
       this._viewEditInChangeView();
-    },
+    }
 
     _handleContentChange(e) {
       this.debounce('store', () => {
@@ -239,13 +251,15 @@
           this.$.storage.eraseEditableContentItem(this.storageKey);
         }
       }, STORAGE_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _handleSaveShortcut(e) {
       e.preventDefault();
       if (!this._saveDisabled) {
         this._saveEdit();
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditorView.is, GrEditorView);
 })();