Filter catalog in UI based on model

Issue-ID: SDC-3679
Signed-off-by: davsad <david.sadlier@est.tech>
Change-Id: Icd0eeb13dbfb1cc27745c7adf6a3212210e00a4a
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
index f79650d..f802858 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
@@ -19,22 +19,12 @@
  */
 package org.openecomp.sdc.be.servlets;
 
-import com.jcabi.aspects.Loggable;
-import fj.data.Either;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.servers.Server;
-import io.swagger.v3.oas.annotations.servers.Servers;
-import io.swagger.v3.oas.annotations.tags.Tags;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -50,8 +40,10 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ElementBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
 import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic;
@@ -83,6 +75,19 @@
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.stereotype.Controller;
 
+import com.jcabi.aspects.Loggable;
+
+import fj.data.Either;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.servers.Server;
+import io.swagger.v3.oas.annotations.servers.Servers;
+import io.swagger.v3.oas.annotations.tags.Tags;
+
 @Path("/v1/")
 /**
  *
@@ -101,15 +106,17 @@
     private final ComponentsCleanBusinessLogic componentsCleanBusinessLogic;
     private final ElementBusinessLogic elementBusinessLogic;
     private final ArtifactsBusinessLogic artifactsBusinessLogic;
+    private final ModelBusinessLogic modelBusinessLogic;
 
     @Inject
     public ElementServlet(final UserBusinessLogic userBusinessLogic, final ComponentsUtils componentsUtils,
                           final ComponentsCleanBusinessLogic componentsCleanBusinessLogic, final ElementBusinessLogic elementBusinessLogic,
-                          final ArtifactsBusinessLogic artifactsBusinessLogic) {
+                          final ArtifactsBusinessLogic artifactsBusinessLogic, final ModelBusinessLogic modelBusinessLogic) {
         super(userBusinessLogic, componentsUtils);
         this.componentsCleanBusinessLogic = componentsCleanBusinessLogic;
         this.elementBusinessLogic = elementBusinessLogic;
         this.artifactsBusinessLogic = artifactsBusinessLogic;
+        this.modelBusinessLogic = modelBusinessLogic;
     }
     /*
      ******************************************************************************
@@ -652,6 +659,7 @@
                 return buildErrorResponse(either.right().value());
             }
             consolidatedObject.put("categories", either.left().value());
+            consolidatedObject.put("models", modelBusinessLogic.listModels());
             consolidatedObject.put("version", getVersion(servletContext));
         } catch (Exception e) {
             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("getSDCVersion");
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
index c183784..f4ca52b 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
@@ -28,11 +28,11 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
-import fj.data.Either;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
@@ -40,8 +40,10 @@
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+
 import org.apache.commons.text.StrSubstitutor;
 import org.apache.http.HttpStatus;
+import org.assertj.core.util.Lists;
 import org.glassfish.hk2.utilities.binding.AbstractBinder;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -54,6 +56,7 @@
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ElementBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
@@ -89,6 +92,8 @@
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.web.context.WebApplicationContext;
 
+import fj.data.Either;
+
 class ElementServletTest extends JerseyTest {
 
     public static final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
@@ -111,6 +116,7 @@
     private static final ComponentsCleanBusinessLogic componentsCleanBusinessLogic = Mockito
         .mock(ComponentsCleanBusinessLogic.class);
     private static final ElementBusinessLogic elementBusinessLogic = Mockito.mock(ElementBusinessLogic.class);
+    private static final ModelBusinessLogic modelBusinessLogic = Mockito.mock(ModelBusinessLogic.class);
 
     private static final ResponseFormat okResponseFormat = new ResponseFormat(HttpStatus.SC_OK);
     private static final ResponseFormat conflictResponseFormat = new ResponseFormat(HttpStatus.SC_CONFLICT);
@@ -180,7 +186,7 @@
         when(webApplicationContext.getBean(ElementBusinessLogic.class)).thenReturn(elementBusinessLogic);
         when(webApplicationContext.getBean(ComponentsUtils.class)).thenReturn(componentUtils);
         when(beGenericServlet.getComponentsUtils()).thenReturn(componentUtils);
-
+        when(modelBusinessLogic.listModels()).thenReturn(Lists.emptyList());
         Either<User, ActionStatus> designerEither = Either.left(designerUser);
 
         when(userAdmin.getUser(designerUser.getUserId(), false)).thenReturn(designerUser);
@@ -1101,6 +1107,7 @@
                     bind(componentsCleanBusinessLogic).to(ComponentsCleanBusinessLogic.class);
                     bind(elementBusinessLogic).to(ElementBusinessLogic.class);
                     bind(artifactsBusinessLogic).to(ArtifactsBusinessLogic.class);
+                    bind(modelBusinessLogic).to(ModelBusinessLogic.class);
                 }
             })
             .property("contextConfig", context);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/catalog/CatalogComponent.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/catalog/CatalogComponent.java
index 5d28db9..f65c84f 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/catalog/CatalogComponent.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/catalog/CatalogComponent.java
@@ -53,6 +53,7 @@
     private Boolean isHighestVersion;
     private String lastUpdaterUserId;
     private List<CategoryDefinition> categories;
+    private String model;
 
     public List<String> getTags() {
         return tags == null ? Collections.emptyList() : ImmutableList.copyOf(tags);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
index bfb6cae..d0f1c3a 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
@@ -1336,6 +1336,7 @@
         if (isAddToCatalog(excludeTypes, metadatObj) && (existInCatalog.get(uniqueId) == null && (isDeleted == null || !isDeleted.booleanValue()))) {
             CatalogComponent catalogComponent = new CatalogComponent();
             catalogComponent.setUniqueId(uniqueId);
+            catalogComponent.setModel((String) metadatObj.get(JsonPresentationFields.MODEL.getPresentation()));
             catalogComponent
                 .setComponentType(ComponentTypeEnum.valueOf((String) metadatObj.get(JsonPresentationFields.COMPONENT_TYPE.getPresentation())));
             catalogComponent.setVersion((String) metadatObj.get(JsonPresentationFields.VERSION.getPresentation()));
diff --git a/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap
index d6091cd..b41d7ce 100644
--- a/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap
+++ b/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap
@@ -13,6 +13,7 @@
   initScopeMembers={[Function Function]}
   isDefaultFilter={[Function Function]}
   loaderService={[Function Object]}
+  models={[Function Array]}
   resourceNamePipe={[Function Object]}
   sdcConfig={[Function Object]}
   sdcMenu={[Function Object]}
@@ -47,6 +48,28 @@
           class="sdc-catalog-leftbar-container"
         >
           <div
+            class="sdc-catalog-model-filter-container"
+          >
+            <div
+              class="i-sdc-designer-leftbar-section-title pointer"
+            >
+              <span
+                class="i-sdc-designer-leftbar-section-title-icon"
+              />
+              <span
+                class="i-sdc-designer-leftbar-section-title-text"
+                data-tests-id="statusFilterTitle"
+              >
+                Model
+              </span>
+            </div>
+            <div
+              class="i-sdc-designer-leftbar-section-content"
+            >
+              <sdc-checklist />
+            </div>
+          </div>
+          <div
             class="sdc-catalog-type-filter-container"
           >
             <div
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html
index 4a13bee..d130d1e 100644
--- a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html
@@ -19,6 +19,20 @@
         <!-- LEFT SIDE -->
         <div perfectScrollbar class="sdc-catalog-body-container w-sdc-left-sidebar i-sdc-designer-left-sidebar">
             <div class="sdc-catalog-leftbar-container">
+                <!-- Model -->
+                <div class="sdc-catalog-model-filter-container">
+                    <div class="i-sdc-designer-leftbar-section-title pointer" (click)="sectionClick('model')"
+                         [ngClass]="{'expanded': expandedSection.indexOf('model') !== -1}">
+                        <span class="i-sdc-designer-leftbar-section-title-icon"></span>
+                        <span class="i-sdc-designer-leftbar-section-title-text"
+                              data-tests-id="statusFilterTitle">Model</span>
+                    </div>
+                    <div class="i-sdc-designer-leftbar-section-content">
+                        <sdc-checklist [checklistModel]="modelsChecklistModel" [testId]="'checklist-model'"
+                                       (checkedChange)="gui.onModelClick()"></sdc-checklist>
+                    </div>
+                </div>
+
                 <div class="sdc-catalog-type-filter-container">
                     <div class="i-sdc-designer-leftbar-section-title pointer"
                          (click)="sectionClick('type')"
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts
index ff27ec7..5473033 100644
--- a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts
@@ -75,18 +75,21 @@
                 components: ["Resource.VF", "Resource.VFC"],
                 order:  ["lastUpdateDate", true],
                 statuses: ["inDesign"],
+                models: ["test"],
                 term: "Vf"
             }
             checkboxesFilterMock = {
                 selectedCategoriesModel: ["serviceNewCategory.network l4+", "resourceNewCategory.allotted resource.allotted resource"],
                 selectedComponentTypes: ["Resource.VF", "Resource.VFC"],
                 selectedResourceSubTypes: ["VF", "VFC"],
-                selectedStatuses: ["NOT_CERTIFIED_CHECKOUT", "NOT_CERTIFIED_CHECKIN"]
+                selectedStatuses: ["NOT_CERTIFIED_CHECKOUT", "NOT_CERTIFIED_CHECKIN"],
+                selectedModels: ["test"]
             };
             checkboxesFilterKeysMock = {
                 categories:{_main: ["serviceNewCategory.network l4+"]},
                 componentTypes: { Resource: ["Resource.VF", "Resource.VFC"], _main: ["Resource.VFC"]},
-                statuses: {_main: ["inDesign"]}
+                statuses: {_main: ["inDesign"]},
+                models: {_main: ["test"]}
             }
 
             stateServiceMock = {
@@ -186,7 +189,7 @@
         expect(component.componentInstance.numberOfItemToDisplay).toEqual(0);
         expect(component.componentInstance.categories).toEqual(categoriesElements);
         expect(component.componentInstance.confStatus).toEqual(component.componentInstance.sdcMenu.statuses);
-        expect(component.componentInstance.expandedSection).toEqual( ["type", "category", "status"]);
+        expect(component.componentInstance.expandedSection).toEqual( ["type", "category", "status", "model"]);
         expect(component.componentInstance.catalogItems).toEqual([]);
         expect(component.componentInstance.search).toEqual({FilterTerm: ""});
         expect(component.componentInstance.initCategoriesMap).toHaveBeenCalled();
@@ -203,10 +206,12 @@
         component.componentInstance.buildChecklistModelForTypes = jest.fn();
         component.componentInstance.buildChecklistModelForCategories = jest.fn();
         component.componentInstance.buildChecklistModelForStatuses = jest.fn();
+		component.componentInstance.buildChecklistModelForModels = jest.fn();
         component.componentInstance.buildCheckboxLists();
         expect(component.componentInstance.buildChecklistModelForTypes).toHaveBeenCalled();
         expect(component.componentInstance.buildChecklistModelForCategories).toHaveBeenCalled();
         expect(component.componentInstance.buildChecklistModelForStatuses).toHaveBeenCalled();
+        expect(component.componentInstance.buildChecklistModelForModels).toHaveBeenCalled();
     });
 
     it ('should call on catalog component getTestIdForCheckboxByText ' , () => {
@@ -266,7 +271,7 @@
         component.componentInstance.initCheckboxesFilter();
         expect(component.componentInstance.checkboxesFilter.selectedComponentTypes).toEqual([]);
         expect(component.componentInstance.checkboxesFilter.selectedResourceSubTypes).toEqual([]);
-        expect(component.componentInstance.checkboxesFilter.selectedCategoriesModel).toEqual([]);
+        expect(component.componentInstance.checkboxesFilter.selectedModels).toEqual([]);
         expect(component.componentInstance.checkboxesFilter.selectedStatuses).toEqual([]);
     });
 
@@ -276,6 +281,7 @@
         expect(component.componentInstance.checkboxesFilterKeys.componentTypes).toEqual({ _main: [] });
         expect(component.componentInstance.checkboxesFilterKeys.categories).toEqual({ _main: [] });
         expect(component.componentInstance.checkboxesFilterKeys.statuses).toEqual({ _main: [] });
+        expect(component.componentInstance.checkboxesFilterKeys.models).toEqual({ _main: [] });
     });
 
     it ('should call on catalog component initCategoriesMap' , () => {
@@ -469,6 +475,7 @@
         component.componentInstance.applyFilterParamsComponents = jest.fn();
         component.componentInstance.applyFilterParamsCategories = jest.fn();
         component.componentInstance.applyFilterParamsStatuses = jest.fn();
+        component.componentInstance.applyFilterParamsModels = jest.fn();
         component.componentInstance.applyFilterParamsOrder = jest.fn();
         component.componentInstance.applyFilterParamsTerm = jest.fn();
         component.componentInstance.filterCatalogItems = jest.fn();
@@ -596,7 +603,7 @@
         component.componentInstance.applyFilterParamsToView = jest.fn();
         component.componentInstance.filterParams =  { active: true, categories: [], components: [], order:  ["lastUpdateDate", true], statuses: [], term: ""};
         component.componentInstance.$state.go = jest.fn().mockImplementation(() => Promise.resolve({ json: () => [] }));
-        const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
+        const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.models": "test", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
         component.componentInstance.changeFilterParams(filterParamsMock);
         expect(component.componentInstance.filterParams).toEqual(filterParamsMock);
         expect(component.componentInstance.$state.go).toHaveBeenCalledWith('.',newParams, {location: 'replace', notify: false});
@@ -610,7 +617,7 @@
         component.componentInstance.buildCheckboxLists = jest.fn();
         component.componentInstance.filterParams =  { active: true, categories: [], components: [], order:  ["lastUpdateDate", true], statuses: [], term: ""};
         component.componentInstance.$state.go = jest.fn().mockImplementation(() => Promise.resolve({ json: () => [] }));
-        const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
+        const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.models": "test", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
         component.componentInstance.typesChecklistModel = checkListModelMock;
         component.componentInstance.categoriesChecklistModel = checkListModelMock;
         component.componentInstance.statusChecklistModel = checkListModelMock;
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts
index 5277648..5d65260 100644
--- a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts
@@ -27,12 +27,15 @@
 import { Component, ICategoryBase, IMainCategory, ISubCategory, IConfigStatuses, ICatalogSelector, CatalogSelectorTypes } from "app/models";
 import { ResourceNamePipe } from "../../pipes/resource-name.pipe";
 import { EntityFilterPipe, IEntityFilterObject, ISearchFilter} from "../../pipes/entity-filter.pipe";
+import { Model } from "app/models/model";
+import { DEFAULT_MODEL_NAME } from "app/utils/constants";
 
 interface Gui {
     onComponentSubTypesClick:Function;
     onComponentTypeClick:Function;
     onCategoryClick:Function;
     onStatusClick:Function;
+    onModelClick:Function;
     changeFilterTerm:Function;
 }
 
@@ -40,6 +43,7 @@
     components: string[];
     categories: string[];
     statuses: (string)[];
+    models: string[];
     order: [string, boolean];
     term: string;
     active: boolean;
@@ -54,6 +58,7 @@
     componentTypes: ICheckboxesFilterMap;
     categories: ICheckboxesFilterMap;
     statuses: ICheckboxesFilterMap;
+    models: ICheckboxesFilterMap;
 }
 
 interface ICategoriesMap {
@@ -73,6 +78,7 @@
     public checkboxesFilterKeys:ICheckboxesFilterKeys;
     public gui:Gui;
     public categories:Array<IMainCategory>;
+    public models: Array<string> = new Array();
     public filteredCategories:Array<IMainCategory>;
     public confStatus:IConfigStatuses;
     public componentTypes:{[key:string]: Array<string>};
@@ -96,11 +102,13 @@
     public typesChecklistModel: SdcUiCommon.ChecklistModel;
     public categoriesChecklistModel: SdcUiCommon.ChecklistModel;
     public statusChecklistModel: SdcUiCommon.ChecklistModel;
+    public modelsChecklistModel: SdcUiCommon.ChecklistModel;
 
     private defaultFilterParams:IFilterParams = {
         components: [],
         categories: [],
         statuses: [],
+        models: [],
         order: ['lastUpdateDate', true],
         term: '',
         active: true
@@ -149,8 +157,10 @@
         this.numberOfItemToDisplay = 0;
         this.categories = this.makeSortedCategories(this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')))
             .map((cat) => <IMainCategory>cat);
+        this.models = this.cacheService.get('models').map((model:Model) => model.name);
+        this.models.unshift(DEFAULT_MODEL_NAME);
         this.confStatus = this.sdcMenu.statuses;
-        this.expandedSection = ["type", "category", "status"];
+        this.expandedSection = ["type", "category", "status", "model"];
         this.catalogItems = [];
         this.search = {FilterTerm: ""};
         this.categoriesMap = this.initCategoriesMap();
@@ -167,6 +177,7 @@
         this.buildChecklistModelForTypes();
         this.buildChecklistModelForCategories();
         this.buildChecklistModelForStatuses();
+        this.buildChecklistModelForModels();
     }
 
     private getTestIdForCheckboxByText = ( text: string ):string => {
@@ -216,6 +227,18 @@
         );
     }
 
+    private buildChecklistModelForModels() {
+        this.modelsChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.models._main,
+            this.models.map((model) => new SdcUiCommon.ChecklistItemModel(
+                model, 
+                false, 
+                this.checkboxesFilterKeys.models._main.indexOf(model) !== -1, 
+                null, 
+                this.getTestIdForCheckboxByText(model), 
+                model))
+        );
+    }
+
     private buildChecklistModelForStatuses() {
         // For statuses checklist model, use the statuses keys as values. On applying filtering map the statuses keys to statuses values.
         this.statusChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.statuses._main,
@@ -236,6 +259,7 @@
         this.checkboxesFilter.selectedResourceSubTypes = [];
         this.checkboxesFilter.selectedCategoriesModel = [];
         this.checkboxesFilter.selectedStatuses = [];
+        this.checkboxesFilter.selectedModels = [];
     }
 
     private initCheckboxesFilterKeys() {
@@ -244,6 +268,7 @@
         this.checkboxesFilterKeys.componentTypes = { _main: [] };
         this.checkboxesFilterKeys.categories = { _main: [] };
         this.checkboxesFilterKeys.statuses = { _main: [] };
+        this.checkboxesFilterKeys.models = { _main: [] };
     }
 
     private initCategoriesMap(categoriesList?:(ICategoryBase)[], parentCategory:ICategoryBase=null): ICategoriesMap {
@@ -360,6 +385,12 @@
                 term: filterTerm
             });
         };
+ 
+        this.gui.onModelClick = (): void => {
+            this.changeFilterParams({
+                models: this.makeFilterParamsFromCheckboxes(this.modelsChecklistModel)
+            });
+        };
     }
 
     public raiseNumberOfElementToDisplay(recalculate:boolean = false): void {
@@ -444,6 +475,7 @@
         this.applyFilterParamsComponents(filterParams);
         this.applyFilterParamsCategories(filterParams);
         this.applyFilterParamsStatuses(filterParams);
+        this.applyFilterParamsModels(filterParams);
         this.applyFilterParamsOrder(filterParams);
         this.applyFilterParamsTerm(filterParams);
 
@@ -499,6 +531,11 @@
         this.checkboxesFilter.selectedStatuses = _.reduce(_.flatMap(this.checkboxesFilterKeys.statuses), (stats, st:string) => [...stats, ...this.confStatus[st].values], []);
     }
 
+    private applyFilterParamsModels(filterParams: IFilterParams) {
+        this.applyFilterParamsToCheckboxes(this.modelsChecklistModel, filterParams.models);
+        this.checkboxesFilter.selectedModels = _.flatMap(this.checkboxesFilterKeys.models);
+    }
+
     private applyFilterParamsOrder(filterParams: IFilterParams) {
         this.sortBy = filterParams.order[0];
         this.reverse = filterParams.order[1];
@@ -525,6 +562,8 @@
                         paramsChecklist = paramsChecklist || this.categoriesChecklistModel;
                     case 'filter.statuses':
                         paramsChecklist = paramsChecklist || this.statusChecklistModel;
+                    case 'filter.models':
+                        paramsChecklist = paramsChecklist || this.modelsChecklistModel;
 
                         // for those cases above - split param by comma and make reduced checklist values for filter params (url)
                         newVal = _.uniq(params[k].split(','));
@@ -559,6 +598,7 @@
                 case 'components':
                 case 'categories':
                 case 'statuses':
+                case 'models':
                     newVal = changedFilterParams[k] && changedFilterParams[k].length ? changedFilterParams[k].join(',') : null;
                     break;
                 case 'order':
@@ -582,7 +622,8 @@
                 this.changeFilterParams({
                     components: this.makeFilterParamsFromCheckboxes(this.typesChecklistModel),
                     categories: this.makeFilterParamsFromCheckboxes(this.categoriesChecklistModel),
-                    statuses: this.makeFilterParamsFromCheckboxes(this.statusChecklistModel)
+                    statuses: this.makeFilterParamsFromCheckboxes(this.statusChecklistModel),
+                    models: this.makeFilterParamsFromCheckboxes(this.modelsChecklistModel)
                 });
                 // rebuild the checkboxes to show selected
                 this.buildCheckboxLists();
diff --git a/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts b/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts
index af107ed..b67f42d 100644
--- a/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts
@@ -20,7 +20,7 @@
 
 import {Pipe, PipeTransform} from "@angular/core";
 import {Component, Resource} from "app/models";
-import {ComponentType} from "app/utils/constants";
+import {ComponentType, DEFAULT_MODEL_NAME} from "app/utils/constants";
 
 export interface ISearchFilter {
     [key:string]: string;
@@ -34,6 +34,8 @@
     selectedCategoriesModel?:Array<string>;
     // Statuses
     selectedStatuses?:Array<string>;
+    // Models
+    selectedModels?:Array<string>;
     // distributed
     distributed?:Array<string>;
     // search
@@ -129,6 +131,21 @@
             filteredComponents = filteredDistributed;
         }
 
+        // filter by model
+        // --------------------------------------------------------------------------
+        if (filter.selectedModels && filter.selectedModels.length > 0) {
+            let filteredModels = [];
+            let defaultModelPresent = filter.selectedModels.indexOf(DEFAULT_MODEL_NAME) > -1;
+            angular.forEach(filteredComponents, (component:Component):void => {
+                if (filter.selectedModels.indexOf(component.model) > -1) {
+                    filteredModels.push(component);
+                } else if (!component.model && defaultModelPresent) {
+	                filteredModels.push(component);
+                }
+            });
+            filteredComponents = filteredModels;
+        }
+
         // filter by search
         // --------------------------------------------------------------------------
         if (filter.search != undefined) {
diff --git a/catalog-ui/src/app/ng2/services/config.service.ts b/catalog-ui/src/app/ng2/services/config.service.ts
index 2b9b49c..55e0899 100644
--- a/catalog-ui/src/app/ng2/services/config.service.ts
+++ b/catalog-ui/src/app/ng2/services/config.service.ts
@@ -49,6 +49,7 @@
             this.cacheService.set('serviceCategories', response.categories.serviceCategories);
             this.cacheService.set('resourceCategories', response.categories.resourceCategories);
             this.cacheService.set('UIConfiguration', response.configuration);
+            this.cacheService.set('models', response.models);
         });
         return promise;
     }
diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts
index f7cbf8d..58aa402 100644
--- a/catalog-ui/src/app/utils/constants.ts
+++ b/catalog-ui/src/app/utils/constants.ts
@@ -28,6 +28,7 @@
 export let CHANGE_COMPONENT_CSAR_VERSION_FLAG = 'changeComponentCsarVersion';
 export let PREVIOUS_CSAR_COMPONENT = 'previousCsarComponent'
 export let CATEGORY_SERVICE_METADATA_KEYS = ["Naming Policy","Service Type","Service Function","Service Role"];
+export let DEFAULT_MODEL_NAME = "SDC AID";
 
 export class GeneralStatus {
   static OK = 'OK';