From 62d7cb234c52d9d10073bd0343daf9dfda65f605 Mon Sep 17 00:00:00 2001
From: Joseph Schorr <josephschorr@users.noreply.github.com>
Date: Fri, 23 Jun 2017 14:22:28 -0400
Subject: [PATCH] Move DockerfileCommand component into TS

---
 static/css/quay.css                           | 27 -------
 static/directives/build-log-command.html      |  2 +-
 static/directives/dockerfile-command.html     |  6 --
 static/directives/image-feature-view.html     |  2 +-
 static/directives/image-view-layer.html       |  4 +-
 .../directives/image-vulnerability-view.html  |  2 +-
 static/js/directives/ui/dockerfile-command.js | 68 ------------------
 .../dockerfile-command.component.css}         | 27 +++++++
 .../dockerfile-command.component.html         |  7 ++
 .../dockerfile-command.component.ts           | 72 +++++++++++++++++++
 static/js/quay.module.ts                      |  2 +
 11 files changed, 113 insertions(+), 106 deletions(-)
 delete mode 100644 static/directives/dockerfile-command.html
 delete mode 100644 static/js/directives/ui/dockerfile-command.js
 rename static/{css/directives/ui/dockerfile-command.css => js/directives/ui/dockerfile-command/dockerfile-command.component.css} (53%)
 create mode 100644 static/js/directives/ui/dockerfile-command/dockerfile-command.component.html
 create mode 100644 static/js/directives/ui/dockerfile-command/dockerfile-command.component.ts

diff --git a/static/css/quay.css b/static/css/quay.css
index 11b676ae5..5734ca150 100644
--- a/static/css/quay.css
+++ b/static/css/quay.css
@@ -222,33 +222,6 @@
   font-size: 18px;
 }
 
