<commit_before>'use strict';

(function (angular) {
  angular.module('vimeoPluginWidget')
    .controller('WidgetFeedCtrl', ['$scope', 'Buildfire', 'DataStore', 'TAG_NAMES', 'STATUS_CODE', 'VimeoApi', '$routeParams', 'VIDEO_COUNT', '$sce', 'Location', '$rootScope', 'LAYOUTS', 'CONTENT_TYPE',
      function ($scope, Buildfire, DataStore, TAG_NAMES, STATUS_CODE, VimeoApi, $routeParams, VIDEO_COUNT, $sce, Location, $rootScope, LAYOUTS, CONTENT_TYPE) {
        var WidgetFeed = this;

        WidgetFeed.data = null;
        //create new instance of buildfire carousel viewer
        var view = null;
        WidgetFeed.videos = [];
        WidgetFeed.busy = false;
        WidgetFeed.nextPageToken = 1;
        var currentListLayout = null;
        var currentFeedId = $routeParams.feedId;
        var feedType = "Channel";

        /*
         * Fetch user's data from datastore
         */
        var init = function () {
          var success = function (result) {
              WidgetFeed.data = result.data;
              if (!WidgetFeed.data.content)
                WidgetFeed.data.content = {};
              if (!WidgetFeed.data.design)
                WidgetFeed.data.design = {};
              if (!WidgetFeed.data.design.itemListLayout) {
                WidgetFeed.data.design.itemListLayout = LAYOUTS.listLayouts[0].name;
              }
              currentListLayout = WidgetFeed.data.design.itemListLayout;
              if (WidgetFeed.data.content && !currentFeedId) {
                currentFeedId = WidgetFeed.data.content.feedID;
              }
            }
            , error = function (err) {
              if (err && err.code !== STATUS_CODE.NOT_FOUND) {
                console.error('Error while getting data', err);
              }
            };
          DataStore.get(TAG_NAMES.VIMEO_INFO).then(success, error);
        };

        init();
        $rootScope.$on("Carousel:LOADED", function () {
          if (!view) {
            view = new Buildfire.components.carousel.view("#carousel", []);
          }
          if (WidgetFeed.data.content && WidgetFeed.data.content.carouselImages) {
            view.loadItems(WidgetFeed.data.content.carouselImages);
          } else {
            view.loadItems([]);
          }
        });

        var getFeedVideos = function (_feedId) {
          Buildfire.spinner.show();
          var success = function (result) {
              Buildfire.spinner.hide();
              WidgetFeed.videos = WidgetFeed.videos.length ? WidgetFeed.videos.concat(result.data.data) : result.data.data;
              WidgetFeed.nextPageToken = result.data.page + 1;
              if (WidgetFeed.videos.length < result.data.total) {
                WidgetFeed.busy = false;
              }
            }
            , error = function (err) {
              Buildfire.spinner.hide();
              console.log('Error In Fetching Single Video Details', err);
            };
          if (WidgetFeed.data && WidgetFeed.data.content && WidgetFeed.data.content.type === CONTENT_TYPE.USER_FEED)
            feedType = "User";
          else
            feedType = "Channel";
          VimeoApi.getFeedVideos(feedType, _feedId, VIDEO_COUNT.LIMIT, WidgetFeed.nextPageToken).then(success, error);
        };

        var onUpdateCallback = function (event) {
          if (event && event.tag === TAG_NAMES.VIMEO_INFO) {
            WidgetFeed.data = event.data;
            if (!WidgetFeed.data.content)
              WidgetFeed.data.content = {};
            if (!WidgetFeed.data.design)
              WidgetFeed.data.design = {};
            if (!WidgetFeed.data.design.itemListLayout) {
              WidgetFeed.data.design.itemListLayout = LAYOUTS.listLayouts[0].name;
            }
            if (WidgetFeed.data.design && WidgetFeed.data.content) {
              if ((currentListLayout != WidgetFeed.data.design.itemListLayout) && view && WidgetFeed.data.content.carouselImages) {
                view._destroySlider();
                view = null;
              }
              else {
                if (view) {
                  view.loadItems(WidgetFeed.data.content.carouselImages);
                }
              }
              currentListLayout = WidgetFeed.data.design.itemListLayout;
            }

            if (!WidgetFeed.data.content.rssUrl) {
              WidgetFeed.videos = [];
              WidgetFeed.busy = false;
              WidgetFeed.nextPageToken = 1;
            } else if (!(WidgetFeed.videos.length > 0) && WidgetFeed.data.content.feedID) {
              currentFeedId = WidgetFeed.data.content.feedID;
              getFeedVideos(WidgetFeed.data.content.feedID);
            }

            if (WidgetFeed.data.content && WidgetFeed.data.content.feedID && (WidgetFeed.data.content.feedID !== currentFeedId)) {
              currentFeedId = WidgetFeed.data.content.feedID;
              Location.goTo("#/feed/" + WidgetFeed.data.content.feedID);
            } else if (WidgetFeed.data.content && WidgetFeed.data.content.videoID)
              Location.goTo("#/video/" + WidgetFeed.data.content.videoID);
          }
        };
        DataStore.onUpdate().then(null, null, onUpdateCallback);

        WidgetFeed.loadMore = function () {
          if (WidgetFeed.busy) return;
          WidgetFeed.busy = true;
          getFeedVideos(currentFeedId);
        };

        WidgetFeed.safeHtml = function (html) {
          if (html)
            return $sce.trustAsHtml(html);
        };

        WidgetFeed.showDescription = function (description) {
          return !(description == '

');
        };
        $scope.$on("$destroy", function () {
          DataStore.clearListener();
        });
      }])
})(window.angular);
<commit_msg>Added check to handle error showed on console<commit_after>'use strict';

(function (angular) {
  angular.module('vimeoPluginWidget')
    .controller('WidgetFeedCtrl', ['$scope', 'Buildfire', 'DataStore', 'TAG_NAMES', 'STATUS_CODE', 'VimeoApi', '$routeParams', 'VIDEO_COUNT', '$sce', 'Location', '$rootScope', 'LAYOUTS', 'CONTENT_TYPE',
      function ($scope, Buildfire, DataStore, TAG_NAMES, STATUS_CODE, VimeoApi, $routeParams, VIDEO_COUNT, $sce, Location, $rootScope, LAYOUTS, CONTENT_TYPE) {
        var WidgetFeed = this;

        WidgetFeed.data = null;
        //create new instance of buildfire carousel viewer
        var view = null;
        WidgetFeed.videos = [];
        WidgetFeed.busy = false;
        WidgetFeed.nextPageToken = 1;
        var currentListLayout = null;
        var currentFeedId = $routeParams.feedId;
        var feedType = "Channel";

        /*
         * Fetch user's data from datastore
         */
        var init = function () {
          var success = function (result) {
              WidgetFeed.data = result.data;
              if (!WidgetFeed.data.content)
                WidgetFeed.data.content = {};
              if (!WidgetFeed.data.design)
                WidgetFeed.data.design = {};
              if (!WidgetFeed.data.design.itemListLayout) {
                WidgetFeed.data.design.itemListLayout = LAYOUTS.listLayouts[0].name;
              }
              currentListLayout = WidgetFeed.data.design.itemListLayout;
              if (WidgetFeed.data.content && !currentFeedId) {
                currentFeedId = WidgetFeed.data.content.feedID;
              }
            }
            , error = function (err) {
              if (err && err.code !== STATUS_CODE.NOT_FOUND) {
                console.error('Error while getting data', err);
              }
            };
          DataStore.get(TAG_NAMES.VIMEO_INFO).then(success, error);
        };

        init();
        $rootScope.$on("Carousel:LOADED", function () {
          if (!view) {
            view = new Buildfire.components.carousel.view("#carousel", []);
          }
          if (WidgetFeed.data.content && WidgetFeed.data.content.carouselImages) {
            view.loadItems(WidgetFeed.data.content.carouselImages);
          } else {
            view.loadItems([]);
          }
        });

        var getFeedVideos = function (_feedId) {
          Buildfire.spinner.show();
          var success = function (result) {
              Buildfire.spinner.hide();
              WidgetFeed.videos = WidgetFeed.videos.length ? WidgetFeed.videos.concat(result.data.data) : result.data.data;
              WidgetFeed.nextPageToken = result.data.page + 1;
              if (WidgetFeed.videos.length < result.data.total) {
                WidgetFeed.busy = false;
              }
            }
            , error = function (err) {
              Buildfire.spinner.hide();
              console.log('Error In Fetching Single Video Details', err);
            };
          if (WidgetFeed.data && WidgetFeed.data.content && WidgetFeed.data.content.type === CONTENT_TYPE.USER_FEED)
            feedType = "User";
          else
            feedType = "Channel";
          VimeoApi.getFeedVideos(feedType, _feedId, VIDEO_COUNT.LIMIT, WidgetFeed.nextPageToken).then(success, error);
        };

        var onUpdateCallback = function (event) {
          if (event && event.tag === TAG_NAMES.VIMEO_INFO) {
            WidgetFeed.data = event.data;
            if (!WidgetFeed.data.content)
              WidgetFeed.data.content = {};
            if (!WidgetFeed.data.design)
              WidgetFeed.data.design = {};
            if (!WidgetFeed.data.design.itemListLayout) {
              WidgetFeed.data.design.itemListLayout = LAYOUTS.listLayouts[0].name;
            }
            if (WidgetFeed.data.design && WidgetFeed.data.content) {
              if ((currentListLayout != WidgetFeed.data.design.itemListLayout) && view && WidgetFeed.data.content.carouselImages) {
                view._destroySlider();
                view = null;
              }
              else {
                if (view) {
                  view.loadItems(WidgetFeed.data.content.carouselImages);
                }
              }
              currentListLayout = WidgetFeed.data.design.itemListLayout;
            }

            if (!WidgetFeed.data.content.rssUrl) {
              WidgetFeed.videos = [];
              WidgetFeed.busy = false;
              WidgetFeed.nextPageToken = 1;
            } else if (!(WidgetFeed.videos.length > 0) && WidgetFeed.data.content.feedID) {
              currentFeedId = WidgetFeed.data.content.feedID;
              getFeedVideos(WidgetFeed.data.content.feedID);
            }

            if (WidgetFeed.data.content && WidgetFeed.data.content.feedID && (WidgetFeed.data.content.feedID !== currentFeedId)) {
              currentFeedId = WidgetFeed.data.content.feedID;
              Location.goTo("#/feed/" + WidgetFeed.data.content.feedID);
            } else if (WidgetFeed.data.content && WidgetFeed.data.content.videoID)
              Location.goTo("#/video/" + WidgetFeed.data.content.videoID);
          }
        };
        DataStore.onUpdate().then(null, null, onUpdateCallback);

        WidgetFeed.loadMore = function () {
          if (WidgetFeed.busy) return;
          WidgetFeed.busy = true;
          if (currentFeedId && currentFeedId !== '1') {
            getFeedVideos(currentFeedId);
          }
        };

        WidgetFeed.safeHtml = function (html) {
          if (html)
            return $sce.trustAsHtml(html);
        };

        WidgetFeed.showDescription = function (description) {
          return !(description == '

');
        };
        $scope.$on("$destroy", function () {
          DataStore.clearListener();
        });
      }])
})(window.angular);
<|endoftext|>


<commit_before>'use strict';

(function (angular, buildfire) {
  angular.module('seminarNotesPluginWidget')
    .controller('WidgetHomeCtrl', ['$scope', 'TAG_NAMES', 'LAYOUTS', 'DataStore', 'PAGINATION', 'Buildfire', 'Location', '$rootScope', 'ViewStack', '$sce', 'UserData', 'SORT', '$modal',
      function ($scope, TAG_NAMES, LAYOUTS, DataStore, PAGINATION, Buildfire, Location, $rootScope, ViewStack, $sce, UserData, SORT, $modal) {
        var WidgetHome = this;
        var currentListLayout, currentSortOrder = null;
        $rootScope.deviceHeight = window.innerHeight;
        $rootScope.deviceWidth = window.innerWidth || 320;
        WidgetHome.busy = false;
        WidgetHome.items = [];
        $scope.isClicked = false;
        WidgetHome.bookmarkItem = [];
        WidgetHome.bookmarks = {};
        $scope.isFetchedAllData = false;
        WidgetHome.listeners={};
        var searchOptions = {
          skip: 0,
          limit: PAGINATION.itemCount
        };

        /**
         * WidgetHome.sortingOptions are used to show options in Sort Items drop-down menu in home.html.
         */
        WidgetHome.sortingOptions = [
          SORT.MANUALLY,
          SORT.ITEM_TITLE_A_Z,
          SORT.ITEM_TITLE_Z_A,
          SORT.NEWEST_PUBLICATION_DATE,
          SORT.OLDEST_PUBLICATION_DATE,
          SORT.NEWEST_FIRST,
          SORT.OLDEST_FIRST
        ];

        /**
         * getSearchOptions(value) is used to get searchOptions with one more key sort which decide the order of sorting.
         */
        WidgetHome.getSearchOptions = function (value) {
          switch (value) {
            case SORT.ITEM_TITLE_A_Z:
              searchOptions.sort = {"title": 1};
              break;
            case SORT.ITEM_TITLE_Z_A:
              searchOptions.sort = {"title": -1};
              break;
            case SORT.NEWEST_PUBLICATION_DATE:
              searchOptions.sort = {"publishedOn": 1};
              break;
            case SORT.OLDEST_PUBLICATION_DATE:
              searchOptions.sort = {"publishedOn": -1};
              break;
            case SORT.NEWEST_FIRST:
              searchOptions.sort = {"dateCreated": -1};
              break;
            case SORT.OLDEST_FIRST:
              searchOptions.sort = {"dateCreated": 1};
              break;
            default :
              searchOptions.sort = {"rank": 1};
              break;
          }
          return searchOptions;
        };

        WidgetHome.data = {
          design: {
            itemListLayout: LAYOUTS.itemListLayout[0].name
          }
        };
        WidgetHome.init = function () {
          Buildfire.spinner.show();
          var success = function (result) {
              Buildfire.spinner.hide();
              if (result && result.data) {
                WidgetHome.data = result.data;
              }
              else {
                WidgetHome.data = {
                  design: {
                    itemListLayout: LAYOUTS.itemListLayout[0].name
                  }
                };
              }
              if (WidgetHome.data && !WidgetHome.data.design) {
                WidgetHome.data.design = {
                  itemListLayout: LAYOUTS.itemListLayout[0].name
                };
              }
              currentListLayout = WidgetHome.data.design.itemListLayout;
              if (!WidgetHome.data.design)
                WidgetHome.data.design = {};
              if (!WidgetHome.data.design.itemListLayout) {
                WidgetHome.data.design.itemListLayout = LAYOUTS.itemListLayout[0].name;
              }
              if (!WidgetHome.data.content)
                WidgetHome.data.content = {};
              if (WidgetHome.data.content.sortBy) {
                currentSortOrder = WidgetHome.data.content.sortBy;
              }

              if (!WidgetHome.data.design.itemListBgImage) {
                $rootScope.itemListbackgroundImage = "";
              } else {
                $rootScope.itemListbackgroundImage = WidgetHome.data.design.itemListBgImage;
              }
              console.log("==============", WidgetHome.data.design)
            }
            , error = function (err) {
              Buildfire.spinner.hide();
              WidgetHome.data = {design: {itemListLayout: LAYOUTS.itemListLayout[0].name}};
              console.error('Error while getting data', err);
            };
          DataStore.get(TAG_NAMES.SEMINAR_INFO).then(success, error);
        };

        WidgetHome.getBookMarkData = function (setBookMarks) {
          Buildfire.spinner.show();
          var err = function (error) {
            Buildfire.spinner.hide();
            console.log("============ There is an error in getting data", error);
          }, result = function (result) {
            Buildfire.spinner.hide();
            console.log("===========Bookmarks", result);
            WidgetHome.bookmarks = result;
            if (setBookMarks)
              WidgetHome.setBookmarks();
          };

          UserData.search({}, TAG_NAMES.SEMINAR_BOOKMARKS).then(result, err);
        };

        WidgetHome.setBookmarks = function () {
          for (var item = 0; item < WidgetHome.items.length; item++) {
            WidgetHome.items[item].isBookmarked = false;
            for (var bookmark in WidgetHome.bookmarks) {
              if (WidgetHome.items[item].id == WidgetHome.bookmarks[bookmark].data.itemId) {
                WidgetHome.items[item].isBookmarked = true;
                WidgetHome.items[item].bookmarkId = WidgetHome.bookmarks[bookmark].id;
              }
            }
          }
          console.log("$$$$$$$$$$$$$$$$$$",WidgetHome.bookmarks, WidgetHome.items);
          $scope.isFetchedAllData = true;
        };
        WidgetHome.init();

        WidgetHome.safeHtml = function (html) {
          if (html) {
            var $html = $('
', {html: html});
            $html.find('iframe').each(function (index, element) {
              var src = element.src;
              console.log('element is: ', src, src.indexOf('http'));
              src = src && src.indexOf('file://') != -1 ? src.replace('file://', 'http://') : src;
              element.src = src && src.indexOf('http') != -1 ? src : 'http:' + src;
            });
            return $sce.trustAsHtml($html.html());
          }
        };

        /**
         * This event listener is bound for "Carousel:LOADED" event broadcast
         */
        $rootScope.$on("Carousel:LOADED", function () {
          WidgetHome.view = null;
          if (!WidgetHome.view) {
            WidgetHome.view = new Buildfire.components.carousel.view("#carousel", []);
          }
          if (WidgetHome.data.content && WidgetHome.data.content.carouselImages) {
            WidgetHome.view.loadItems(WidgetHome.data.content.carouselImages);
          } else {
            WidgetHome.view.loadItems([]);
          }
        });
        WidgetHome.showBookmarkItems = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Bookmarks',
              params: {
                controller: "WidgetBookmarkCtrl as WidgetBookmark"
              }
            });
          } else {
            WidgetHome.openLogin();
          }
        };

        WidgetHome.showItemNotes = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Notes',
              params: {
                controller: "WidgetNotesCtrl as WidgetNotes"
              }
            });
          }
          else {
            WidgetHome.openLogin();
          }
        };
        var onUpdateCallback = function (event) {
          console.log(event);
          setTimeout(function () {
            $scope.$digest();
            if (event && event.tag === TAG_NAMES.SEMINAR_INFO) {
              WidgetHome.data = event.data;
              if (!WidgetHome.data.design)
                WidgetHome.data.design = {};
              if (!WidgetHome.data.content)
                WidgetHome.data.content = {};
              if (event.data.content.sortBy && currentSortOrder != event.data.content.sortBy) {
                WidgetHome.data.content.sortBy = event.data.content.sortBy;
                WidgetHome.items = [];
                searchOptions.skip = 0;
                WidgetHome.busy = false;
                WidgetHome.loadMore();
              }
              if (!WidgetHome.data.design.itemListBgImage) {
                $rootScope.itemListbackgroundImage = "";
              } else {
                $rootScope.itemListbackgroundImage = WidgetHome.data.design.itemListBgImage;
              }
            }
            else if (event && event.tag === TAG_NAMES.SEMINAR_ITEMS) {
              WidgetHome.items = [];
              searchOptions.skip = 0;
              WidgetHome.busy = false;
              WidgetHome.loadMore();
            }

            if (!WidgetHome.data.design.itemListLayout) {
              WidgetHome.data.design.itemListLayout = LAYOUTS.itemListLayout[0].name;
            }
            if (currentListLayout != WidgetHome.data.design.itemListLayout && WidgetHome.view && WidgetHome.data.content.carouselImages) {
              WidgetHome.view._destroySlider();
              WidgetHome.view = null;
              console.log("==========1")
            }
            else {
              if (WidgetHome.view) {
                WidgetHome.view.loadItems(WidgetHome.data.content.carouselImages);
                console.log("==========2")
              }
            }
            currentListLayout = WidgetHome.data.design.itemListLayout;
            $scope.$digest();
            $rootScope.$digest();
          }, 0);
        };
        DataStore.onUpdate().then(null, null, onUpdateCallback);

        WidgetHome.loadMore = function () {
          console.log("===============In loadmore");
          if (WidgetHome.busy) return;
          WidgetHome.busy = true;
          WidgetHome.getItems();
        };

        WidgetHome.getItems = function () {
          Buildfire.spinner.show();
          var successAll = function (resultAll) {
              Buildfire.spinner.hide();
              WidgetHome.items = WidgetHome.items.length ? WidgetHome.items.concat(resultAll) : resultAll;
              searchOptions.skip = searchOptions.skip + PAGINATION.itemCount;
              if (resultAll.length == PAGINATION.itemCount) {
                WidgetHome.busy = false;
              }
              console.log("----------------------",WidgetHome.items)
              WidgetHome.setBookmarks();
            },
            errorAll = function (error) {
              Buildfire.spinner.hide();
              console.log("error", error)
            };
          console.log("***********", WidgetHome.data.content);
          if (WidgetHome.data && WidgetHome.data.content && WidgetHome.data.content.sortBy) {
            searchOptions = WidgetHome.getSearchOptions(WidgetHome.data.content.sortBy);
          }
          DataStore.search(searchOptions, TAG_NAMES.SEMINAR_ITEMS).then(successAll, errorAll);
        };

        WidgetHome.openDetails = function (itemId) {
          ViewStack.push({
            template: 'Item',
            params: {
              controller: "WidgetItemCtrl as WidgetItem",
              itemId: itemId
            }
          });

          //buildfire.messaging.sendMessageToControl({
          //  type: 'OpenItem',
          //  data: {"id": itemId}
          //});
        };

        WidgetHome.currentLoggedInUser = null;

        /**
         * Method to open buildfire auth login pop up and allow user to login using credentials.
         */
        WidgetHome.openLogin = function () {
          buildfire.auth.login({}, function () {

          });
        };

        var loginCallback = function () {
          buildfire.auth.getCurrentUser(function (err, user) {
            console.log("=========User", user);
            if (user) {
              WidgetHome.currentLoggedInUser = user;
              $scope.$apply();
              WidgetHome.getBookMarkData(true);
            }
          });
        };

        buildfire.auth.onLogin(loginCallback);

        /**
         * Check for current logged in user, if not show ogin screen
         */
        buildfire.auth.getCurrentUser(function (err, user) {
          console.log("===========LoggedInUser", user);
          if (user) {
            WidgetHome.currentLoggedInUser = user;
            $scope.$apply();
            WidgetHome.getBookMarkData();
          }
        });

        WidgetHome.addToBookmark = function (item, isBookmarked, index) {
          console.log("$$$$$$$$$$$$$$$$$", item, isBookmarked, index);
          Buildfire.spinner.show();
          if (isBookmarked && item.bookmarkId) {
            var successRemove = function (result) {
              Buildfire.spinner.hide();
              WidgetHome.items[index].isBookmarked = false;
              WidgetHome.items[index].bookmarkId = null;
              if (!$scope.$$phase)
                $scope.$digest();
              $modal.open({
                templateUrl: 'templates/Bookmark_Removed.html',
                size: 'sm'
              });
            }, errorRemove = function () {
              Buildfire.spinner.hide();
              return console.error('There was a problem removing your data');
            };
            UserData.delete(item.bookmarkId, TAG_NAMES.SEMINAR_BOOKMARKS, WidgetHome.currentLoggedInUser._id).then(successRemove, errorRemove)
          } else {
            WidgetHome.bookmarkItem = {
              data: {
                itemId: item.id
              }
            };
            var successItem = function (result) {
              Buildfire.spinner.hide();
              console.log("Inserted", result);
              WidgetHome.items[index].isBookmarked = true;
              if (!$scope.$$phase)
                $scope.$digest();
              $modal.open({
                templateUrl: 'templates/Bookmark_Confirm.html',
                size: 'sm'
              });
            }, errorItem = function () {
              Buildfire.spinner.hide();
              return console.error('There was a problem saving your data');
            };
            UserData.insert(WidgetHome.bookmarkItem.data, TAG_NAMES.SEMINAR_BOOKMARKS).then(successItem, errorItem);
          }
        };

        WidgetHome.showSearchPage = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Search',
              params: {
                controller: "WidgetSearchCtrl as WidgetSearch"
              }
            });
          } else {
            WidgetHome.openLogin();
          }
        };

        WidgetHome.showDescription = function (description) {
          return !((description == '

') || (description == '

') || (description == ''));
        };

        $rootScope.$on('NEW_ITEM_ADDED_UPDATED', function (e) {
          WidgetHome.items = [];
          searchOptions.skip = 0;
          WidgetHome.busy = false;
          WidgetHome.loadMore();
        });

        $rootScope.$on('ITEM_BOOKMARKED', function (e) {
          WidgetHome.getBookMarkData(true);
        });

        $scope.$on("$destroy", function () {
          console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed211112");
          for (var i in WidgetHome.listeners) {
            if (WidgetHome.listeners.hasOwnProperty(i)) {
              WidgetHome.listeners[i]();
            }
          }
          DataStore.clearListener();
        });

        WidgetHome.listeners['CHANGED'] = $rootScope.$on('VIEW_CHANGED', function (e, type, view) {
          if (type === 'POP') {
            console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed311113");
            DataStore.onUpdate().then(null, null, onUpdateCallback);
            WidgetHome.getBookMarkData(true);
            WidgetHome.setBookmarks();
           }
          if (type === 'POPALL') {
            console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed311113");
            DataStore.onUpdate().then(null, null, onUpdateCallback);
            WidgetHome.getBookMarkData(true);
            WidgetHome.setBookmarks();
          }
        });
      }])
})(window.angular, window.buildfire);
<commit_msg>Fixed the multiple bookmark adding issue for the home screen.<commit_after>'use strict';

