From 837ce367d6f502a0dc68820a1b87cca62e461943 Mon Sep 17 00:00:00 2001
From: Oleksii Kurinnyi <okurinny@redhat.com>
Date: Thu, 14 Nov 2019 14:19:56 +0200
Subject: [PATCH] use default icon if actual icon is not accessible (#15181)

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
---
 .../devfile-selector.controller.ts            | 20 ++++++++++++++++---
 .../devfile-selector/devfile-selector.html    | 19 +++++++++---------
 .../attribute/img-src/img-src.directive.ts    | 20 ++++++++++++++++++-
 3 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.controller.ts b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.controller.ts
index d002de2b8a..e2860a80ed 100644
--- a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.controller.ts
+++ b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.controller.ts
@@ -12,6 +12,7 @@
 'use strict';
 import {CheWorkspace} from '../../../../../components/api/workspace/che-workspace.factory';
 import {DevfileRegistry, IDevfileMetaData} from '../../../../../components/api/devfile-registry.factory';
+import {ImgSrcOnloadResult} from '../../../../../components/attribute/img-src/img-src.directive';
 
 /**
  * @description This class is handling the controller of devfile selector.
@@ -21,13 +22,17 @@ export class DevfileSelectorController {
 
   static $inject = ['devfileRegistry', 'cheWorkspace'];
 
-  private devfileRegistry: DevfileRegistry;
-  private cheWorkspace: CheWorkspace;
-  private devfiles: Array<IDevfileMetaData>;
+  devfiles: Array<IDevfileMetaData>;
   devfileOrderBy: string;
   onDevfileSelect: Function;
   selectedDevfile: any;
   stackName: string;
+  iconsLoaded: {
+    iconUrl?: boolean;
+  } = {};
+
+  private devfileRegistry: DevfileRegistry;
+  private cheWorkspace: CheWorkspace;
 
   /**
    * Default constructor that is using resource injection
@@ -68,4 +73,13 @@ export class DevfileSelectorController {
       });
     }
   }
+
+  iconOnLoad(iconUrl: string, result: ImgSrcOnloadResult): void {
+    this.iconsLoaded[iconUrl] = result.loaded;
+  }
+
+  showIcon(iconUrl: string): boolean {
+    return !!this.iconsLoaded[iconUrl];
+  }
+
 }
diff --git a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.html b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.html
index 698785c795..5165b3e1da 100644
--- a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.html
+++ b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/devfile-selector/devfile-selector.html
@@ -21,11 +21,11 @@
               <che-list-header-column flex="50"
                                       che-sort-value="devfileSelectorController.devfileOrderBy"
                                       che-sort-item="description"
-                                      che-column-title="Description"></che-list-header-column>            
+                                      che-column-title="Description"></che-list-header-column>
               <che-list-header-column flex="10"
                                       che-sort-value="devfileSelectorController.devfileOrderBy"
                                       che-sort-item="globalMemoryLimit"
-                                      che-column-title="Required memory"></che-list-header-column>                                                
+                                      che-column-title="Required memory"></che-list-header-column>
             </div>
           </div>
         </che-list-header>
@@ -42,11 +42,12 @@
                   <!-- Icon -->
                   <div class="devfile-selector-icon-column"
                         layout="column" layout-align="center center">
-                    <div ng-if="devfile.icon" class="devfile-selector-item-icon">
-                      <img ng-src="{{devfile.icon}}"/>
-                    </div>
-                    <div ng-if="!devfile.icon" class="devfile-selector-item-icon blank-icon">
-                      <div class="chefont cheico-type-blank"></div>
+                    <div class="devfile-selector-item-icon">
+                      <img img-src="{{devfile.icon}}"
+                        img-src-onload="devfileSelectorController.iconOnLoad(devfile.icon, $result)"
+                        ng-show="devfileSelectorController.showIcon(devfile.icon)===true">
+                      <div class="chefont cheico-type-blank"
+                        ng-show="devfileSelectorController.showIcon(devfile.icon)===false"></div>
                     </div>
                   </div>
                   <!-- Name -->
@@ -57,8 +58,8 @@
                   <div flex="50">
                     <span class="che-list-item-secondary" devfile-description="{{devfile.description}}">{{devfile.description}}</span>
                   </div>
-                   <!-- Memory -->
-                   <div flex="10">
+                  <!-- Memory -->
+                  <div flex="10">
                     <span class="che-list-item-secondary" devfile-memory="{{devfile.globalMemoryLimit}}">{{devfile.globalMemoryLimit}}</span>
                   </div>
                 </div>
diff --git a/dashboard/src/components/attribute/img-src/img-src.directive.ts b/dashboard/src/components/attribute/img-src/img-src.directive.ts
index f4c2d50347..e2cfe55f57 100644
--- a/dashboard/src/components/attribute/img-src/img-src.directive.ts
+++ b/dashboard/src/components/attribute/img-src/img-src.directive.ts
@@ -11,9 +11,17 @@
  */
 'use strict';
 
+export type ImgSrcOnloadResult = {
+  loaded: boolean;
+};
+
 /**
  * Fetches images using the $http service.
  *
+ * @usage
+ *   <img img-src="ctrl.imageSrc"
+ *        img-src-onload="ctrl.onImageLoad($result)">
+ *
  * @author Oleksii Kurinnyi
  */
 export class ImgSrc implements ng.IDirective {
@@ -34,6 +42,13 @@ export class ImgSrc implements ng.IDirective {
   }
 
   link($scope: ng.IScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes): void {
+    const onload = (loaded: boolean) => {
+      if (!$attrs.imgSrcOnload) {
+        return;
+      }
+      $scope.$eval($attrs.imgSrcOnload, { $result: { loaded } });
+    };
+
     $attrs.$observe('imgSrc', (url: string) => {
       if (this.isDev) {
         url = url.replace(/https?:\/\/[^\/]+/, '');
@@ -44,9 +59,12 @@ export class ImgSrc implements ng.IDirective {
         url: url,
         cache: 'true'
       };
-      this.$http(requestConfig).then((response: any) => {
+      this.$http<string>(requestConfig).then((response: ng.IHttpResponse<string>) => {
         const blob = new Blob([response.data], {type: response.headers('Content-Type')});
         $attrs.$set('src', (window.URL || (window as any).webkitURL).createObjectURL(blob));
+        onload(true);
+      }, () => {
+        onload(false);
       });
     });
   }
-- 
GitLab