-.dockerfile-command {
-  position: relative;
-}
-
-.dockerfile-command .command-title {
-  font-family: Consolas, "Lucida Console", Monaco, monospace;
-  padding-left: 90px;
-  display: inline-block;
-}
-
-.dockerfile-command .label {
-  color: white;
-
-  padding-top: 4px;
-  text-align: right;
-  margin-right: 4px;
-  width: 86px;
-  display: inline-block;
-
-  border-right: 4px solid #aaa;
-  background-color: #333;
-
-  position: absolute;
-  top: 0px;
-  left: -4px;
-}
-
 .codetooltipcontainer .tooltip-inner {
     white-space:pre;
     max-width:none;
diff --git a/static/directives/build-log-command.html b/static/directives/build-log-command.html
index 40d1c8880..678fea6ab 100644
--- a/static/directives/build-log-command.html
+++ b/static/directives/build-log-command.html
@@ -1 +1 @@
-<span class="dockerfile-command command" command="getWithoutStep(command.message)"></span>
+<dockerfile-command class="command" command="getWithoutStep(command.message)"></dockerfile-command>
diff --git a/static/directives/dockerfile-command.html b/static/directives/dockerfile-command.html
deleted file mode 100644
index 0e0c7bc5e..000000000
--- a/static/directives/dockerfile-command.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<span class="dockerfile-command-element" bindonce>
-  <span class="label" bo-class="getCommandKind(command)" bo-show="getCommandKind(command)"
-        bo-text="getCommandKind(command)">
-  </span>
-  <span class="command-title" bo-html="getCommandTitleHtml(command)"></span>
-</span>
diff --git a/static/directives/image-feature-view.html b/static/directives/image-feature-view.html
index d6b524844..f3a68d985 100644
--- a/static/directives/image-feature-view.html
+++ b/static/directives/image-feature-view.html
@@ -165,7 +165,7 @@
          <td class="double-col image-col hidden-xs hidden-sm hidden-md">
             <span bo-if="feature.imageCommand">
               <span data-title="{{ feature.imageCommand }}" data-container="body" bs-tooltip>
-                <span class="dockerfile-command" command="feature.imageCommand"></span>
+                <dockerfile-command command="feature.imageCommand"></dockerfile-command>
               </span>
               <a href="/repository/{{ repository.namespace }}/{{ repository.name }}/image/{{ feature.imageId }}"><i class="fa fa-archive"></i></a>
               </span>
diff --git a/static/directives/image-view-layer.html b/static/directives/image-view-layer.html
index 0d0601b6d..bb6c94dbd 100644
--- a/static/directives/image-view-layer.html
+++ b/static/directives/image-view-layer.html
@@ -6,8 +6,8 @@
   </div>
    <div class="image-command">
      <div class="nondocker-command" ng-if="!getDockerfileCommand(image.command)">{{ image.command.join(' ') }}</div>
-     <div class="dockerfile-command" command="getDockerfileCommand(image.command)"
-          ng-if="getDockerfileCommand(image.command)"></div>
+     <dockerfile-command command="getDockerfileCommand(image.command)"
+                         ng-if="getDockerfileCommand(image.command)"></dockerfile-command>
   </div>
   <div class="image-layer-dot"></div>
   <div class="image-layer-line"></div>
diff --git a/static/directives/image-vulnerability-view.html b/static/directives/image-vulnerability-view.html
index bc3e3f4f4..b6c0f54fa 100644
--- a/static/directives/image-vulnerability-view.html
+++ b/static/directives/image-vulnerability-view.html
@@ -153,7 +153,7 @@
          <td class="double-col image-col hidden-xs hidden-sm hidden-md">
             <span bo-if="vuln.imageCommand">
               <span data-title="{{ vuln.imageCommand }}" data-container="body" bs-tooltip>
-                <span class="dockerfile-command" command="vuln.imageCommand"></span>
+                <dockerfile-command command="vuln.imageCommand"></dockerfile-command>
               </span>
               <a href="/repository/{{ repository.namespace }}/{{ repository.name }}/image/{{ vuln.imageId }}"><i class="fa fa-archive"></i></a>
               </span>
diff --git a/static/js/directives/ui/dockerfile-command.js b/static/js/directives/ui/dockerfile-command.js
deleted file mode 100644
index c83d53d6e..000000000
--- a/static/js/directives/ui/dockerfile-command.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * An element which displays a Dockerfile command nicely formatted, with optional link to the
- * image (for FROM commands that link to us or to the DockerHub).
- */
-angular.module('quay').directive('dockerfileCommand', function () {
-  var directiveDefinitionObject = {
-    priority: 0,
-    templateUrl: '/static/directives/dockerfile-command.html',
-    replace: false,
-    transclude: false,
-    restrict: 'C',
-    scope: {
-      'command': '=command'
-    },
-    controller: function($scope, $element, UtilService, Config) {
-      var registryHandlers = {
-        'quay.io': function(pieces) {
-          var rnamespace =  pieces[pieces.length - 2];
-          var rname = pieces[pieces.length - 1].split(':')[0];
-          return '/repository/' + rnamespace + '/' + rname + '/';
-        },
-
-        '': function(pieces) {
-          var rnamespace = pieces.length == 1 ? '_' : 'u/' + pieces[0];
-          var rname = pieces[pieces.length - 1].split(':')[0];
-          return 'https://registry.hub.docker.com/' + rnamespace + '/' + rname + '/';
-        }
-      };
-
-      registryHandlers[Config.getDomain()] = registryHandlers['quay.io'];
-
-      var kindHandlers = {
-        'FROM': function(title) {
-          var pieces = title.split('/');
-          var registry = pieces.length < 3 ? '' : pieces[0];
-          if (!registryHandlers[registry]) {
-            return title;
-          }
-
-          return '<i class="fa fa-hdd-o"></i> <a href="' + registryHandlers[registry](pieces) + '" target="_blank">' + title + '</a>';
-        }
-      };
-
-      $scope.getCommandKind = function(title) {
-        var space = title.indexOf(' ');
-        return title.substring(0, space);
-      };
-
-      $scope.getCommandTitleHtml = function(title) {
-        var space = title.indexOf(' ');
-        if (space <= 0) {
-          return UtilService.textToSafeHtml(title);
-        }
-
-        var kind = $scope.getCommandKind(title);
-        var sanitized = UtilService.textToSafeHtml(title.substring(space + 1));
-
-        var handler = kindHandlers[kind || ''];
-        if (handler) {
-          return handler(sanitized);
-        } else {
-          return sanitized;
-        }
-      };
-    }
-  };
-  return directiveDefinitionObject;
-});
\ No newline at end of file
diff --git a/static/css/directives/ui/dockerfile-command.css b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.css
similarity index 53%
rename from static/css/directives/ui/dockerfile-command.css
rename to static/js/directives/ui/dockerfile-command/dockerfile-command.component.css
index 693f789d7..9532320dd 100644
--- a/static/css/directives/ui/dockerfile-command.css
+++ b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.css
@@ -25,3 +25,30 @@
 .label.MAINTAINER {
   border-color: #aaa !important;
 }
+
+.dockerfile-command {
+  position: relative;
+}
+
+.dockerfile-command .command-title {
+  font-family: Consolas, "Lucida Console", Monaco, monospace;
+  padding-left: 90px;
+  display: inline-block;
+}
+
+.dockerfile-command .label {
+  color: white;
+
+  padding-top: 4px;
+  text-align: right;
+  margin-right: 4px;
+  width: 86px;
+  display: inline-block;
+
+  border-right: 4px solid #aaa;
+  background-color: #333;
+
+  position: absolute;
+  top: 0px;
+  left: -4px;
+}
diff --git a/static/js/directives/ui/dockerfile-command/dockerfile-command.component.html b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.html
new file mode 100644
index 000000000..31003882a
--- /dev/null
+++ b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.html
@@ -0,0 +1,7 @@
+<span class="dockerfile-command dockerfile-command-element">
+  <span class="label" ng-class="::$ctrl.getCommandKind($ctrl.command)"
+        ng-if="::$ctrl.getCommandKind($ctrl.command)">
+    {{ ::$ctrl.getCommandKind($ctrl.command) }}
+  </span>
+  <span class="command-title" ng-bind-html="::$ctrl.getCommandTitleHtml($ctrl.command)"></span>
+</span>
diff --git a/static/js/directives/ui/dockerfile-command/dockerfile-command.component.ts b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.ts
new file mode 100644
index 000000000..2e10bade7
--- /dev/null
+++ b/static/js/directives/ui/dockerfile-command/dockerfile-command.component.ts
@@ -0,0 +1,72 @@
+import { Input, Component, Inject } from 'ng-metadata/core';
+import './dockerfile-command.component.css';
+
+/**
+ * A component which displays a Dockerfile command, nicely formatted.
+ */
+@Component({
+  selector: 'dockerfile-command',
+  templateUrl: '/static/js/directives/ui/dockerfile-command/dockerfile-command.component.html',
+})
+export class DockerfileCommandComponent {
+  @Input('<') public command: string;
+
+  private registryHandlers: {[domain: string]: Function};
+
+  constructor (@Inject('Config') Config: any, @Inject('UtilService') private utilService: any) {
+    var registryHandlers = {
+      'quay.io': function(pieces) {
+        var rnamespace =  pieces[pieces.length - 2];
+        var rname = pieces[pieces.length - 1].split(':')[0];
+        return '/repository/' + rnamespace + '/' + rname + '/';
+      },
+
+      '': function(pieces) {
+        var rnamespace = pieces.length == 1 ? '_' : 'u/' + pieces[0];
+        var rname = pieces[pieces.length - 1].split(':')[0];
+        return 'https://registry.hub.docker.com/' + rnamespace + '/' + rname + '/';
+      }
+    };
+
+    registryHandlers[Config.getDomain()] = registryHandlers['quay.io'];
+    this.registryHandlers = registryHandlers;
+  }
+
+  private getCommandKind(command: string): string {
+    if (!command) { return ''; }
+
+    var space = command.indexOf(' ');
+    return command.substring(0, space);
+  }
+
+  private getCommandTitleHtml(command: string): string {
+    if (!command) { return ''; }
+
+    var kindHandlers = {
+      'FROM': (command) => {
+        var pieces = command.split('/');
+        var registry = pieces.length < 3 ? '' : pieces[0];
+        if (!this.registryHandlers[registry]) {
+          return command;
+        }
+
+        return '<i class="fa fa-hdd-o"></i> <a href="' + this.registryHandlers[registry](pieces) + '" target="_blank">' + command + '</a>';
+      }
+    };
+
+    var space = command.indexOf(' ');
+    if (space <= 0) {
+      return this.utilService.textToSafeHtml(command);
+    }
+
+    var kind = this.getCommandKind(command);
+    var sanitized = this.utilService.textToSafeHtml(command.substring(space + 1));
+
+    var handler = kindHandlers[kind || ''];
+    if (handler) {
+      return handler(sanitized);
+    } else {
+      return sanitized;
+    }
+  }
+}
diff --git a/static/js/quay.module.ts b/static/js/quay.module.ts
index c274af627..bf9f5cb2e 100644
--- a/static/js/quay.module.ts
+++ b/static/js/quay.module.ts
@@ -28,6 +28,7 @@ import { MarkdownInputComponent } from './directives/ui/markdown/markdown-input.
 import { MarkdownViewComponent } from './directives/ui/markdown/markdown-view.component';
 import { MarkdownToolbarComponent } from './directives/ui/markdown/markdown-toolbar.component';
 import { MarkdownEditorComponent } from './directives/ui/markdown/markdown-editor.component';
+import { DockerfileCommandComponent } from './directives/ui/dockerfile-command/dockerfile-command.component';
 import { BrowserPlatform, browserPlatform } from './constants/platform.constant';
 import { ManageTriggerComponent } from './directives/ui/manage-trigger/manage-trigger.component';
 import { ClipboardCopyDirective } from './directives/ui/clipboard-copy/clipboard-copy.directive';
@@ -66,6 +67,7 @@ import * as Clipboard from 'clipboard';
     MarkdownToolbarComponent,
     MarkdownEditorComponent,
     SearchBoxComponent,
+    DockerfileCommandComponent,
     TypeaheadDirective,
     ManageTriggerComponent,
     ClipboardCopyDirective,