Re: TopicCollection.js

From disqus.com, 2 Months ago, written in JavaScript, viewed 3 times. This paste is a reply to Re:WindowBus.js from disqus.com - view diff
URL https://pastebin.freepbx.org/view/66052c53 Embed
Download Paste or View Raw
  1. define('home/collections/TopicCollection',[
  2.     'underscore',
  3.     'backbone',
  4.  
  5.     'home/models/Topic',
  6.     'core/UniqueModel',
  7.  
  8.     'core/api',
  9.     'core/strings',
  10. ], function (
  11.     _,
  12.     Backbone,
  13.  
  14.     Topic,
  15.     UniqueModel,
  16.  
  17.     api,
  18.     strings
  19. ) {
  20.     'use strict';
  21.  
  22.     var gettext = strings.get;
  23.  
  24.     var TopicCollection = Backbone.Collection.extend({
  25.         model: UniqueModel.boundModel(Topic),
  26.  
  27.         initialize: function (_models, options) {
  28.             if (options && options.thread)
  29.                 this.thread = options.thread;
  30.         },
  31.  
  32.         /**
  33.          * Returns the intersection of topics in this collection and categories
  34.          * on the channel for this collection's thread, case insensitive.
  35.          * Technically this can return more than 1, ex: during editing a user
  36.          * may input more than 1 category as a topic. Validation should prevent
  37.          * a thread from being saved with more or less than 1 returned category.
  38.          */
  39.         getCategoryTopics: function () {
  40.             var channel = this.thread.forum.channel;
  41.             var categories = channel.getCategories();
  42.  
  43.             if (!categories)
  44.                 return [];
  45.  
  46.             categories = categories && _.keys(categories);
  47.             return this.filter(function (topic) {
  48.                 var lowerDisplayName = topic.get('displayName').toLowerCase();
  49.  
  50.                 return _.find(categories, function (category) {
  51.                     return Topic.cleanTopicName(category).toLowerCase() === lowerDisplayName;
  52.                 });
  53.             });
  54.         },
  55.  
  56.         isValid: function () {
  57.             var error = this.validationError = this.validate() || null;
  58.             if (!error)
  59.                 return true;
  60.  
  61.             this.trigger('invalid', this, error, { validationError: error });
  62.             return false;
  63.         },
  64.  
  65.         validate: function () {
  66.             // First check for topics invalid on their own
  67.             var invalidModel = this.find(function (topic) {
  68.                 return !topic.isValid();
  69.             });
  70.  
  71.             if (invalidModel)
  72.                 return invalidModel.validationError;
  73.  
  74.             // No restrictions on topic collections not bound to a thread
  75.             if (!this.thread)
  76.                 return;
  77.  
  78.             // Check max length. Only check non-hidden topics (those editable by and
  79.             // visible to the user).
  80.             var countsByHidden = this.countBy(function (topic) {
  81.                 return topic.get('hidden') ? 'hidden' : 'visible';
  82.             });
  83.             if (countsByHidden.visible > TopicCollection.MAX_LENGTH) {
  84.                 return {
  85.                     attrName: 'topics',
  86.                     message: strings.interpolate(gettext('You may not have more than %(num)s topics'), { num: TopicCollection.MAX_LENGTH }),
  87.                 };
  88.             }
  89.  
  90.             var channel = this.thread.forum.channel;
  91.             var categories = channel && channel.getCategories();
  92.             if (categories) {
  93.                 var chosenCategories = this.getCategoryTopics();
  94.  
  95.                 if (chosenCategories.length < 1) {
  96.                     return {
  97.                         attrName: 'category',
  98.                         message: gettext('You must choose a category'),
  99.                     };
  100.                 }
  101.  
  102.                 var collidesWithCategory = _.any(
  103.                     chosenCategories,
  104.                     function (category) { return !category.get('hidden'); }
  105.                 );
  106.                 if (collidesWithCategory) {
  107.                     return {
  108.                         attrName: 'topics',
  109.                         message: gettext('You may not enter a category as a topic'),
  110.                     };
  111.                 }
  112.             }
  113.         },
  114.  
  115.         _syncTopicsOnThread: function (topics, method) {
  116.             var options = {
  117.                 url: this.urls[method],
  118.                 type: 'POST',
  119.                 processData: true,
  120.                 emulateHTTP: true,
  121.                 data: {
  122.                     thread: this.thread.id,
  123.                     topics: _.map(topics, function (item) {
  124.                         return item.get('displayName');
  125.                     }),
  126.                 },
  127.             };
  128.  
  129.             return Backbone.sync(method, this, options);
  130.         },
  131.  
  132.         urls: {
  133.             'addTopicsToThread': api.getURL('timelines/curation/addTopicsToThread'),
  134.             'removeTopicsFromThread': api.getURL('timelines/curation/removeTopicsFromThread'),
  135.         },
  136.  
  137.         save: function () {
  138.             if (!this.thread || !this.isValid())
  139.                 return;
  140.  
  141.             var syncedTopics = this.thread.topics.models;
  142.             var addedTopics = _.difference(this.models, syncedTopics);
  143.             var removedTopics = _.difference(syncedTopics, this.models);
  144.             var thread = this.thread;
  145.  
  146.             if (addedTopics.length) {
  147.                 this._syncTopicsOnThread(addedTopics, 'addTopicsToThread').then(function (response) {
  148.                     if (response.response) {
  149.                         // Endpoint returned topic details: consistent casing for display names and
  150.                         // identifiers. Add these full topics to the thread's topic collection.
  151.                         thread.topics.add(_.map(response.response, function (attrs) {
  152.                             return new UniqueModel(Topic, attrs);
  153.                         }));
  154.                     }
  155.                 });
  156.             }
  157.  
  158.             if (removedTopics.length) {
  159.                 this._syncTopicsOnThread(removedTopics, 'removeTopicsFromThread').then(function () {
  160.                     thread.topics.remove(removedTopics);
  161.                 });
  162.             }
  163.         },
  164.  
  165.         parse: function (response) {
  166.             return response.response;
  167.         },
  168.     }, {
  169.         MAX_LENGTH: 5,
  170.     });
  171.  
  172.     return TopicCollection;
  173. });
  174.  
  175. // https://c.disquscdn.com/next/9768c46/home/js/collections/TopicCollection.js

Reply to "Re: TopicCollection.js"

Here you can reply to the paste above