(function (angular, buildfire) {
  angular.module('seminarNotesPluginWidget')
    .controller('WidgetHomeCtrl', ['$scope', 'TAG_NAMES', 'LAYOUTS', 'DataStore', 'PAGINATION', 'Buildfire', 'Location', '$rootScope', 'ViewStack', '$sce', 'UserData', 'SORT', '$modal',
      function ($scope, TAG_NAMES, LAYOUTS, DataStore, PAGINATION, Buildfire, Location, $rootScope, ViewStack, $sce, UserData, SORT, $modal) {
        var WidgetHome = this;
        var currentListLayout, currentSortOrder = null;
        $rootScope.deviceHeight = window.innerHeight;
        $rootScope.deviceWidth = window.innerWidth || 320;
        WidgetHome.busy = false;
        WidgetHome.items = [];
        $scope.isClicked = false;
        WidgetHome.bookmarkItem = [];
        WidgetHome.bookmarks = {};
        $scope.isFetchedAllData = false;
        WidgetHome.listeners={};
        var searchOptions = {
          skip: 0,
          limit: PAGINATION.itemCount
        };

        /**
         * WidgetHome.sortingOptions are used to show options in Sort Items drop-down menu in home.html.
         */
        WidgetHome.sortingOptions = [
          SORT.MANUALLY,
          SORT.ITEM_TITLE_A_Z,
          SORT.ITEM_TITLE_Z_A,
          SORT.NEWEST_PUBLICATION_DATE,
          SORT.OLDEST_PUBLICATION_DATE,
          SORT.NEWEST_FIRST,
          SORT.OLDEST_FIRST
        ];

        /**
         * getSearchOptions(value) is used to get searchOptions with one more key sort which decide the order of sorting.
         */
        WidgetHome.getSearchOptions = function (value) {
          switch (value) {
            case SORT.ITEM_TITLE_A_Z:
              searchOptions.sort = {"title": 1};
              break;
            case SORT.ITEM_TITLE_Z_A:
              searchOptions.sort = {"title": -1};
              break;
            case SORT.NEWEST_PUBLICATION_DATE:
              searchOptions.sort = {"publishedOn": 1};
              break;
            case SORT.OLDEST_PUBLICATION_DATE:
              searchOptions.sort = {"publishedOn": -1};
              break;
            case SORT.NEWEST_FIRST:
              searchOptions.sort = {"dateCreated": -1};
              break;
            case SORT.OLDEST_FIRST:
              searchOptions.sort = {"dateCreated": 1};
              break;
            default :
              searchOptions.sort = {"rank": 1};
              break;
          }
          return searchOptions;
        };

        WidgetHome.data = {
          design: {
            itemListLayout: LAYOUTS.itemListLayout[0].name
          }
        };
        WidgetHome.init = function () {
          Buildfire.spinner.show();
          var success = function (result) {
              Buildfire.spinner.hide();
              if (result && result.data) {
                WidgetHome.data = result.data;
              }
              else {
                WidgetHome.data = {
                  design: {
                    itemListLayout: LAYOUTS.itemListLayout[0].name
                  }
                };
              }
              if (WidgetHome.data && !WidgetHome.data.design) {
                WidgetHome.data.design = {
                  itemListLayout: LAYOUTS.itemListLayout[0].name
                };
              }
              currentListLayout = WidgetHome.data.design.itemListLayout;
              if (!WidgetHome.data.design)
                WidgetHome.data.design = {};
              if (!WidgetHome.data.design.itemListLayout) {
                WidgetHome.data.design.itemListLayout = LAYOUTS.itemListLayout[0].name;
              }
              if (!WidgetHome.data.content)
                WidgetHome.data.content = {};
              if (WidgetHome.data.content.sortBy) {
                currentSortOrder = WidgetHome.data.content.sortBy;
              }

              if (!WidgetHome.data.design.itemListBgImage) {
                $rootScope.itemListbackgroundImage = "";
              } else {
                $rootScope.itemListbackgroundImage = WidgetHome.data.design.itemListBgImage;
              }
              console.log("==============", WidgetHome.data.design)
            }
            , error = function (err) {
              Buildfire.spinner.hide();
              WidgetHome.data = {design: {itemListLayout: LAYOUTS.itemListLayout[0].name}};
              console.error('Error while getting data', err);
            };
          DataStore.get(TAG_NAMES.SEMINAR_INFO).then(success, error);
        };

        WidgetHome.getBookMarkData = function (setBookMarks) {
          Buildfire.spinner.show();
          var err = function (error) {
            Buildfire.spinner.hide();
            console.log("============ There is an error in getting data", error);
          }, result = function (result) {
            Buildfire.spinner.hide();
            console.log("===========Bookmarks", result);
            WidgetHome.bookmarks = result;
            if (setBookMarks)
              WidgetHome.setBookmarks();
          };

          UserData.search({}, TAG_NAMES.SEMINAR_BOOKMARKS).then(result, err);
        };

        WidgetHome.setBookmarks = function () {
          for (var item = 0; item < WidgetHome.items.length; item++) {
            WidgetHome.items[item].isBookmarked = false;
            for (var bookmark in WidgetHome.bookmarks) {
              if (WidgetHome.items[item].id == WidgetHome.bookmarks[bookmark].data.itemId) {
                WidgetHome.items[item].isBookmarked = true;
                WidgetHome.items[item].bookmarkId = WidgetHome.bookmarks[bookmark].id;
              }
            }
          }
          console.log("$$$$$$$$$$$$$$$$$$",WidgetHome.bookmarks, WidgetHome.items);
          $scope.isFetchedAllData = true;
        };
        WidgetHome.init();

        WidgetHome.safeHtml = function (html) {
          if (html) {
            var $html = $('
', {html: html});
            $html.find('iframe').each(function (index, element) {
              var src = element.src;
              console.log('element is: ', src, src.indexOf('http'));
              src = src && src.indexOf('file://') != -1 ? src.replace('file://', 'http://') : src;
              element.src = src && src.indexOf('http') != -1 ? src : 'http:' + src;
            });
            return $sce.trustAsHtml($html.html());
          }
        };

        /**
         * This event listener is bound for "Carousel:LOADED" event broadcast
         */
        $rootScope.$on("Carousel:LOADED", function () {
          WidgetHome.view = null;
          if (!WidgetHome.view) {
            WidgetHome.view = new Buildfire.components.carousel.view("#carousel", []);
          }
          if (WidgetHome.data.content && WidgetHome.data.content.carouselImages) {
            WidgetHome.view.loadItems(WidgetHome.data.content.carouselImages);
          } else {
            WidgetHome.view.loadItems([]);
          }
        });
        WidgetHome.showBookmarkItems = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Bookmarks',
              params: {
                controller: "WidgetBookmarkCtrl as WidgetBookmark"
              }
            });
          } else {
            WidgetHome.openLogin();
          }
        };

        WidgetHome.showItemNotes = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Notes',
              params: {
                controller: "WidgetNotesCtrl as WidgetNotes"
              }
            });
          }
          else {
            WidgetHome.openLogin();
          }
        };
        var onUpdateCallback = function (event) {
          console.log(event);
          setTimeout(function () {
            $scope.$digest();
            if (event && event.tag === TAG_NAMES.SEMINAR_INFO) {
              WidgetHome.data = event.data;
              if (!WidgetHome.data.design)
                WidgetHome.data.design = {};
              if (!WidgetHome.data.content)
                WidgetHome.data.content = {};
              if (event.data.content.sortBy && currentSortOrder != event.data.content.sortBy) {
                WidgetHome.data.content.sortBy = event.data.content.sortBy;
                WidgetHome.items = [];
                searchOptions.skip = 0;
                WidgetHome.busy = false;
                WidgetHome.loadMore();
              }
              if (!WidgetHome.data.design.itemListBgImage) {
                $rootScope.itemListbackgroundImage = "";
              } else {
                $rootScope.itemListbackgroundImage = WidgetHome.data.design.itemListBgImage;
              }
            }
            else if (event && event.tag === TAG_NAMES.SEMINAR_ITEMS) {
              WidgetHome.items = [];
              searchOptions.skip = 0;
              WidgetHome.busy = false;
              WidgetHome.loadMore();
            }

            if (!WidgetHome.data.design.itemListLayout) {
              WidgetHome.data.design.itemListLayout = LAYOUTS.itemListLayout[0].name;
            }
            if (currentListLayout != WidgetHome.data.design.itemListLayout && WidgetHome.view && WidgetHome.data.content.carouselImages) {
              WidgetHome.view._destroySlider();
              WidgetHome.view = null;
              console.log("==========1")
            }
            else {
              if (WidgetHome.view) {
                WidgetHome.view.loadItems(WidgetHome.data.content.carouselImages);
                console.log("==========2")
              }
            }
            currentListLayout = WidgetHome.data.design.itemListLayout;
            $scope.$digest();
            $rootScope.$digest();
          }, 0);
        };
        DataStore.onUpdate().then(null, null, onUpdateCallback);

        WidgetHome.loadMore = function () {
          console.log("===============In loadmore");
          if (WidgetHome.busy) return;
          WidgetHome.busy = true;
          WidgetHome.getItems();
        };

        WidgetHome.getItems = function () {
          Buildfire.spinner.show();
          var successAll = function (resultAll) {
              Buildfire.spinner.hide();
              WidgetHome.items = WidgetHome.items.length ? WidgetHome.items.concat(resultAll) : resultAll;
              searchOptions.skip = searchOptions.skip + PAGINATION.itemCount;
              if (resultAll.length == PAGINATION.itemCount) {
                WidgetHome.busy = false;
              }
              console.log("----------------------",WidgetHome.items)
              WidgetHome.setBookmarks();
            },
            errorAll = function (error) {
              Buildfire.spinner.hide();
              console.log("error", error)
            };
          console.log("***********", WidgetHome.data.content);
          if (WidgetHome.data && WidgetHome.data.content && WidgetHome.data.content.sortBy) {
            searchOptions = WidgetHome.getSearchOptions(WidgetHome.data.content.sortBy);
          }
          DataStore.search(searchOptions, TAG_NAMES.SEMINAR_ITEMS).then(successAll, errorAll);
        };

        WidgetHome.openDetails = function (itemId) {
          ViewStack.push({
            template: 'Item',
            params: {
              controller: "WidgetItemCtrl as WidgetItem",
              itemId: itemId
            }
          });

          //buildfire.messaging.sendMessageToControl({
          //  type: 'OpenItem',
          //  data: {"id": itemId}
          //});
        };

        WidgetHome.currentLoggedInUser = null;

        /**
         * Method to open buildfire auth login pop up and allow user to login using credentials.
         */
        WidgetHome.openLogin = function () {
          buildfire.auth.login({}, function () {

          });
        };

        var loginCallback = function () {
          buildfire.auth.getCurrentUser(function (err, user) {
            console.log("=========User", user);
            if (user) {
              WidgetHome.currentLoggedInUser = user;
              $scope.$apply();
              WidgetHome.getBookMarkData(true);
            }
          });
        };

        buildfire.auth.onLogin(loginCallback);

        /**
         * Check for current logged in user, if not show ogin screen
         */
        buildfire.auth.getCurrentUser(function (err, user) {
          console.log("===========LoggedInUser", user);
          if (user) {
            WidgetHome.currentLoggedInUser = user;
            $scope.$apply();
            WidgetHome.getBookMarkData();
          }
        });

        WidgetHome.addToBookmark = function (item, isBookmarked, index) {
          console.log("$$$$$$$$$$$$$$$$$", item, isBookmarked, index);
          Buildfire.spinner.show();
          if (isBookmarked && item.bookmarkId) {
            var successRemove = function (result) {
              Buildfire.spinner.hide();
              WidgetHome.items[index].isBookmarked = false;
              WidgetHome.items[index].bookmarkId = null;
              if (!$scope.$$phase)
                $scope.$digest();
              $modal.open({
                templateUrl: 'templates/Bookmark_Removed.html',
                size: 'sm'
              });
            }, errorRemove = function () {
              Buildfire.spinner.hide();
              return console.error('There was a problem removing your data');
            };
            UserData.delete(item.bookmarkId, TAG_NAMES.SEMINAR_BOOKMARKS, WidgetHome.currentLoggedInUser._id).then(successRemove, errorRemove)
          } else {
            WidgetHome.bookmarkItem = {
              data: {
                itemId: item.id
              }
            };
            var successItem = function (result) {
              Buildfire.spinner.hide();
              console.log("Inserted", result);
              WidgetHome.items[index].isBookmarked = true;
              WidgetHome.items[index].bookmarkId = result.id;
              if (!$scope.$$phase)
                $scope.$digest();
              $modal.open({
                templateUrl: 'templates/Bookmark_Confirm.html',
                size: 'sm'
              });
            }, errorItem = function () {
              Buildfire.spinner.hide();
              return console.error('There was a problem saving your data');
            };
            UserData.insert(WidgetHome.bookmarkItem.data, TAG_NAMES.SEMINAR_BOOKMARKS).then(successItem, errorItem);
          }
        };

        WidgetHome.showSearchPage = function () {
          if (WidgetHome.currentLoggedInUser) {
            ViewStack.push({
              template: 'Search',
              params: {
                controller: "WidgetSearchCtrl as WidgetSearch"
              }
            });
          } else {
            WidgetHome.openLogin();
          }
        };

        WidgetHome.showDescription = function (description) {
          return !((description == '

') || (description == '

') || (description == ''));
        };

        $rootScope.$on('NEW_ITEM_ADDED_UPDATED', function (e) {
          WidgetHome.items = [];
          searchOptions.skip = 0;
          WidgetHome.busy = false;
          WidgetHome.loadMore();
        });

        $rootScope.$on('ITEM_BOOKMARKED', function (e) {
          WidgetHome.getBookMarkData(true);
        });

        $scope.$on("$destroy", function () {
          console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed211112");
          for (var i in WidgetHome.listeners) {
            if (WidgetHome.listeners.hasOwnProperty(i)) {
              WidgetHome.listeners[i]();
            }
          }
          DataStore.clearListener();
        });

        WidgetHome.listeners['CHANGED'] = $rootScope.$on('VIEW_CHANGED', function (e, type, view) {
          if (type === 'POP') {
            console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed311113");
            DataStore.onUpdate().then(null, null, onUpdateCallback);
            WidgetHome.getBookMarkData(true);
            WidgetHome.setBookmarks();
           }
          if (type === 'POPALL') {
            console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>destroyed311113");
            DataStore.onUpdate().then(null, null, onUpdateCallback);
            WidgetHome.getBookMarkData(true);
            WidgetHome.setBookmarks();
          }
        });
      }])
})(window.angular, window.buildfire);
<|endoftext|>


