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