545e48707ec8c556bf1c20ff78b6cc9add7b0baf
[nit.git] / share / nitweb / javascripts / entities.js
1 /*
2 * Copyright 2016 Alexandre Terrasa <alexandre@moz-code.org>.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 (function() {
18 angular
19 .module('entities', ['ngSanitize', 'ui'])
20
21 /* Router */
22
23 .config(function($stateProvider, $locationProvider) {
24 $stateProvider
25 .state('doc', {
26 url: '/doc/:id',
27 templateUrl: 'views/doc/index.html',
28 resolve: {
29 mentity: function(Model, $q, $stateParams, $state) {
30 var d = $q.defer();
31 Model.loadEntity($stateParams.id, d.resolve,
32 function() {
33 $state.go('404', null, { location: false })
34 });
35 return d.promise;
36 }
37 },
38 controller: function(mentity) {
39 this.mentity = mentity;
40 },
41 controllerAs: 'vm',
42 abstract: true
43 })
44 .state('doc.entity', {
45 url: '',
46 templateUrl: 'views/doc/entity.html',
47 controller: function(mentity) {
48 this.mentity = mentity;
49 },
50 controllerAs: 'vm',
51 abstract: true
52 })
53 .state('doc.entity.doc', {
54 url: '',
55 templateUrl: 'views/doc/doc.html',
56 resolve: {
57 doc: function(Model, $q, $stateParams, $state) {
58 var d = $q.defer();
59 Model.loadEntityDoc($stateParams.id, d.resolve,
60 function() {
61 $state.go('404', null, { location: false })
62 });
63 return d.promise;
64 }
65 },
66 controller: function(mentity, doc) {
67 this.mentity = mentity;
68 this.doc = doc;
69
70 this.date = function(date) {
71 return new Date(date);
72 }
73 },
74 controllerAs: 'vm',
75 })
76 .state('doc.entity.graph', {
77 url: '/graph',
78 templateUrl: 'views/doc/graph.html',
79 resolve: {
80 graph: function(Model, $q, $stateParams, $state) {
81 var d = $q.defer();
82 Model.loadEntityGraph($stateParams.id, d.resolve,
83 function() {
84 $state.go('404', null, { location: false })
85 });
86 return d.promise;
87 },
88 inh: function(Model, $q, $stateParams, $state) {
89 var d = $q.defer();
90 Model.loadEntityInh($stateParams.id, d.resolve,
91 function() {
92 $state.go('404', null, { location: false })
93 });
94 return d.promise;
95 }
96 },
97 controller: function(inh, graph, $sce) {
98 this.graph = $sce.trustAsHtml(graph);
99 this.inh = inh;
100 },
101 controllerAs: 'vm',
102 })
103 .state('doc.entity.metrics', {
104 url: '/metrics',
105 templateUrl: 'views/doc/metrics.html',
106 resolve: {
107 metrics: function(Metrics, $q, $stateParams, $state) {
108 var d = $q.defer();
109 Metrics.loadStructuralMetrics($stateParams.id, d.resolve,
110 function() {
111 $state.go('404', null, { location: false })
112 });
113 return d.promise;
114 }
115 },
116 controller: function(mentity, metrics) {
117 this.mentity = mentity;
118 this.metrics = metrics;
119 },
120 controllerAs: 'vm',
121 })
122 .state('doc.entity.code', {
123 url: '/code',
124 templateUrl: 'views/doc/code.html',
125 resolve: {
126 code: function(Model, $q, $stateParams, $state) {
127 var d = $q.defer();
128 Model.loadEntityCode($stateParams.id, d.resolve,
129 function() {
130 $state.go('404', null, { location: false })
131 });
132 return d.promise;
133 }
134 },
135 controller: function(mentity, code) {
136 this.mentity = mentity;
137 this.code = code;
138 },
139 controllerAs: 'vm',
140 })
141 .state('doc.entity.defs', {
142 url: '/defs',
143 templateUrl: 'views/doc/defs.html',
144 resolve: {
145 defs: function(Model, $q, $stateParams, $state) {
146 var d = $q.defer();
147 Model.loadEntityDefs($stateParams.id, d.resolve,
148 function() {
149 $state.go('404', null, { location: false })
150 });
151 return d.promise;
152 }
153 },
154 controller: function(mentity, defs) {
155 this.mentity = mentity;
156 this.defs = defs;
157 },
158 controllerAs: 'vm',
159 })
160 .state('doc.entity.lin', {
161 url: '/lin',
162 templateUrl: 'views/doc/lin.html',
163 resolve: {
164 lin: function(Model, $q, $stateParams, $state) {
165 var d = $q.defer();
166 Model.loadEntityLinearization($stateParams.id, d.resolve,
167 function() {
168 $state.go('404', null, { location: false })
169 });
170 return d.promise;
171 }
172 },
173 controller: function(mentity, lin, $scope, $location, $anchorScroll) {
174 var vm = this;
175 vm.focus = $location.hash() ?
176 $location.hash() : mentity.intro.full_name;
177 vm.mentity = mentity;
178 vm.linearization = lin;
179 setTimeout(function() {
180 $anchorScroll();
181 }, 400);
182 $scope.$watch(function () {
183 return $location.hash();
184 }, function (value) {
185 vm.focus = $location.hash() ?
186 $location.hash() : mentity.intro.full_name;
187 $anchorScroll();
188 });
189 },
190 controllerAs: 'vm'
191 })
192 .state('doc.entity.all', {
193 url: '/all',
194 templateUrl: 'views/doc/all.html',
195 controller: function(mentity) {
196 this.mentity = mentity;
197 },
198 controllerAs: 'vm',
199 })
200 })
201
202 /* Model */
203
204 .factory('Model', [ '$http', function($http) {
205 return {
206
207 loadEntity: function(id, cb, cbErr) {
208 $http.get('/api/entity/' + id)
209 .success(cb)
210 .error(cbErr);
211 },
212
213 loadEntityDoc: function(id, cb, cbErr) {
214 $http.get('/api/entity/' + id + '/doc')
215 .success(cb)
216 .error(cbErr);
217 },
218
219 loadEntityLinearization: function(id, cb, cbErr) {
220 $http.get('/api/linearization/' + id)
221 .success(cb)
222 .error(cbErr);
223 },
224
225 loadEntityDefs: function(id, cb, cbErr) {
226 $http.get('/api/defs/' + id)
227 .success(cb)
228 .error(cbErr);
229 },
230
231 loadEntityCode: function(id, cb, cbErr) {
232 $http.get('/api/code/' + id)
233 .success(cb)
234 .error(cbErr);
235 },
236
237 loadEntityGraph: function(id, cb, cbErr) {
238 $http.get('/api/graph/inheritance/' + id + '?cdepth=3')
239 .success(cb)
240 .error(cbErr);
241 },
242
243 loadEntityInh: function(id, cb, cbErr) {
244 $http.get('/api/inheritance/' + id)
245 .success(cb)
246 .error(cbErr);
247 },
248 search: function(q, p, n, cb, cbErr) {
249 $http.get('/api/search?q=' + q + '&p=' + p + '&n=' + n)
250 .success(cb)
251 .error(cbErr);
252 }
253 };
254 }])
255
256 /* Directives */
257
258 .directive('entityLink', function() {
259 return {
260 restrict: 'E',
261 scope: {
262 mentity: '='
263 },
264 templateUrl: '/directives/entity/link.html'
265 };
266 })
267
268 .directive('entityDoc', function() {
269 return {
270 restrict: 'E',
271 scope: {
272 mentity: '='
273 },
274 templateUrl: '/directives/entity/doc.html'
275 };
276 })
277
278 .directive('entitySignature', function() {
279 return {
280 restrict: 'E',
281 scope: {
282 mentity: '='
283 },
284 templateUrl: '/directives/entity/signature.html'
285 };
286 })
287
288 .directive('entityNamespace', function() {
289 return {
290 restrict: 'E',
291 scope: {
292 namespace: '='
293 },
294 templateUrl: '/directives/entity/namespace.html',
295 link: function ($scope, element, attrs) {
296 $scope.isObject = function(obj) {
297 return typeof obj === 'object';
298 };
299 $scope.isArray = function(obj) {
300 return Array.isArray(obj);
301 };
302 $scope.isString = function(obj) {
303 return typeof obj === 'string';
304 };
305 }
306 };
307 })
308
309 .directive('entityTag', function() {
310 return {
311 restrict: 'E',
312 scope: {
313 mentity: '='
314 },
315 replace: true,
316 templateUrl: '/directives/entity/tag.html'
317 };
318 })
319
320 .directive('entityLocation', function() {
321 return {
322 restrict: 'E',
323 scope: {
324 mentity: '='
325 },
326 templateUrl: '/directives/entity/location.html'
327 };
328 })
329
330 .directive('entityGraph', function() {
331 return {
332 restrict: 'E',
333 scope: {
334 mentity: '=',
335 graph: '='
336 },
337 replace: true,
338 templateUrl: '/directives/entity/graph.html'
339 };
340 })
341
342 .directive('entityCard', ['Feedback', function(Feedback) {
343 return {
344 restrict: 'E',
345 scope: {
346 mentity: '='
347 },
348 replace: true,
349 templateUrl: '/directives/entity/card.html'
350 };
351 }])
352
353 .directive('entityList', function() {
354 return {
355 restrict: 'E',
356 scope: {
357 listEntities: '=',
358 listId: '@',
359 listTitle: '@',
360 listObjectFilter: '=',
361 },
362 templateUrl: '/directives/entity/list.html',
363 link: function ($scope, element, attrs) {
364 $scope.showFilters = false;
365 if(!$scope.listObjectFilter) {
366 $scope.listObjectFilter = {};
367 }
368 if(!$scope.visibilityFilter) {
369 $scope.visibilityFilter = {
370 public: true,
371 protected: true,
372 private: false
373 };
374 }
375 $scope.toggleFilters = function() {
376 $scope.showFilters = !$scope.showFilters;
377 };
378 }
379 };
380 })
381
382 .directive('entityLinearization', function() {
383 return {
384 restrict: 'E',
385 scope: {
386 listEntities: '=',
387 listTitle: '@',
388 listFocus: '='
389 },
390 templateUrl: '/directives/entity/linearization.html'
391 };
392 })
393
394 .directive('entityDef', ['Model', function(Model, Code) {
395 return {
396 restrict: 'E',
397 scope: {
398 definition: '=',
399 focus: '='
400 },
401 templateUrl: '/directives/entity/defcard.html',
402 link: function ($scope, element, attrs) {
403 $scope.codeId = 'code_' + $scope.definition.full_name.replace(/[^a-zA-Z0-9]/g, '_');
404
405 $scope.isActive = function() {
406 return $scope.focus == $scope.definition.full_name;
407 }
408
409 $scope.loadCardCode = function() {
410 if(!$scope.code) {
411 Model.loadEntityCode($scope.definition.full_name,
412 function(data) {
413 $scope.code = data;
414 setTimeout(function() { // smooth collapse
415 $('#' + $scope.codeId).collapse('show')
416 }, 1);
417 }, function(err) {
418 $scope.code = err;
419 });
420 } else {
421 if($('#' + $scope.codeId).hasClass('in')) {
422 $('#' + $scope.codeId).collapse('hide');
423 } else {
424 $('#' + $scope.codeId).collapse('show');
425 }
426 }
427 };
428
429 $scope.$watch('focus', function() {
430 if($scope.isActive()) $scope.loadCardCode();
431 });
432 }
433 };
434 }])
435
436 .controller('StarsCtrl', ['Feedback', '$scope', function(Feedback, $scope) {
437 $ctrl = this;
438
439 this.postStar = function(rating) {
440 Feedback.postEntityStarDimension($scope.mentity.full_name,
441 $scope.dimension, rating,
442 function(data) {
443 $scope.mean = data.mean;
444 $scope.list = data.ratings;
445 $scope.user = data.user;
446 $ctrl.loadEntityStars($scope);
447 }, function(err) {
448 $scope.err = err;
449 });
450 }
451
452 this.loadEntityStars = function($scope) {
453 Feedback.loadEntityStars($scope.mentity.full_name,
454 function(data) {
455 $scope.ratings = data;
456 }, function(message, status) {
457 $scope.error = {message: message, status: status};
458 });
459 };
460 }])
461
462 .directive('entityRating', ['Feedback', function(Feedback) {
463 return {
464 restrict: 'E',
465 scope: {
466 mentity: '=',
467 ratings: '='
468 },
469 controller: 'StarsCtrl',
470 controllerAs: 'ratingsCtrl',
471 templateUrl: '/directives/entity/rating.html'
472 };
473 }])
474
475 .directive('entityStars', ['Feedback', function(Feedback) {
476 return {
477 restrict: 'E',
478 scope: {
479 mentity: '=',
480 dimension: '@',
481 mean: '=',
482 list: '=',
483 user: '=',
484 refresh: '=',
485 ratings: '='
486 },
487 controller: 'StarsCtrl',
488 controllerAs: 'starsCtrl',
489 templateUrl: '/directives/entity/stars.html'
490 };
491 }])
492 })();