<commit_before>define([
    'util/appCellUtil',
    'common/props',
    'common/spec',
    'testUtil',
    'base/js/namespace',
    'narrativeConfig',
    'narrativeMocks',
    '/test/data/testBulkImportObj',
], (Util, Props, Spec, TestUtil, Jupyter, Config, Mocks, TestBulkImportObject) => {
    'use strict';

    const testFileType = 'someFileType';
    const testAppId = 'kb_uploadmethods/import_fastq_sra_as_reads_from_staging';
    const filePathIds = ['fastq_fwd_staging_file_name', 'fastq_rev_staging_file_name', 'name'];
    const paramIds = [
        'import_type',
        'sequencing_tech',
        'single_genome',
        'interleaved',
        'read_orientation_outward',
        'insert_size_std_dev',
        'insert_size_mean',
    ];
    const outputIds = ['name'];
    // all of these tests use the 'kb_uploadmethods/import_fastq_sra_as_reads_from_staging'
    // spec as given in test/data/testBulkImportObj
    /**
     * This builds a quick and dirty test "model" around one or more instances of the same app
     * spec. It just gets used multiple times (we're testing whether the model validates, not the
     * various apps).
     * @param {Array} inputs - an object where key is the fileType, and value is an array of file names
     * @returns {Object} model - a Props object with data matching the file names and parameters
     *  from the test app spec
     */
    function buildModel(fileInputs) {
        const fileTypes = Object.keys(fileInputs);
        // set up inputs
        const params = {
                import_type: 'SRA',
                insert_size_mean: null,
                insert_size_std_dev: null,
                interleaved: 0,
                read_orientation_outward: 0,
                sequencing_tech: 'Illumina',
                single_genome: 1,
            },
            inputs = {},
            appParams = {},
            fileParamIds = {},
            otherParamIds = {},
            outputParamIds = {};
        fileTypes.forEach((fileType) => {
            const files = fileInputs[fileType];
            fileParamIds[fileType] = Object.assign([], filePathIds);
            otherParamIds[fileType] = Object.assign([], paramIds);
            outputParamIds[fileType] = Object.assign([], outputIds);
            inputs[fileType] = {
                appId: testAppId,
                files,
            };
            const filePaths = files.map((filename) => {
                return {
                    fastq_fwd_staging_file_name: filename,
                    fastq_rev_staging_file_name: filename,
                    name: filename,
                };
            });
            appParams[fileType] = {
                filePaths,
                params: Object.assign({}, params),
            };
        });
        return Props.make({
            data: {
                app: { fileParamIds, otherParamIds, outputParamIds },
                inputs,
                params: appParams,
            },
            onUpdate: () => {
                /* empty */
            },
        });
    }

    fdescribe('BulkImportCell Utility tests', () => {
        let spec;
        beforeAll(() => {
            Jupyter.narrative = {
                getAuthToken: () => 'fakeToken',
            };
            spec = Spec.make({ appSpec: TestBulkImportObject.app.specs[testAppId] });
        });

        beforeEach(() => {
            jasmine.Ajax.install();
            Mocks.mockJsonRpc1Call({
                url: Config.url('workspace'),
                body: /get_object_info_new/,
                response: [null],
            });
        });

        afterEach(() => {
            TestUtil.clearRuntime();
            jasmine.Ajax.uninstall();
        });

        describe('evaluateAppConfig tests', () => {
            // happy path tests with >= 1 file path sets
            [1, 2, 5].forEach((fileCount) => {
                it(`should return "complete" with ${fileCount} file paths in a ready state`, async () => {
                    // Array interpolation cleverness from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
                    const files = Array.from({ length: fileCount }, (v, x) => `file${x + 1}`);
                    const fileInputs = {};
                    fileInputs[testFileType] = files;
                    const model = buildModel(fileInputs);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        Array.from({ length: fileCount }, () => ({})),
                        spec
                    );
                    expect(status).toEqual('complete');
                });
            });

            // unhappy file path row tests
            [
                { label: 'empty', data: [] },
                { label: 'multiple missing', data: [{ fastq_rev_staging_file_name: 'rev1' }] },
                {
                    label: 'single missing',
                    data: [{ fastq_rev_staging_file_name: 'rev2', name: 'name2' }],
                },
                {
                    label: 'multiple null required',
                    data: [
                        {
                            fastq_fwd_staging_file_name: null,
                            fastq_rev_staging_file_name: 'rev3',
                            name: null,
                        },
                    ],
                },
                {
                    label: 'single null required',
                    data: [
                        {
                            fastq_fwd_staging_file_name: null,
                            fastq_rev_staging_file_name: 'rev4',
                            name: 'name4',
                        },
                    ],
                },
            ].forEach((testCase) => {
                it(`should return "incomplete" with ${testCase.label} filePath inputs`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = [];
                    const model = buildModel(fileInputs);
                    model.setItem(['params', testFileType, 'filePaths'], testCase.data);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        [{}],
                        spec
                    );
                    expect(status).toEqual('incomplete');
                });
            });

            [
                { label: 'empty', data: { remove: paramIds } },
                { label: 'a single missing required', data: { remove: ['import_type'] } },
                {
                    label: 'multiple missing required',
                    data: { remove: ['import_type', 'sequencing_tech'] },
                },
                { label: 'a single null required', data: { alter: { import_type: null } } },
                {
                    label: 'multiple null required',
                    data: { alter: { import_type: null, sequencing_tech: null } },
                },
                { label: 'an incorrect value type', data: { alter: { insert_size_mean: 'wat' } } },
            ].forEach((testCase) => {
                it(`should return "incomplete" with ${testCase.label} param inputs`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = ['some_file'];
                    const model = buildModel(fileInputs);
                    const defaultParams = model.getItem(['params', testFileType, 'params']);
                    let testParams = defaultParams;
                    if ('remove' in testCase.data) {
                        testCase.data.remove.forEach((key) => {
                            delete testParams[key];
                        });
                    }
                    if ('alter' in testCase.data) {
                        testParams = Object.assign(testParams, testCase.data.alter);
                    }
                    model.setItem(['params', testFileType, 'params'], testParams);
                    const filePathValues = model.getItem(['params', testFileType, 'filePaths']);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        Array.from({ length: filePathValues.length }, () => ({})),
                        spec
                    );
                    expect(status).toEqual('incomplete');
                });
            });

            const testObjName = 'some_file';
            [
                {
                    label: 'complete, with same',
                    mockResponse: [1, testObjName, 'KBaseFile.PairedEndLibrary'],
                    result: 'complete',
                },
                {
                    label: 'incomplete, with different',
                    mockResponse: [1, testObjName, 'SomeModule.SomeType'],
                    result: 'incomplete',
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.label} object type in the workspace with the same name`, async () => {
                    Mocks.mockJsonRpc1Call({
                        url: Config.url('workspace'),
                        body: /get_object_info_new/,
                        response: [testCase.mockResponse],
                    });
                    const fileInputs = {};
                    fileInputs[testFileType] = [testObjName];
                    const model = buildModel(fileInputs);
                    const outputNameOptions = {
                        shouldNotExist: true,
                        workspaceServiceUrl: Config.url('workspace'),
                        authToken: 'fakeToken',
                        workspaceId: 123,
                    };

                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        [{ name: outputNameOptions }],
                        spec
                    );
                    expect(status).toEqual(testCase.result);
                    expect(jasmine.Ajax.requests.count()).toBe(1);
                });
            });
        });

        describe('evaluateConfigReadyState tests', () => {
            let specs;
            beforeAll(() => {
                specs = {};
                specs[testAppId] = spec;
            });

            [
                {
                    label: 'complete',
                    files: ['file1', 'file2'],
                },
                {
                    label: 'incomplete',
                    files: [],
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.label} for a single file type`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = testCase.files;
                    const model = buildModel(fileInputs);
                    const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                    const expected = {};
                    expected[testFileType] = testCase.label;
                    expect(readyState).toEqual(expected);
                });
            });

            [
                {
                    fileTypeCount: 2,
                    fileCounts: [2, 2],
                    result: ['complete', 'complete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [0, 2],
                    result: ['incomplete', 'complete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [2, 0],
                    result: ['complete', 'incomplete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [0, 0],
                    result: ['incomplete', 'incomplete'],
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.result} for multiple file types`, async () => {
                    const fileInputs = {};
                    const expected = {};
                    for (let i = 0; i < testCase.fileTypeCount; i++) {
                        const fileType = `fileType${i}`;
                        const count = testCase.fileCounts[i];
                        fileInputs[fileType] = Array.from(
                            { length: count },
                            (v, x) => `file${i}_${x + 1}`
                        );
                        expected[fileType] = testCase.result[i];
                    }
                    const model = buildModel(fileInputs);

                    const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                    expect(readyState).toEqual(expected);
                });
            });

            it('should return partial incomplete with some bad matching of file types in workspace objects', async () => {
                const fileInputs = {
                    fileType1: ['file1'],
                    fileType2: ['file2'],
                };
                const model = buildModel(fileInputs);

                // mock should only activate when we're looking up file1, otherwise use the default mock
                Mocks.mockJsonRpc1Call({
                    url: Config.url('workspace'),
                    body: /^(?=.*get_object_info_new.*)(?=.*file1.*).*$/, // look for both get_object_info_new and file1 in the body of the request, in any order
                    response: [[1, 'file1', 'SomeModule.SomeType']],
                });

                const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                expect(readyState).toEqual({
                    fileType1: 'incomplete',
                    fileType2: 'complete',
                });
            });
        });

        describe('getMissingFiles tests', () => {
            const stagingUrl = Config.url('staging_api_url');

            beforeEach(() => {
                const fakeStagingResponse = ['file1', 'file2', 'file3'].map((fileName) => {
                    return {
                        name: fileName,
                        path: 'someUser' + '/' + fileName,
                        mtime: 1532738637499,
                        size: 34,
                        isFolder: false,
                    };
                });

                jasmine.Ajax.stubRequest(new RegExp(`${stagingUrl}/list/`)).andReturn({
                    status: 200,
                    statusText: 'success',
                    contentType: 'text/plain',
                    responseHeaders: '',
                    responseText: JSON.stringify(fakeStagingResponse),
                });
            });

            [
                {
                    files: ['file1', 'file2', 'file3'],
                    expected: [],
                    label: 'none missing',
                },
                {
                    files: [],
                    expected: [],
                    label: 'no files',
                },
                {
                    files: ['file1', 'file2', 'file4'],
                    expected: ['file4'],
                    label: 'missing file',
                },
            ].forEach((testCase) => {
                it(`should return an array of missing files: ${testCase.label}`, async () => {
                    const missing = await Util.getMissingFiles(testCase.files);
                    expect(missing).toEqual(testCase.expected);
                });
            });

            it('should throw an error if the staging area returns an error', async () => {
                const error = 'Some Error';
                jasmine.Ajax.stubRequest(new RegExp(`${stagingUrl}/list/`)).andReturn({
                    status: 500,
                    statusText: 'failed',
                    contentType: 'text/plain',
                    responseHeaders: '',
                    responseText: error,
                });

                await expectAsync(Util.getMissingFiles(['someFile'])).toBeRejectedWith(
                    new Error('Error while identifying missing files: ' + error)
                );
            });
        });

        const uploaders = {
                dropdown_order: [
                    { id: 'assembly', name: 'Assembly' },
                    { id: 'fastq_reads_interleaved', name: 'FASTQ Reads Interleaved' },
                    { id: 'fastq_reads_noninterleaved', name: 'FASTQ Reads NonInterleaved' },
                    { id: 'sra_reads', name: 'SRA Reads' },
                ],
            },
            ttf = {
                assembly: {},
                fastq_reads_interleaved: {},
                sra_reads: {},
                unknown_type: {},
            },
            expectedFileTypeMapping = {
                assembly: 'Assembly',
                fastq_reads_interleaved: 'FASTQ Reads Interleaved',
                fastq_reads_noninterleaved: 'FASTQ Reads NonInterleaved',
                sra_reads: 'SRA Reads',
            };

        describe('generateFileTypeMappings', () => {
            it('generates type mappings with empty input', () => {
                spyOn(Config, 'get').and.returnValue(uploaders);
                const output = Util.generateFileTypeMappings();
                expect(output).toEqual({
                    fileTypesDisplay: {},
                    fileTypeMapping: expectedFileTypeMapping,
                });
            });

            it('generates type mappings and display info with input', () => {
                spyOn(Config, 'get').and.returnValue(uploaders);
                const output = Util.generateFileTypeMappings(ttf);
                expect(output).toEqual({
                    fileTypesDisplay: {
                        assembly: { label: 'Assembly' },
                        fastq_reads_interleaved: {
                            label: 'FASTQ Reads Interleaved',
                        },
                        sra_reads: {
                            label: 'SRA Reads',
                        },
                        unknown_type: {
                            label: 'Unknown type "unknown_type"',
                        },
                    },
                    fileTypeMapping: expectedFileTypeMapping,
                });
            });
        });
    });
});
<commit_msg>remove fdescribe, add a request count check<commit_after>define([
    'util/appCellUtil',
    'common/props',
    'common/spec',
    'testUtil',
    'base/js/namespace',
    'narrativeConfig',
    'narrativeMocks',
    '/test/data/testBulkImportObj',
], (Util, Props, Spec, TestUtil, Jupyter, Config, Mocks, TestBulkImportObject) => {
    'use strict';

    const testFileType = 'someFileType';
    const testAppId = 'kb_uploadmethods/import_fastq_sra_as_reads_from_staging';
    const filePathIds = ['fastq_fwd_staging_file_name', 'fastq_rev_staging_file_name', 'name'];
    const paramIds = [
        'import_type',
        'sequencing_tech',
        'single_genome',
        'interleaved',
        'read_orientation_outward',
        'insert_size_std_dev',
        'insert_size_mean',
    ];
    const outputIds = ['name'];
    // all of these tests use the 'kb_uploadmethods/import_fastq_sra_as_reads_from_staging'
    // spec as given in test/data/testBulkImportObj
    /**
     * This builds a quick and dirty test "model" around one or more instances of the same app
     * spec. It just gets used multiple times (we're testing whether the model validates, not the
     * various apps).
     * @param {Array} inputs - an object where key is the fileType, and value is an array of file names
     * @returns {Object} model - a Props object with data matching the file names and parameters
     *  from the test app spec
     */
    function buildModel(fileInputs) {
        const fileTypes = Object.keys(fileInputs);
        // set up inputs
        const params = {
                import_type: 'SRA',
                insert_size_mean: null,
                insert_size_std_dev: null,
                interleaved: 0,
                read_orientation_outward: 0,
                sequencing_tech: 'Illumina',
                single_genome: 1,
            },
            inputs = {},
            appParams = {},
            fileParamIds = {},
            otherParamIds = {},
            outputParamIds = {};
        fileTypes.forEach((fileType) => {
            const files = fileInputs[fileType];
            fileParamIds[fileType] = Object.assign([], filePathIds);
            otherParamIds[fileType] = Object.assign([], paramIds);
            outputParamIds[fileType] = Object.assign([], outputIds);
            inputs[fileType] = {
                appId: testAppId,
                files,
            };
            const filePaths = files.map((filename) => {
                return {
                    fastq_fwd_staging_file_name: filename,
                    fastq_rev_staging_file_name: filename,
                    name: filename,
                };
            });
            appParams[fileType] = {
                filePaths,
                params: Object.assign({}, params),
            };
        });
        return Props.make({
            data: {
                app: { fileParamIds, otherParamIds, outputParamIds },
                inputs,
                params: appParams,
            },
            onUpdate: () => {
                /* empty */
            },
        });
    }

    describe('BulkImportCell Utility tests', () => {
        let spec;
        beforeAll(() => {
            Jupyter.narrative = {
                getAuthToken: () => 'fakeToken',
            };
            spec = Spec.make({ appSpec: TestBulkImportObject.app.specs[testAppId] });
        });

        beforeEach(() => {
            jasmine.Ajax.install();
            Mocks.mockJsonRpc1Call({
                url: Config.url('workspace'),
                body: /get_object_info_new/,
                response: [null],
            });
        });

        afterEach(() => {
            TestUtil.clearRuntime();
            jasmine.Ajax.uninstall();
        });

        describe('evaluateAppConfig tests', () => {
            // happy path tests with >= 1 file path sets
            [1, 2, 5].forEach((fileCount) => {
                it(`should return "complete" with ${fileCount} file paths in a ready state`, async () => {
                    // Array interpolation cleverness from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
                    const files = Array.from({ length: fileCount }, (v, x) => `file${x + 1}`);
                    const fileInputs = {};
                    fileInputs[testFileType] = files;
                    const model = buildModel(fileInputs);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        Array.from({ length: fileCount }, () => ({})),
                        spec
                    );
                    expect(status).toEqual('complete');
                });
            });

            // unhappy file path row tests
            [
                { label: 'empty', data: [] },
                { label: 'multiple missing', data: [{ fastq_rev_staging_file_name: 'rev1' }] },
                {
                    label: 'single missing',
                    data: [{ fastq_rev_staging_file_name: 'rev2', name: 'name2' }],
                },
                {
                    label: 'multiple null required',
                    data: [
                        {
                            fastq_fwd_staging_file_name: null,
                            fastq_rev_staging_file_name: 'rev3',
                            name: null,
                        },
                    ],
                },
                {
                    label: 'single null required',
                    data: [
                        {
                            fastq_fwd_staging_file_name: null,
                            fastq_rev_staging_file_name: 'rev4',
                            name: 'name4',
                        },
                    ],
                },
            ].forEach((testCase) => {
                it(`should return "incomplete" with ${testCase.label} filePath inputs`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = [];
                    const model = buildModel(fileInputs);
                    model.setItem(['params', testFileType, 'filePaths'], testCase.data);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        [{}],
                        spec
                    );
                    expect(status).toEqual('incomplete');
                });
            });

            [
                { label: 'empty', data: { remove: paramIds } },
                { label: 'a single missing required', data: { remove: ['import_type'] } },
                {
                    label: 'multiple missing required',
                    data: { remove: ['import_type', 'sequencing_tech'] },
                },
                { label: 'a single null required', data: { alter: { import_type: null } } },
                {
                    label: 'multiple null required',
                    data: { alter: { import_type: null, sequencing_tech: null } },
                },
                { label: 'an incorrect value type', data: { alter: { insert_size_mean: 'wat' } } },
            ].forEach((testCase) => {
                it(`should return "incomplete" with ${testCase.label} param inputs`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = ['some_file'];
                    const model = buildModel(fileInputs);
                    const defaultParams = model.getItem(['params', testFileType, 'params']);
                    let testParams = defaultParams;
                    if ('remove' in testCase.data) {
                        testCase.data.remove.forEach((key) => {
                            delete testParams[key];
                        });
                    }
                    if ('alter' in testCase.data) {
                        testParams = Object.assign(testParams, testCase.data.alter);
                    }
                    model.setItem(['params', testFileType, 'params'], testParams);
                    const filePathValues = model.getItem(['params', testFileType, 'filePaths']);
                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        Array.from({ length: filePathValues.length }, () => ({})),
                        spec
                    );
                    expect(status).toEqual('incomplete');
                });
            });

            const testObjName = 'some_file';
            [
                {
                    label: 'complete, with same',
                    mockResponse: [1, testObjName, 'KBaseFile.PairedEndLibrary'],
                    result: 'complete',
                },
                {
                    label: 'incomplete, with different',
                    mockResponse: [1, testObjName, 'SomeModule.SomeType'],
                    result: 'incomplete',
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.label} object type in the workspace with the same name`, async () => {
                    Mocks.mockJsonRpc1Call({
                        url: Config.url('workspace'),
                        body: /get_object_info_new/,
                        response: [testCase.mockResponse],
                    });
                    const fileInputs = {};
                    fileInputs[testFileType] = [testObjName];
                    const model = buildModel(fileInputs);
                    const outputNameOptions = {
                        shouldNotExist: true,
                        workspaceServiceUrl: Config.url('workspace'),
                        authToken: 'fakeToken',
                        workspaceId: 123,
                    };

                    const status = await Util.evaluateAppConfig(
                        paramIds,
                        model.getItem(['params', testFileType, 'params']),
                        {},
                        filePathIds,
                        model.getItem(['params', testFileType, 'filePaths']),
                        [{ name: outputNameOptions }],
                        spec
                    );
                    expect(status).toEqual(testCase.result);
                    expect(jasmine.Ajax.requests.count()).toBe(1);
                });
            });
        });

        describe('evaluateConfigReadyState tests', () => {
            let specs;
            beforeAll(() => {
                specs = {};
                specs[testAppId] = spec;
            });

            [
                {
                    label: 'complete',
                    files: ['file1', 'file2'],
                },
                {
                    label: 'incomplete',
                    files: [],
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.label} for a single file type`, async () => {
                    const fileInputs = {};
                    fileInputs[testFileType] = testCase.files;
                    const model = buildModel(fileInputs);
                    const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                    const expected = {};
                    expected[testFileType] = testCase.label;
                    expect(readyState).toEqual(expected);
                });
            });

            [
                {
                    fileTypeCount: 2,
                    fileCounts: [2, 2],
                    result: ['complete', 'complete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [0, 2],
                    result: ['incomplete', 'complete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [2, 0],
                    result: ['complete', 'incomplete'],
                },
                {
                    fileTypeCount: 2,
                    fileCounts: [0, 0],
                    result: ['incomplete', 'incomplete'],
                },
            ].forEach((testCase) => {
                it(`should return ${testCase.result} for multiple file types`, async () => {
                    const fileInputs = {};
                    const expected = {};
                    for (let i = 0; i < testCase.fileTypeCount; i++) {
                        const fileType = `fileType${i}`;
                        const count = testCase.fileCounts[i];
                        fileInputs[fileType] = Array.from(
                            { length: count },
                            (v, x) => `file${i}_${x + 1}`
                        );
                        expected[fileType] = testCase.result[i];
                    }
                    const model = buildModel(fileInputs);

                    const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                    expect(readyState).toEqual(expected);
                });
            });

            it('should return partial incomplete with some bad matching of file types in workspace objects', async () => {
                const fileInputs = {
                    fileType1: ['file1'],
                    fileType2: ['file2'],
                };
                const model = buildModel(fileInputs);

                // mock should only activate when we're looking up file1, otherwise use the default mock
                Mocks.mockJsonRpc1Call({
                    url: Config.url('workspace'),
                    body: /^(?=.*get_object_info_new.*)(?=.*file1.*).*$/, // look for both get_object_info_new and file1 in the body of the request, in any order
                    response: [[1, 'file1', 'SomeModule.SomeType']],
                });

                const readyState = await Util.evaluateConfigReadyState(model, specs, new Set());
                expect(readyState).toEqual({
                    fileType1: 'incomplete',
                    fileType2: 'complete',
                });
                expect(jasmine.Ajax.requests.count()).toBe(2);
            });
        });

        describe('getMissingFiles tests', () => {
            const stagingUrl = Config.url('staging_api_url');

            beforeEach(() => {
                const fakeStagingResponse = ['file1', 'file2', 'file3'].map((fileName) => {
                    return {
                        name: fileName,
                        path: 'someUser' + '/' + fileName,
                        mtime: 1532738637499,
                        size: 34,
                        isFolder: false,
                    };
                });

                jasmine.Ajax.stubRequest(new RegExp(`${stagingUrl}/list/`)).andReturn({
                    status: 200,
                    statusText: 'success',
                    contentType: 'text/plain',
                    responseHeaders: '',
                    responseText: JSON.stringify(fakeStagingResponse),
                });
            });

            [
                {
                    files: ['file1', 'file2', 'file3'],
                    expected: [],
                    label: 'none missing',
                },
                {
                    files: [],
                    expected: [],
                    label: 'no files',
                },
                {
                    files: ['file1', 'file2', 'file4'],
                    expected: ['file4'],
                    label: 'missing file',
                },
            ].forEach((testCase) => {
                it(`should return an array of missing files: ${testCase.label}`, async () => {
                    const missing = await Util.getMissingFiles(testCase.files);
                    expect(missing).toEqual(testCase.expected);
                });
            });

            it('should throw an error if the staging area returns an error', async () => {
                const error = 'Some Error';
                jasmine.Ajax.stubRequest(new RegExp(`${stagingUrl}/list/`)).andReturn({
                    status: 500,
                    statusText: 'failed',
                    contentType: 'text/plain',
                    responseHeaders: '',
                    responseText: error,
                });

                await expectAsync(Util.getMissingFiles(['someFile'])).toBeRejectedWith(
                    new Error('Error while identifying missing files: ' + error)
                );
            });
        });

        const uploaders = {
                dropdown_order: [
                    { id: 'assembly', name: 'Assembly' },
                    { id: 'fastq_reads_interleaved', name: 'FASTQ Reads Interleaved' },
                    { id: 'fastq_reads_noninterleaved', name: 'FASTQ Reads NonInterleaved' },
                    { id: 'sra_reads', name: 'SRA Reads' },
                ],
            },
            ttf = {
                assembly: {},
                fastq_reads_interleaved: {},
                sra_reads: {},
                unknown_type: {},
            },
            expectedFileTypeMapping = {
                assembly: 'Assembly',
                fastq_reads_interleaved: 'FASTQ Reads Interleaved',
                fastq_reads_noninterleaved: 'FASTQ Reads NonInterleaved',
                sra_reads: 'SRA Reads',
            };

        describe('generateFileTypeMappings', () => {
            it('generates type mappings with empty input', () => {
                spyOn(Config, 'get').and.returnValue(uploaders);
                const output = Util.generateFileTypeMappings();
                expect(output).toEqual({
                    fileTypesDisplay: {},
                    fileTypeMapping: expectedFileTypeMapping,
                });
            });

            it('generates type mappings and display info with input', () => {
                spyOn(Config, 'get').and.returnValue(uploaders);
                const output = Util.generateFileTypeMappings(ttf);
                expect(output).toEqual({
                    fileTypesDisplay: {
                        assembly: { label: 'Assembly' },
                        fastq_reads_interleaved: {
                            label: 'FASTQ Reads Interleaved',
                        },
                        sra_reads: {
                            label: 'SRA Reads',
                        },
                        unknown_type: {
                            label: 'Unknown type "unknown_type"',
                        },
                    },
                    fileTypeMapping: expectedFileTypeMapping,
                });
            });
        });
    });
});
<|endoftext|>