Source: src/js/views/portals/PortalUsagesView.js

define(["jquery",
  "underscore",
  "backbone",
  "collections/SolrResults",
  "collections/Filters",
  "collections/bookkeeper/Usages",
  "views/portals/PortalListView",
  "text!templates/portals/portalList.html"],
  function($, _, Backbone, SearchResults, Filters, Usages, PortalListView, Template){

    /**
    * @class PortalUsagesView
    * @classdesc A view that shows a list of Portal Usages
    * @classcategory Views/Portals
    * @extends PortalListView
    * @since 2.14.0
    * @constructor
    */
    return PortalListView.extend(
      /** @lends PortalUsagesView.prototype */{

      /**
      * A reference to the Usages collection that is rendered in this view
      * @type {Usages}
      */
      usagesCollection: null,

      /**
      * Renders this view
      */
      render: function(){

        try{

          //If the "my portals" feature is disabled, exit now
          if(MetacatUI.appModel.get("showMyPortals") === false){
            return;
          }

          //Insert the template
          this.$el.html(this.template());

          if( !this.usagesCollection ){
            this.usagesCollection = new Usages();
          }

          //When in DataONE Plus Preview mode, search for portals in Solr first,
          // then create Usage models for each portal in Solr.
          if( MetacatUI.appModel.get("dataonePlusPreviewMode") ){

            this.listenTo(this.searchResults, "sync", function(){

              //Create a Usage for each portal found in Solr
              this.searchResults.each(function(searchResult){
                this.usagesCollection.add({
                  instanceId: searchResult.get("seriesId"),
                  status: "active",
                  quantity: 1,
                  nodeId: searchResult.get("datasource")
                });
              }, this);

              //Merge the Usages and Search Results
              this.mergeSearchResults();

              //Update the view with info about the corresponding Usage model
              this.showUsageInfo();
            });

            if( MetacatUI.appModel.get("dataonePlusPreviewPortals").length ){

              this.altReposChecked = 0;
              this.altReposToCheck = [];
              this.additionalPortalsToDisplay = [];

              _.each( MetacatUI.appModel.get("alternateRepositories"), function(altRepo){

                var portalsInThisRepo = _.where(MetacatUI.appModel.get("dataonePlusPreviewPortals"),
                                          { datasource: altRepo.identifier });

                if( portalsInThisRepo.length ){

                  var searchResults = new SearchResults();
                  this.listenToOnce(searchResults, "reset", function(){

                    if( searchResults.length ){
                      this.additionalPortalsToDisplay = this.additionalPortalsToDisplay.concat( searchResults.models );
                    }

                    if(typeof this.altReposChecked == "number" ){
                      this.altReposChecked++;
                      if( this.altReposChecked == this.altReposToCheck ){
                        //Call the PortalListView render function
                        PortalListView.prototype.render.call(this);
                      }
                    }

                    //Create a Usage for each portal found in Solr
                    searchResults.each(function(searchResult){
                      this.usagesCollection.add({
                        instanceId: searchResult.get("seriesId"),
                        status: "active",
                        quantity: 1,
                        nodeId: searchResult.get("datasource")
                      });
                    }, this);

                    //Merge the Usages and Search Results
                    this.mergeSearchResults(searchResults);

                    //Update the view with info about the corresponding Usage model
                    this.showUsageInfo();

                  });

                  //Create a Filters() collection
                  var portalFilters = new Filters();
                  portalFilters.mustMatchIds = true;
                  portalFilters.addWritePermissionFilter();
                  portalFilters.add({
                    fields: ["obsoletedBy"],
                    values: ["*"],
                    matchSubstring: false,
                    exclude: true
                  });
                  portalFilters.add({
                    fields: ["datasource"],
                    values: [altRepo.identifier],
                    matchSubstring: false,
                    exclude: false
                  });
                  var portalIds = _.pluck(portalsInThisRepo, "seriesId");
                  portalFilters.add({
                    fields: ["seriesId"],
                    values: portalIds,
                    operator: "OR",
                    matchSubstring: false
                  });

                  searchResults.rows = portalIds.length;
                  searchResults.fields = this.searchFields;

                  searchResults.queryServiceUrl = altRepo.queryServiceUrl;

                  searchResults.setQuery( portalFilters.getQuery() );

                  this.altReposToCheck++;

                  //Get the first page of results
                  searchResults.toPage(0);
                }

              }, this);


              return;

            }

            //Call the PortalListView render function
            PortalListView.prototype.render.call(this);

            //Don't do anything else in this render function
            return;
          }

          //When the collection has been fetched, redner the Usage list
          this.listenToOnce(this.usagesCollection, "sync", this.getSearchResultsForUsages);

          //Listen to the collection for errors
          this.listenToOnce(this.usagesCollection, "error", this.showError);

          //When the SearchResults are retrieved, merge them with the Usages collection
          this.listenToOnce(this.searchResults, "sync", function(){
            this.mergeSearchResults();

            //Update the view with info about the corresponding Usage model
            this.showUsageInfo();
          });

          //Fetch the collection
          this.usagesCollection.fetch({
            quotaType: "portal",
            subject: MetacatUI.appUserModel.get("username")
          });

        }
        catch(e){
          console.error("Failed to render the PortalUsagesView: ", e);
        }

      },

      /**
      * Using the Usages collection, this function creates Filters that search for
      * the portal objects for those Usages
      * @param {Usages} usages The Usages collection to get search results for
      */
      getSearchResultsForUsages: function(usages){

        try{

          //Set the number of portals to the number of usages found
          this.numPortals = this.usagesCollection.length;

          var portalIds = this.usagesCollection.pluck("instanceId");

          //If there are no given filters, create a Filter for the seriesId of each portal Usage
          if( !this.filters && portalIds.length ){
            this.filters = new Filters();

            this.filters.mustMatchIds = true;
            this.filters.add({
              fields: ["seriesId"],
              values: portalIds,
              operator: "OR",
              matchSubstring: false,
              exclude: false
            });

            //Only get Portals that the user is an owner of
            this.filters.addWritePermissionFilter();
          }
          //If the filters set on this view is an array of JSON, add it to a Filters collection
          else if( this.filters.length && !Filters.prototype.isPrototypeOf(this.filters) ){
            //Create search filters for finding the portals
            var filters = new Filters();

            filters.add( this.filters );

            this.filters = filters;
          }
          else{
            this.filters = new Filters();
          }

          this.getSearchResults();

        }
        catch(e){
          this.showError();
          console.error("Failed to create search results for the portal list: ", e);
        }

      },

      /**
      * Merges the SearchResults collection with the Usages collection
      */
      mergeSearchResults: function(searchResults){

        if(typeof searchResults == "undefined"){
          var searchResults = this.searchResults;
        }

        this.usagesCollection.mergeCollections(searchResults);

        //If in DataONE Plus Preview mode, total the portal count from Solr and use that as the portal totalUsage
        if( MetacatUI.appModel.get("dataonePlusPreviewMode") ){

          var portalQuotas = MetacatUI.appUserModel.getQuotas("portal");

          if( portalQuotas.length ){
            portalQuotas[0].set("totalUsage", this.usagesCollection.length);
          }

        }
      },

      /**
      * Shows the Usage info for each Portal in this view
      */
      showUsageInfo: function(){

        this.usagesCollection.each(function(usage){

          //Find the list item HTML element for this Usage
          var listItem = this.$("[data-seriesId='" + usage.get("instanceId") + "']");

          //If a list item is found, update it
          if( listItem.length ){

            //Disable the Edit button if the Usage status is "inactive"
            if( usage.get("status") == "inactive" ){
              listItem.find(".edit.btn")
                      .attr("disabled", "disabled")
                      .popover({
                        trigger: "hover focus click",
                        placement: "top",
                        delay: {
                          show: 800
                        },
                        html: true,
                        content: "To edit this " + MetacatUI.appModel.get("portalTermSingular") + ", contact us at " +
                                 "<a href='mailto:" + MetacatUI.appModel.get("emailContact") + "'>" +
                                 MetacatUI.appModel.get("emailContact") + "</a>" +
                                 " to activate it. It may be deactivated because your " +
                                  MetacatUI.appModel.get("dataonePlusName") + " membership has ended."
                      });
            }

          }

        }, this);

        //Add a "Create" button to create a new portal, since we know the total Usage and
        // remaining Quota now.
        this.renderCreateButton();

      }

    });
});