{"version":3,"file":"6331de91c665c7298d2b94d7.js?3.6.14.7428b935c.1727745705662","mappings":"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","sources":["webpack://mono-repo/./packages/core-category/src/models/category.js","webpack://mono-repo/./build-targets/portal/packages/core-category/src/models/category.js"],"sourcesContent":["/**\n * @class\n * @extends Netx.Model\n */\nimport Base from '@netx/core/lib/netx-model';\nimport AssetSearhRulesCollection from '@netx/core-search/collections/searchRules_assets';\nimport AssetSetModel from '@netx/core-asset/models/assetSet';\nimport CategoryDetailsData from './categoryDetailsData';\nimport CategoryTreeNodesCollection from '../collections/categoryTreeNodes';\nimport AttributeProfile from '@netx/core-asset/models/attributeProfile';\nimport AttributeProfiles from '@netx/core-asset/collections/attributeProfiles';\n\nimport AssetModel from '@netx/core-asset/models/asset';\n\nimport {types as assetSetTypes} from '@netx/core-asset/properties/assetSets';\nimport customConfig from '../config';\n\nexport default class Category extends Base {\n\t/**\n\t * @type {Netx.Rpc}\n\t * @private\n\t */\n\tget rpc() {\n\t\treturn true;\n\t}\n\n\t/** @type {string} */\n\tget idAttribute() {\n\t\treturn 'categoryid';\n\t}\n\n\t/** @type {boolean} */\n\tget xhrTrackProgress() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @property {object} defaults - Default attributes\n\t * @default\n\t * @property {number} defaults.assetId - Primary asset for category (id)\n\t * @property {string} defaults.assetLabel - Primary asset for category (label)\n\t * @property {string} defaults.byteCount - Size of all assets in category\n\t * @property {array} defaults.categoryAttributes - Attributes for category (an array of ids)\n\t * @property {number} defaults.categoryid - Category id (Never set the id in defaults)\n\t * @property {array} defaults.children - Child categories (an array of ids)\n\t * @property {string} defaults.contents - ??? Generally is filled with thie string \"categories\"\n\t * @property {string} defaults.creationDate - Date created\n\t * @property {string} defaults.description - Description\n\t * @property {boolean} defaults.facet - Determines whether a category should be used as a facet\n\t * @property {string} defaults.file - Primary file path for category\n\t * @property {number} defaults.fileCount \t\t\t- Number of assets in category\n\t * @property {boolean} defaults.hasContents - Whether or not the category has any assets\n\t * @property {string} defaults.moduserlabel - Last user to modify category\n\t * @property {string} defaults.name - Category name\n\t * @property {number} defaults.orderby - Place in order\n\t * @property {string} defaults.parentCategoryName - Parent category name\n\t * @property {number} defaults.parentid - Parent id\n\t * @property {string} defaults.path - Path to category\n\t * @property {array} defaults.permissionMatrix - Permission matrix ['read', 'download', 'add', 'modify', 'delete', 'all'] (represented by 1s and 0s)\n\t * @property {number} defaults.repositorydirectory - Repository directory (eg \"cat1/cat2/cat3\")\n\t * @property {number} defaults.subCategoryCount - Numbers of categories within parent category\n\t * @property {number} defaults.type - ??? Generally is filled wit the number 1\n\t * @property {number} defaults.userId - Id of user who created category\n\t * @property {number} defaults.visible - Whether or not the category iss visible (a boolean represented by a number)\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tassetId: 0,\n\t\t\tassetLabel: '',\n\t\t\tbyteCount: '',\n\t\t\tcategoryAttributes: [],\n\t\t\t// categoryid: 0,\n\t\t\tchildren: [],\n\t\t\tcontents: '',\n\t\t\tcreationDate: '',\n\t\t\tdescription: '',\n\t\t\tfacet: false,\n\t\t\tfile: '',\n\t\t\tfileCount: 0,\n\t\t\thasContents: false,\n\t\t\tmoduserlabel: '',\n\t\t\tname: '',\n\t\t\torderby: 0,\n\t\t\tparentCategoryName: '',\n\t\t\tparentid: 1,\n\t\t\tpath: '',\n\t\t\tpermissionMatrix: [],\n\t\t\trepositorydirectory: '/',\n\t\t\tsubCategoryCount: 0,\n\t\t\ttype: 0,\n\t\t\tuserId: 0,\n\t\t\tvisible: 1,\n\n\t\t\t// Client attributes\n\t\t\topen: false,\n\t\t\tbreadcrumb: [],\n\t\t\t// tree: new Netx.Collections.CategoryTreeNodes([]),\n\t\t\t// childCategories: new Netx.Collections.CategoryTreeNodes([])\n\t\t};\n\t}\n\n\t// Attributes that must be removed before sending to server\n\tget clientAttrs() {\n\t\treturn [\n\t\t\t'breadcrumb',\n\t\t\t'byteCount',\n\t\t\t'childCategories',\n\t\t\t'fileCount',\n\t\t\t'open',\n\t\t\t'subCategoryCount',\n\t\t\t'tree',\n\t\t\t'collection',\n\t\t];\n\t}\n\n\t/**\n\t * @property {object} methods - Methods for this model\n\t * @property {method} methods.create - Create category\n\t * @property {method} methods.read - Fetch category\n\t * @property {method} methods.remove - Destroy category\n\t * @property {method} methods.update - Update category\n\t *\n\t * @property {method} methods._addToCategory - Add assets to category\n\t * @property {method} methods.fetchChildren - Fetch category children\n\t * @property {method} methods.getCategoryBreadcrumbs - Fetch category breadcrumbs\n\t * @property {method} methods.getCategoryByPath - Fetch category by path string\n\t * @property {method} methods.getCategoryData - Fetch category\n\t * @property {method} methods.getCategoryDetailsData - Fetch category details data\n\t * @property {method} methods._moveToCategory - Move assets to category\n\t * @property {method} methods.setCategoryObject - Update category\n\t */\n\tget methods() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tcreate: function (opts) {\n\t\t\t\t// The server really wants this id to be passed at creation...\n\t\t\t\tthis.set('categoryid', 0, {silent: true});\n\t\t\t\treturn this.setCategoryObject(opts).then(function (id) {\n\t\t\t\t\treturn this.set(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcategoryid: id,\n\t\t\t\t\t\t},\n\t\t\t\t\t\topts,\n\t\t\t\t\t).fetch(opts);\n\t\t\t\t});\n\t\t\t},\n\t\t\t/**\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tread: function (opts) {\n\t\t\t\tvar d = new $.Deferred();\n\n\t\t\t\tthis.getCategoryData(\n\t\t\t\t\t_.extend({duplicateQueryPolicy: 'abort'}, opts),\n\t\t\t\t).then(function (category) {\n\t\t\t\t\t// TODO: See https://jira.netx.net/browse/DAM-9247\n\t\t\t\t\t// The server returns an empty category with the id of 0 when one is not found\n\t\t\t\t\tif (category.categoryid === 0) {\n\t\t\t\t\t\treturn d.reject(new Error(i18n.t('i18n.categoryNotFound')));\n\t\t\t\t\t}\n\t\t\t\t\tif (!opts.silent) {\n\t\t\t\t\t\t// Open\n\t\t\t\t\t\tthis.set(\n\t\t\t\t\t\t\t'open',\n\t\t\t\t\t\t\tthis.get('open') && this.get('children').length > 0,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\td.resolveWith(this, [category]);\n\t\t\t\t}, d.reject);\n\n\t\t\t\treturn d.promise();\n\t\t\t},\n\t\t\t/**\n\t\t\t * Destroy category\n\t\t\t * @method\n\t\t\t */\n\t\t\tremove: ['deleteCategory', 'categoryid'],\n\t\t\t/**\n\t\t\t * Update category\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tupdate: function (opts) {\n\t\t\t\treturn this.setCategoryObject(opts).then(() => {\n\t\t\t\t\t// Need the DAM to send full beans blah blah blah\n\t\t\t\t\treturn this.fetch(opts);\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add assets to category\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\t_addToCategory: function (opts) {\n\t\t\t\treturn ['setAssetCategoryLinks', this.assetsToTransfer, this.id, true];\n\t\t\t},\n\t\t\t/**\n\t\t\t * Fetch category children\n\t\t\t * @method\n\t\t\t */\n\t\t\tfetchChildren: ['getCategoryTree', 'id'],\n\t\t\t/**\n\t\t\t * Fetch category breadcrumbs\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetCategoryBreadcrumbs: function (opts) {\n\t\t\t\tvar cid = this.id;\n\t\t\t\treturn ['getCategoryBreadcrumbs', cid > 1 ? cid : 0];\n\t\t\t},\n\t\t\t/**\n\t\t\t * Fetch category by path string\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetCategoryByPath: function (opts) {\n\t\t\t\tvar path = this.get('repositorydirectory').split('/');\n\t\t\t\treturn ['getCategoryByPath', path];\n\t\t\t},\n\t\t\t/**\n\t\t\t * Fetch category\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetCategoryData: function (opts) {\n\t\t\t\tvar catId = this.id;\n\t\t\t\tif (catId == null) {\n\t\t\t\t\treturn new $.Deferred().reject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t'Skipping call to \"getCategoryData\". Category ID is null or undefined:',\n\t\t\t\t\t\t\tcatId,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn ['getCategoryData', catId];\n\t\t\t},\n\t\t\t/**\n\t\t\t * Fetches additional details about a category\n\t\t\t * @method\n\t\t\t */\n\t\t\tgetCategoryDetailsData: ['getCategoryDetailsData', 'categoryid'],\n\t\t\t/**\n\t\t\t * Move assets to category\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\t_moveToCategory: function (opts) {\n\t\t\t\treturn ['setAssetCategoryLinks', this.assetsToTransfer, this.id, false];\n\t\t\t},\n\t\t\t/**\n\t\t\t * Create category\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tsetCategoryObject: function (opts) {\n\t\t\t\treturn ['setCategoryObject', this.self()];\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * @method\n\t * @param {object} data Data to parse\n\t * @param {object} opts Options\n\t */\n\tparseAndSave(data, opts) {\n\t\t// Use model's attribute keys to pull needed data out of `data` object\n\t\tconst catData = _.pick.apply(\n\t\t\t_,\n\t\t\t[data].concat(Object.keys(this.attributes)),\n\t\t);\n\n\t\tconst {attributeProfileId} = data;\n\n\t\t// If `attributeProfile` is null, then the user is removing the\n\t\t// attribute profile from the folder\n\t\tif (attributeProfileId === '') {\n\t\t\tthis.selectedAttributeProfile = new AttributeProfile({profileId: null});\n\t\t} else {\n\t\t\tthis.selectedAttributeProfile = new AttributeProfile({\n\t\t\t\tprofileId: attributeProfileId,\n\t\t\t});\n\t\t}\n\n\t\treturn this.save(catData, {wait: true, ...opts}).then(() => {\n\t\t\t// If attributeProfileId is undefined, we probably got here from creating\n\t\t\t// a folder where you cannot - currently - choose an attribute profile\n\t\t\tif (attributeProfileId === undefined) return;\n\n\t\t\t// If the attribute profile id is null, that means the user\n\t\t\t// removed the attribute profile from the folder\n\t\t\tif (this.selectedAttributeProfile.get('profileId') === null) {\n\t\t\t\treturn this.selectedAttributeProfile.removeAttributeProfileFromFolder(\n\t\t\t\t\tthis.id,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\treturn this.selectedAttributeProfile.setAttributeProfileForFolder(\n\t\t\t\t\tthis.id,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * @property {object} parsers - Parsers for this model\n\t * @property {method} parsers.getCategoryBreadcrumbs - Parse fetch of category breadcrumbs\n\t * @property {method} parsers.getCategoryByPath - Parse fetch of category by path\n\t * @property {method} parsers.getCategoryDetailsData - Parse fetch of category details data\n\t */\n\tget parsers() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * Fetched category breadcrumbs\n\t\t\t * @method\n\t\t\t * @param {array} data Label value objects\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetCategoryBreadcrumbs: function (data, opts) {\n\t\t\t\tthis.set('breadcrumb', _.toArray(data).reverse(), opts);\n\t\t\t},\n\t\t\t/**\n\t\t\t * Fetched category by path\n\t\t\t * @method\n\t\t\t * @param {number} id Category id\n\t\t\t * @param {object} opts Request options\n\t\t\t * @fires module:category#category:current:update\n\t\t\t * @todo Why do it with a dispatcher in the parser? Whatever called this can do that...\n\t\t\t */\n\t\t\tgetCategoryByPath: function (id, opts) {\n\t\t\t\tdispatcher.trigger('category:current:update', {categoryid: id});\n\t\t\t\t// TODO does getCategoryPath belong on the collection?\n\t\t\t\t// This parser wherever it winds up living needs to call this.fetch()\n\t\t\t\t// and add the result to the categories collection\n\t\t\t},\n\t\t\t/**\n\t\t\t * Sets additional attributes about the category on the model\n\t\t\t * @method\n\t\t\t * @param {object} data Category details data\n\t\t\t * @param {object} opts Request options\n\t\t\t * @example {\n\t\t\t * \"categoryId\": 3,\n\t\t\t * \"fileCount\": 0,\n\t\t\t * \"subCategoryCount\": 0,\n\t\t\t * \"byteCount\":\"0.0 bytes\"\n\t\t\t * }\n\t\t\t */\n\t\t\tgetCategoryDetailsData: function (data, opts) {\n\t\t\t\t// This call returns 'categoryId' instead of 'categoryid'.\n\t\t\t\t// Anyway, we know our id. This call should not be allowed to change it.\n\t\t\t\tthis.set(_.omit(data, 'categoryId', 'categoryid'), opts);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {object} attrs Category attributes\n\t * @param {object} opts Category options\n\t */\n\tconstructor(attrs, opts = {}) {\n\t\t// This is related to a circular reference somewhere\n\t\t// Anytime you find that a require at the top results in an empty object - this is why\n\t\t// https://stackoverflow.com/questions/37127083/can-two-files-have-each-other-as-dependencies-in-javascript-when-using-webpack\n\t\t// AssetModel = require('@netx/core-asset/models/asset').default;\n\n\t\tsuper(attrs, opts);\n\n\t\t// Debounce these methods\n\t\tthis.assetsAddedToCategory = _.debounce(this.assetsAddedToCategory, 50);\n\t\tthis.childAdded = _.debounce(this.childAdded, 100);\n\t\tthis.childRemoved = _.debounce(this.childRemoved, 100);\n\t\tthis.childrenChanged = _.debounce(this.childrenChanged, 100);\n\t\tthis.close = _.debounce(this.close, 100);\n\t\tthis.open = _.debounce(this.open, 100);\n\n\t\t// Member variable to hold up-to-date list of all attribute profiles\n\t\tthis.attributeProfiles = new AttributeProfiles();\n\n\t\t// Need to defer so everything is done initing\n\t\t_.defer(\n\t\t\t_.bind(function () {\n\t\t\t\t// If a tree was not already set, try and set one\n\t\t\t\tif (!this.has('tree')) {\n\t\t\t\t\tthis.set('tree', opts.tree || this.collection);\n\t\t\t\t}\n\t\t\t\tvar tree = this.get('tree');\n\t\t\t\tif (tree) {\n\t\t\t\t\t// This is a bit backwards as we are storing the collection on the model and also belone to the collection we are storing\n\t\t\t\t\t// We always maintain a reference to our tree until we are totally removed\n\t\t\t\t\t// This way we do not errounously get garbage collected just because we left another collection (so long as we are in the tree)\n\t\t\t\t\tthis.addCollectionReference(this.get('tree'));\n\t\t\t\t}\n\t\t\t}, this),\n\t\t);\n\n\t\t// Set childCategories collection\n\t\tif (!this.has('childCategories')) {\n\t\t\tthis.set(\n\t\t\t\t'childCategories',\n\t\t\t\tnew CategoryTreeNodesCollection(\n\t\t\t\t\tthis.get('open') ? this.children() : [],\n\t\t\t\t\t{categoryid: this.id},\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Hey, listen!\n\t\tthis.listenTo(\n\t\t\tthis,\n\t\t\t'sync',\n\t\t\t_.debounce(function () {\n\t\t\t\t// If it was open, re-open\n\t\t\t\tthis.isOpen() && this.open();\n\t\t\t}, 50),\n\t\t);\n\n\t\t// Child ids have changed\n\t\tthis.listenTo(\n\t\t\tthis,\n\t\t\t'change:children',\n\t\t\t_.debounce(function () {\n\t\t\t\tif (this.get('children').length === 0) {\n\t\t\t\t\tthis.close();\n\t\t\t\t}\n\t\t\t}, 50),\n\t\t);\n\n\t\t// Category successfully edited/created\n\t\tthis.listenTo(\n\t\t\tdispatcher,\n\t\t\t'category:edit:success',\n\t\t\tfunction (model, isNew, newParent) {\n\t\t\t\tif (model instanceof Category) {\n\t\t\t\t\t// Parent id of the updated category\n\t\t\t\t\tvar parentId = parseInt(model.get('parentid'));\n\t\t\t\t\tif (newParent && parentId === customConfig.categoryid) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// If a different model instance of the same DAM category has been edited, grab those changes.\n\t\t\t\t\tif (model.id == this.id && model !== this) {\n\t\t\t\t\t\tthis.updated(model);\n\t\t\t\t\t}\n\t\t\t\t\t// Category successfully added to another - check if it was added to us\n\t\t\t\t\telse if (isNew && parentId == this.id) {\n\t\t\t\t\t\tthis.childAdded(model);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t// The number of children in this category have changed\n\t\tthis.listenTo(\n\t\t\tdispatcher,\n\t\t\t'category:children:changed',\n\t\t\tfunction (parentid, cat) {\n\t\t\t\tparentid = parseInt(parentid);\n\t\t\t\t// If parentid is \"top level\" - that should be sorted out by the tree collection\n\t\t\t\tif (parentid === this.id && parentid !== customConfig.categoryid) {\n\t\t\t\t\tthis.childrenChanged({duplicateQueryPolicy: 'merge'});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t// A child has been removed from category\n\t\tthis.listenTo(\n\t\t\tdispatcher,\n\t\t\t'category:children:removed',\n\t\t\tfunction (parentid, cat) {\n\t\t\t\tparentid = parseInt(parentid);\n\t\t\t\tif (parentid === this.id && parentid !== customConfig.categoryid) {\n\t\t\t\t\tcat && this.childRemoved(cat.id, {duplicateQueryPolicy: 'merge'});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t// Category successfully deleted\n\t\tthis.listenTo(dispatcher, 'category:delete:success', function (cat) {\n\t\t\t// Check if it is one of our children\n\t\t\tif (this.get('children').indexOf(cat.id) > -1) {\n\t\t\t\tthis.childRemoved(cat.id, {duplicateQueryPolicy: 'merge'});\n\t\t\t}\n\t\t});\n\n\t\t// Category was moved\n\t\t// We need to refetch as our ancestors, path and parentid have changed\n\t\tthis.listenTo(\n\t\t\tdispatcher,\n\t\t\t'category:move:success',\n\t\t\tfunction (cat, oldParentId, newParentId) {\n\t\t\t\t// This should never happen - moving the \"top level\" category - but just in case\n\t\t\t\tif (cat && cat.id === this.id && cat.id !== customConfig.categoryid) {\n\t\t\t\t\tthis.moved();\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t// Assets have been added to this category\n\t\tthis.listenTo(\n\t\t\tdispatcher,\n\t\t\t'asset:added:to:category asset:moved:to:category',\n\t\t\tfunction (assetId, catId) {\n\t\t\t\tcatId === this.id && this.assetsAddedToCategory();\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * A model attribute we are storing is not a subCollection but in this case is a collection reference - do not want to get those mixed up\n\t * @override\n\t */\n\tset() {\n\t\t// TODO: Fix this issue - this is dirty dirty\n\t\treturn Backbone.ES6Model.prototype.set.apply(this, arguments);\n\t}\n\t/**\n\t * Only garbage collect if we are no longer referenced in the tree\n\t * @override\n\t */\n\tgarbageCollect() {\n\t\tvar tree = this.get('tree');\n\t\tif (!tree || !tree.get(this.id) || tree.get(this.id) !== this) {\n\t\t\tsuper.garbageCollect();\n\t\t}\n\t}\n\n\t/**\n\t * Fetches attribute profile name/ID for the attribute profile attached\n\t * to the category\n\t */\n\tgetAttributeProfile() {\n\t\treturn this.attributeProfiles\n\t\t\t.getAttributeProfileForFolder(this.id)\n\t\t\t.then(\n\t\t\t\t(attributeProfile) =>\n\t\t\t\t\t(this.selectedAttributeProfile = attributeProfile),\n\t\t\t);\n\t}\n\n\t/**\n\t * Add assets to category\n\t * @method\n\t * @param {array} assets Asset ids\n\t */\n\taddToCategory(assets) {\n\t\tthis.assetsToTransfer = assets;\n\t\treturn this._addToCategory();\n\t}\n\n\t/**\n\t * @method\n\t */\n\tassetsAddedToCategory() {\n\t\t// We can be pretty sure that we now have contents (if we did not already)\n\t\tthis.set('hasContents', true);\n\t}\n\n\t/**\n\t * Check our permissionMatrix for whether a particular named bit is set.\n\t * @method\n\t * @param {string} perm One of the permissions in {module:asset/properties/assetPermissions#matrixNames}\n\t * @returns {mixed} returns true or false, or undefined (which is falsy) if the argument is undefined.\n\t */\n\t// DEVNOTE:\n\t// Until we have a better include/export scheme, we won't know whether asset or category inits first,\n\t// so we can't define one of these in terms of the other at startup.\n\t//\n\t// So instead of doing this:\n\t// allows: module:asset/models/asset.prototype.allows\n\t//\n\t// We must use a wrapper at run-time, like so:\n\tallows() {\n\t\treturn AssetModel.prototype.allows.apply(this, arguments);\n\t}\n\n\t/**\n\t * Child category added\n\t * @method\n\t * @param {Netx.Models.Category} cat Category\n\t * @param {object} opts Request options\n\t */\n\tchildAdded(cat, opts) {\n\t\tthis.fetch(_.extend({duplicateQueryPolicy: 'merge'}, opts));\n\t}\n\t/**\n\t * Child removed/deleted\n\t * @method\n\t * @param {number} catid Category id\n\t * @param {object} opts Request options\n\t */\n\tchildRemoved(catid, opts) {\n\t\t// One of our children was deleted!\n\t\t// 1) update fast!\n\t\tthis.set({children: _.without(this.get('children'), catid)});\n\t\t// 2) sync any/all other changes from server.\n\t\tthis.fetch(_.extend({duplicateQueryPolicy: 'merge'}, opts));\n\t}\n\t/**\n\t * Category children have changed\n\t * @method\n\t * @param {object} opts Request options\n\t */\n\tchildrenChanged(opts) {\n\t\t// Let the tree handle this if there is one to be had\n\t\tthis.fetch(opts).then(\n\t\t\t_.bind(function () {\n\t\t\t\t// Run through tree if we have one\n\t\t\t\tvar tree = this.get('tree'),\n\t\t\t\t\tchildren = this.get('children'),\n\t\t\t\t\tfetchChildren = false;\n\n\t\t\t\tif (tree) {\n\t\t\t\t\t// Check if we have any of our children in the tree\n\t\t\t\t\tfor (var i = 0, c = children.length; i < c; i++) {\n\t\t\t\t\t\tif (tree.get(children[i])) {\n\t\t\t\t\t\t\tfetchChildren = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfetchChildren &&\n\t\t\t\t\t\ttree.fetchChildren(this.id).then(\n\t\t\t\t\t\t\t_.bind(function () {\n\t\t\t\t\t\t\t\tthis.isOpen() && this.open();\n\t\t\t\t\t\t\t}, this),\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}, this),\n\t\t);\n\t}\n\n\t/**\n\t * @method\n\t * @return {Netx.Models.Category} Cloned category\n\t */\n\tclone(tree) {\n\t\ttree = tree || this.get('tree');\n\t\t// Need this to be real clean\n\t\treturn new this.constructor(\n\t\t\t_.extend({}, _.omit(this.attributes, 'childCategories', 'tree'), {\n\t\t\t\tchildCategories: new CategoryTreeNodesCollection(\n\t\t\t\t\tthis.get('childCategories').map(function (m) {\n\t\t\t\t\t\treturn m.clone(tree);\n\t\t\t\t\t}, this),\n\t\t\t\t\t{categoryid: this.id},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{tree: tree},\n\t\t);\n\t}\n\n\t/**\n\t * Close category\n\t * Manage the state of this category in the category tree\n\t * @method\n\t * @param {object} opts Request options\n\t */\n\tclose(opts) {\n\t\topts = opts || {};\n\t\t// Set on model\n\t\tthis.set('open', false);\n\n\t\t// Deprecate - use change:open\n\t\tthis.trigger('close', this);\n\n\t\t// Empty collection so our sub categories are not in the DOM\n\t\tthis.get('childCategories').reset([]);\n\n\t\tvar tree = this.get('tree');\n\t\t// Close all children if desired\n\t\tif (tree && opts.recursive) {\n\t\t\t_.each(\n\t\t\t\tthis.get('children'),\n\t\t\t\tfunction (childId) {\n\t\t\t\t\tvar child = tree.get(childId);\n\t\t\t\t\tchild && child.close(opts);\n\t\t\t\t},\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @method\n\t * @return {number} Depth\n\t */\n\tdepth() {\n\t\tif (this.id == customConfig.categoryid) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this.get('parentid') == customConfig.categoryid) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tvar parentCat = this.parent();\n\t\treturn !parentCat && this.get('ancestors')\n\t\t\t? this.get('ancestors').length || 1\n\t\t\t: parentCat.depth() + 1;\n\t}\n\n\t/*\n\t * Queries the DAM for statistics about the category's contents.\n\t * It returns a promise to categoryDetailsData model.\n\t * @method\n\t * @param {object} opts Fetch options\n\t */\n\tgetDetails(opts) {\n\t\tthis.detailsData = this.detailsData || new CategoryDetailsData();\n\t\tthis.detailsData.set({categoryId: this.id});\n\t\treturn this.detailsData.fetch(opts);\n\t}\n\n\t/**\n\t * Returns a direct link url\n\t * @method\n\t * @return {string} Direct link\n\t */\n\tgetDirectLink() {\n\t\treturn [location.origin, location.pathname, '#category/', this.id].join('');\n\t}\n\n\t/**\n\t * Query this category's position in the overall category tree structure\n\t * @method\n\t * @param {number} id Category id\n\t * @param {boolean} Is child of\n\t */\n\tisChildOf(id) {\n\t\treturn this.get('parentid') == id;\n\t}\n\n\t/**\n\t * @method\n\t * @return {boolean} Open\n\t */\n\tisOpen() {\n\t\treturn this.get('open') ? true : false;\n\t}\n\n\t/**\n\t * Query this category's position in the overall category tree structure\n\t * @method\n\t * @param {number} id Category id\n\t * @return {boolean} Is parent of\n\t */\n\tisParentOf(id) {\n\t\treturn this.get('children').indexOf(id) > -1;\n\t}\n\n\t/**\n\t * Move assets to this category\n\t * @method\n\t * @param {array} assets Asset ids\n\t */\n\tmoveToCategory(assets) {\n\t\t// TODO: make client model attribute\n\t\tthis.assetsToTransfer = assets;\n\t\treturn this._moveToCategory();\n\t}\n\n\t/**\n\t * Our category was moved to another\n\t * @method\n\t */\n\tmoved() {\n\t\t// Refetch us\n\t\tthis.fetch({duplicateQueryPolicy: 'merge'}).then(\n\t\t\t_.bind(function () {\n\t\t\t\t// Run through tree\n\t\t\t\tvar tree = this.get('tree'),\n\t\t\t\t\tchildren = this.get('children'),\n\t\t\t\t\tfetchChildren = false;\n\n\t\t\t\tif (tree) {\n\t\t\t\t\tfor (var i = 0, c = children.length; i < c; i++) {\n\t\t\t\t\t\tif (tree.get(children[i])) {\n\t\t\t\t\t\t\tfetchChildren = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfetchChildren &&\n\t\t\t\t\t\ttree.fetchChildren(this.id).then(\n\t\t\t\t\t\t\t_.bind(function () {\n\t\t\t\t\t\t\t\tthis.isOpen() && this.open();\n\t\t\t\t\t\t\t}, this),\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}, this),\n\t\t);\n\t}\n\n\t/**\n\t * Open category\n\t * Manage the state of this category in the category tree\n\t * @param {object} opts Request options\n\t */\n\topen(opts) {\n\t\topts = opts || {};\n\n\t\t// Set on model\n\t\tthis.set('open', true);\n\t\t// Deprecate - use change:open\n\t\tthis.trigger('open', this);\n\n\t\tlet tree = this.get('tree');\n\n\t\tif (!tree && this.collection instanceof CategoryTreeNodesCollection) {\n\t\t\ttree = this.collection;\n\t\t}\n\n\t\t// Defer so that our views can respond to this change before we start shoving sub categories down its throat\n\t\t_.defer(() => {\n\t\t\tconst childCategories = this.get('childCategories');\n\t\t\tconst empty = !childCategories || childCategories.length === 0;\n\t\t\tlet childrenUpdated = false;\n\t\t\tlet p;\n\n\t\t\t// Set children if necessary\n\t\t\tif (empty) {\n\t\t\t\tp = this.children();\n\t\t\t\tp.then(function (children) {\n\t\t\t\t\t// Use reset or we get an ungdoly amount of add events in the child view code\n\t\t\t\t\tchildCategories.reset(children);\n\t\t\t\t\tchildrenUpdated = true;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Check that we differ at all - otherwise our child models should be updating to their own children changed events\n\t\t\t\tlet diff = _.difference(\n\t\t\t\t\tthis.get('children'),\n\t\t\t\t\tchildCategories.pluck('categoryid'),\n\t\t\t\t);\n\t\t\t\tif (!diff.length) {\n\t\t\t\t\tdiff = _.difference(\n\t\t\t\t\t\tchildCategories.pluck('categoryid'),\n\t\t\t\t\t\tthis.get('children'),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (diff.length) {\n\t\t\t\t\tp = this.children();\n\t\t\t\t\tp.then(function (children) {\n\t\t\t\t\t\tchildCategories.set(children);\n\t\t\t\t\t\tchildrenUpdated = true;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.when(p).then(function () {\n\t\t\t\t// open any/all children (of this category) present in this.get('tree')\n\t\t\t\tif (tree && opts.recursive) {\n\t\t\t\t\t_.each(\n\t\t\t\t\t\tthis.get('children'),\n\t\t\t\t\t\tfunction (childId) {\n\t\t\t\t\t\t\tvar child = tree.get(childId);\n\t\t\t\t\t\t\tchild && child.open(opts);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tthis,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// If there are any children that should be open - open them again (basically put their childView collection models back)\n\t\t\t\t\tchildCategories.each(function (cat) {\n\t\t\t\t\t\tcat.get('open') && cat.open();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * List all (advanced search)\n\t * @method\n\t * @return {Netx.Collections.SearchRules_assets}\n\t */\n\tsearchRules_listAll() {\n\t\t// Build search rules\n\t\tvar searchRules = new AssetSearhRulesCollection([\n\t\t\t{\n\t\t\t\telementType: 23,\n\t\t\t\telementValue1: this.id,\n\t\t\t\telementSubType1: 0,\n\t\t\t},\n\t\t]);\n\t\treturn searchRules;\n\t}\n\n\t/**\n\t * Return an AssetSet model describing this category.\n\t * @method\n\t * @return {module:asset/models/assetSet} Asset set\n\t */\n\ttoAssetSet() {\n\t\treturn new AssetSetModel({\n\t\t\ttype: assetSetTypes.category,\n\t\t\tids: [this.id],\n\t\t\tmodels: [this],\n\t\t\tlabel: this.get('name'),\n\t\t});\n\t}\n\n\t/**\n\t * Another instance of this category has been updated\n\t * @method\n\t * @param {Netx.Collections.Category} cat Category\n\t */\n\tupdated(cat) {\n\t\t// Do not include the childCategories reference - we will get a clean new one\n\t\tthis.set(_.omit(cat.attributes, 'childCategories', 'tree'));\n\t}\n\n\t// children(), parent() and depth() presume that this.get('tree') is a general\n\t// object cache; that's true for the category tree objects, but not\n\t// true for a freshly created object.\n\t// TODO: implement a proper object cache, then query these through it.\n\t/**\n\t * @method\n\t * @return {array} Children\n\t */\n\tchildren() {\n\t\tvar tree = this.get('tree');\n\n\t\t// Tree safeguard\n\t\tif (!tree && this.collection instanceof CategoryTreeNodesCollection) {\n\t\t\ttree = this.collection;\n\t\t}\n\n\t\tvar d = new $.Deferred(),\n\t\t\tself = this;\n\n\t\tif (!tree || !this.get('children').length) {\n\t\t\td.resolve([]);\n\t\t} else {\n\t\t\tvar children = _.compact(\n\t\t\t\t_.map(\n\t\t\t\t\tthis.get('children'),\n\t\t\t\t\tfunction (catid) {\n\t\t\t\t\t\treturn tree.get(catid);\n\t\t\t\t\t},\n\t\t\t\t\tthis,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\td.resolve(children);\n\t\t}\n\n\t\treturn d.promise();\n\t}\n\n\t/**\n\t * @method\n\t * @return {Netx.Models.Category} Parent\n\t */\n\tparent() {\n\t\tvar tree = this.get('tree');\n\t\treturn tree ? tree.get(this.get('parentid')) : undefined;\n\t}\n\n\t/**\n\t * @method\n\t * @return {array} Parents\n\t */\n\tparents(arr) {\n\t\tvar tree = this.get('tree');\n\n\t\tarr = arr || [];\n\n\t\tvar parentid = this.get('parentid');\n\t\tif (tree && parentid != customConfig.categoryid) {\n\t\t\tvar parent = tree.get(parentid);\n\t\t\tarr.push(parent);\n\t\t\treturn parent.parents(arr);\n\t\t}\n\t\treturn arr;\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Category';\n\t}\n}\n","/**\n * @class\n */\nimport Base from 'netxcore@netx/core-category/models/category';\n\nimport customConfig from '../config';\n\nexport default class Category extends Base {\n\t/** @override */\n\tget clientAttrs() {\n\t\treturn super.clientAttrs.concat(['truncated', 'crumbOverflow']);\n\t}\n\n\t/** @override */\n\tget parsers() {\n\t\treturn {\n\t\t\t...super.parsers,\n\t\t\t/**\n\t\t\t * Fetched category breadcrumbs\n\t\t\t * calculates breadcrumb and overflow menu\n\t\t\t * @override\n\t\t\t * @param {array} data Return of the getCategoryBreadcrumbs call (label value objects)\n\t\t\t */\n\t\t\tgetCategoryBreadcrumbs(data, opts) {\n\t\t\t\t// TODO: should a category *model* be creating bread crumbs and even know about the DOM?\n\t\t\t\t// Answer: no\n\t\t\t\t/*\n\t\t\t\t\tmeasuring the width of crumbs by dipping them in the dom\n\t\t\t\t*/\n\n\t\t\t\tvar maxWidth = 135,\n\t\t\t\t\tallCrumbs = _.toArray(data).reverse(),\n\t\t\t\t\tuseCrumbs = [],\n\t\t\t\t\toverflowCrumbs = [],\n\t\t\t\t\tcrumb,\n\t\t\t\t\tcrumbWidth = 0,\n\t\t\t\t\tadj = 10;\n\t\t\t\tthis.set('truncated', false);\n\n\t\t\t\t// THEM-1459 - breadcrumbs stop at the portal categroy setting\n\t\t\t\tvar rootCrumb = _.findWhere(allCrumbs, {\n\t\t\t\t\t\tvalue: customConfig.categoryid.toString(),\n\t\t\t\t\t}),\n\t\t\t\t\trootIdx = (rootCrumb && _.indexOf(allCrumbs, rootCrumb)) || 0;\n\n\t\t\t\t// top level category is not passed back with getCategoryBreadcrumbs\n\t\t\t\t// although it can be set as a portal category, shows up as \"Folders\"\n\t\t\t\tif (customConfig.categoryid > 1) {\n\t\t\t\t\trootIdx++;\n\t\t\t\t}\n\t\t\t\t// cut off everything above the portal root category\n\t\t\t\tallCrumbs = allCrumbs.slice(rootIdx);\n\n\t\t\t\twhile (allCrumbs.length) {\n\t\t\t\t\tcrumb = allCrumbs.pop();\n\n\t\t\t\t\t// once you start down the overflow path, forever will it dominate your destiny, consume you it will\n\t\t\t\t\tif (overflowCrumbs.length > 0) {\n\t\t\t\t\t\toverflowCrumbs.push(crumb);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// create element, hidden and possitioned off screen\n\t\t\t\t\tvar $c = $('