1 /*global GCN: true */ 2 3 (function (GCN) { 4 5 'use strict'; 6 7 /** 8 * Maps constructcategories that were fetched via the Rest API 9 * into a sorted nested array of constructs. 10 * 11 * @param {object<string, object>} constructs 12 * @return {object<string, object>} 13 */ 14 function mapConstructCategories(constructs) { 15 var constructKeyword; 16 var categoryMap = { categories: {}, categorySortorder: [] }; 17 var constructCategoryArray = []; 18 19 for (constructKeyword in constructs) { 20 if (constructs.hasOwnProperty(constructKeyword)) { 21 var construct = constructs[constructKeyword]; 22 23 var constructCategoryName = construct.category; 24 var categorySortorder = construct.categorySortorder; 25 26 // Use a custom name for constructs that have not been assigned to a category 27 if (!constructCategoryName) { 28 constructCategoryName = "GCN_UNCATEGORIZED"; 29 categorySortorder = -1; 30 } 31 32 // Initialize the inner array of constructs 33 if (!categoryMap.categories[constructCategoryName]) { 34 var newCategory = {}; 35 newCategory.constructs = {}; 36 newCategory.sortorder = categorySortorder; 37 newCategory.name = constructCategoryName; 38 categoryMap.categories[constructCategoryName] = newCategory; 39 constructCategoryArray.push(newCategory); 40 } 41 42 // Add the construct to the category 43 categoryMap.categories[constructCategoryName].constructs[constructKeyword] = construct; 44 } 45 } 46 47 // Sort the categories by the sortorder 48 constructCategoryArray.sort(function (a, b) { 49 return a.sortorder - b.sortorder; 50 }); 51 52 // Add the sorted category names to the sortorder field 53 var k; 54 for (k in constructCategoryArray) { 55 if (constructCategoryArray.hasOwnProperty(k)) { 56 var category = constructCategoryArray[k]; 57 if (typeof category.sortorder !== 'undefined' && category.sortorder !== -1) { 58 categoryMap.categorySortorder.push(category.name); 59 } 60 } 61 } 62 63 return categoryMap; 64 } 65 66 /** 67 * Maps constructs, that were fetched via the Rest API, using their keyword 68 * as the keys. 69 * 70 * @param {object<string, object>} constructs Consturcts mapped against 71 * their id. 72 * @return {object<string, object>} Constructs mapped against their keys. 73 */ 74 function mapConstructs(constructs) { 75 if (!constructs) { 76 return {}; 77 } 78 var map = {}; 79 var constructId; 80 for (constructId in constructs) { 81 if (constructs.hasOwnProperty(constructId)) { 82 map[constructs[constructId].keyword] = constructs[constructId]; 83 } 84 } 85 return map; 86 } 87 88 /** 89 * Node object. 90 * 91 * @name NodeAPI 92 * @class 93 * @augments Chainback 94 */ 95 var NodeAPI = GCN.defineChainback({ 96 /** @lends NodeAPI */ 97 98 __chainbacktype__: 'NodeAPI', 99 _extends: GCN.ContentObjectAPI, 100 _type: 'node', 101 102 _data: { 103 folderId: null 104 }, 105 106 /** 107 * @private 108 * @type {object<string, number} Constructs for this node are cached 109 * here so that we only need to fetch 110 * this once. 111 */ 112 _constructs: null, 113 114 /** 115 * @private 116 * @type {object<string, object} Constructs categories for this node. 117 * Cached here so that we only need to 118 * fetch this once. 119 */ 120 _constructCategories: null, 121 122 /** 123 * Retrieves a list of constructs and constructs categories that are 124 * assigned to this node and passes it as the only argument into the 125 * the `success()' callback. 126 * 127 * @param {function(Array.<object>)=} success Callback to receive an 128 * array of constructs. 129 * @param {function(GCNError):boolean=} error Custom error handler. 130 * @return undefined 131 * @throws INVALID_ARGUMENTS 132 */ 133 constructs: function (success, error) { 134 var that = this; 135 if (!success) { 136 GCN.error('INVALID_ARGUMENTS', 'the `constructs()\' method ' + 137 'requires at least a success callback to be given'); 138 } 139 if (this._constructs) { 140 this._invoke(success, [this._constructs]); 141 } else { 142 var fork = this._fork(); 143 var fetchConstructs = function () { 144 fork._authAjax({ 145 url: GCN.settings.BACKEND_PATH + '/rest/construct/list.json?nodeId=' + that.id(), 146 type: 'GET', 147 error: function (xhr, status, msg) { 148 GCN.handleHttpError(xhr, msg, error); 149 }, 150 success: function (response) { 151 if (GCN.getResponseCode(response) === 'OK') { 152 fork._constructs = mapConstructs(response.constructs); 153 fork._invoke(success, [fork._constructs]); 154 } else { 155 GCN.handleResponseError(response, error); 156 fork._merge(); 157 } 158 }, 159 complete: function () { 160 fork._merge(); 161 } 162 }); 163 return false; 164 }; 165 166 fork._read(fetchConstructs, error); 167 } 168 }, 169 170 /** 171 * Removes this node object. 172 * 173 * @param {function=} success Callback. 174 * @param {function(GCNError):boolean=} error Custom error handler. 175 * @param {function} success callback 176 */ 177 remove: function (success, error) { 178 GCN.error('NOT_YET_IMPLEMENTED', "This method is not yet implemented"); 179 }, 180 181 /** 182 * Saves the locally modified changes back to the system. 183 * This is currently not yet implemented. 184 * 185 * @public 186 * @override 187 */ 188 save: function () { 189 GCN.error('NOT_YET_IMPLEMENTED', "This method is not yet implemented"); 190 }, 191 192 /** 193 * Retrieves the top-level folders of this node's root folder. 194 * 195 * @param {function(FolderAPI)=} success 196 * @param {function(GCNError):boolean=} error Custom error handler. 197 */ 198 '!folders': function (success, error) { 199 return this.folder(null, error).folders(success, error); 200 }, 201 202 /** 203 * Helper method that will load the constructs of this node. 204 * 205 * @private 206 * @this {NodeAPI} 207 * @param {function(Array.<object>)} success callback 208 * @param {function(GCNError):boolean=} error callback 209 */ 210 constructCategories: function (success, error) { 211 if (this._constructCategories) { 212 this._invoke(success, [this._constructCategories]); 213 } else { 214 var that = this; 215 this._read(function () { 216 that._data.id = that._data.nodeId; //child._data.nodeId 217 that.constructs(function (constructs) { 218 that._constructCategories 219 = mapConstructCategories(constructs); 220 that._invoke(success, [that._constructCategories]); 221 }, error); 222 }, error); 223 } 224 } 225 226 }); 227 228 GCN.node = GCN.exposeAPI(NodeAPI); 229 GCN.NodeAPI = NodeAPI; 230 231 }(GCN)); 232