Merge: doc: fixed some typos and other misc. corrections
[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 parents: function(Model, $q, $stateParams, $state) {
66 var d = $q.defer();
67 Model.loadEntityParents($stateParams.id, d.resolve,
68 function() {
69 $state.go('404', null, { location: false })
70 });
71 return d.promise;
72 },
73 children: function(Model, $q, $stateParams, $state) {
74 var d = $q.defer();
75 Model.loadEntityChildren($stateParams.id, d.resolve,
76 function() {
77 $state.go('404', null, { location: false })
78 });
79 return d.promise;
80 },
81 intros: function(Model, $q, $stateParams, $state) {
82 var d = $q.defer();
83 Model.loadEntityIntros($stateParams.id, d.resolve,
84 function() {
85 $state.go('404', null, { location: false })
86 });
87 return d.promise;
88 },
89 redefs: function(Model, $q, $stateParams, $state) {
90 var d = $q.defer();
91 Model.loadEntityRedefs($stateParams.id, d.resolve,
92 function() {
93 $state.go('404', null, { location: false })
94 });
95 return d.promise;
96 },
97 meta: function(Model, $q, $stateParams, $state) {
98 var d = $q.defer();
99 Model.loadEntityMeta($stateParams.id, d.resolve,
100 function() {
101 $state.go('404', null, { location: false })
102 });
103 return d.promise;
104 }
105 },
106 controller: function(mentity, doc, parents, children, intros, redefs, meta) {
107 this.mentity = mentity;
108 this.doc = doc;
109 this.parents = parents;
110 this.children = children;
111 this.intros = intros;
112 this.redefs = redefs;
113 this.meta = meta;
114
115 this.date = function(date) {
116 return new Date(date);
117 }
118 },
119 controllerAs: 'vm',
120 })
121 .state('doc.entity.graph', {
122 url: '/graph',
123 templateUrl: 'views/doc/graph.html',
124 resolve: {
125 graph: function(Model, $q, $stateParams, $state) {
126 var d = $q.defer();
127 Model.loadEntityGraph($stateParams.id, d.resolve,
128 function() {
129 $state.go('404', null, { location: false })
130 });
131 return d.promise;
132 },
133 ancestors: function(Model, $q, $stateParams, $state) {
134 var d = $q.defer();
135 Model.loadEntityAncestors($stateParams.id, d.resolve,
136 function() {
137 $state.go('404', null, { location: false })
138 });
139 return d.promise;
140 },
141 parents: function(Model, $q, $stateParams, $state) {
142 var d = $q.defer();
143 Model.loadEntityParents($stateParams.id, d.resolve,
144 function() {
145 $state.go('404', null, { location: false })
146 });
147 return d.promise;
148 },
149 children: function(Model, $q, $stateParams, $state) {
150 var d = $q.defer();
151 Model.loadEntityChildren($stateParams.id, d.resolve,
152 function() {
153 $state.go('404', null, { location: false })
154 });
155 return d.promise;
156 },
157 descendants: function(Model, $q, $stateParams, $state) {
158 var d = $q.defer();
159 Model.loadEntityDescendants($stateParams.id, d.resolve,
160 function() {
161 $state.go('404', null, { location: false })
162 });
163 return d.promise;
164 },
165 },
166 controller: function(ancestors, parents, children, descendants, graph, $sce) {
167 this.graph = $sce.trustAsHtml(graph.graph);
168 this.ancestors = ancestors;
169 this.parents = parents;
170 this.children = children;
171 this.descendants = descendants;
172 },
173 controllerAs: 'vm',
174 })
175 .state('doc.entity.metrics', {
176 url: '/metrics',
177 templateUrl: 'views/doc/metrics.html',
178 resolve: {
179 metrics: function(Metrics, $q, $stateParams, $state) {
180 var d = $q.defer();
181 Metrics.loadStructuralMetrics($stateParams.id, d.resolve,
182 function() {
183 $state.go('404', null, { location: false })
184 });
185 return d.promise;
186 }
187 },
188 controller: function(mentity, metrics) {
189 this.mentity = mentity;
190 this.metrics = metrics;
191 },
192 controllerAs: 'vm',
193 })
194 .state('doc.entity.code', {
195 url: '/code',
196 templateUrl: 'views/doc/code.html',
197 resolve: {
198 code: function(Model, $q, $stateParams, $state) {
199 var d = $q.defer();
200 Model.loadEntityCode($stateParams.id, d.resolve,
201 function() {
202 $state.go('404', null, { location: false })
203 });
204 return d.promise;
205 }
206 },
207 controller: function(mentity, code) {
208 this.mentity = mentity;
209 this.code = code;
210 },
211 controllerAs: 'vm',
212 })
213 .state('doc.entity.defs', {
214 url: '/defs',
215 templateUrl: 'views/doc/defs.html',
216 resolve: {
217 defs: function(Model, $q, $stateParams, $state) {
218 var d = $q.defer();
219 Model.loadEntityDefs($stateParams.id, d.resolve,
220 function() {
221 $state.go('404', null, { location: false })
222 });
223 return d.promise;
224 }
225 },
226 controller: function(mentity, defs) {
227 this.mentity = mentity;
228 this.defs = defs;
229 },
230 controllerAs: 'vm',
231 })
232 .state('doc.entity.lin', {
233 url: '/lin',
234 templateUrl: 'views/doc/lin.html',
235 resolve: {
236 lin: function(Model, $q, $stateParams, $state) {
237 var d = $q.defer();
238 Model.loadEntityLin($stateParams.id, d.resolve,
239 function() {
240 $state.go('404', null, { location: false })
241 });
242 return d.promise;
243 }
244 },
245 controller: function(mentity, lin, $scope, $location, $anchorScroll) {
246 var vm = this;
247 vm.focus = $location.hash() ?
248 $location.hash() : lin.results[0].full_name;
249 vm.mentity = mentity;
250 vm.linearization = lin;
251 setTimeout(function() {
252 $anchorScroll();
253 }, 400);
254 $scope.$watch(function () {
255 return $location.hash();
256 }, function (value) {
257 vm.focus = $location.hash() ?
258 $location.hash() : lin.results[0].full_name;
259 $anchorScroll();
260 });
261 },
262 controllerAs: 'vm'
263 })
264 .state('doc.entity.all', {
265 url: '/all',
266 templateUrl: 'views/doc/defs.html',
267 resolve: {
268 defs: function(Model, $q, $stateParams, $state) {
269 var d = $q.defer();
270 Model.loadEntityAll($stateParams.id, d.resolve,
271 function() {
272 $state.go('404', null, { location: false })
273 });
274 return d.promise;
275 }
276 },
277 controller: function(mentity, defs) {
278 this.mentity = mentity;
279 this.defs = defs;
280 },
281 controllerAs: 'vm',
282 })
283 .state('doc.entity.license', {
284 url: '/license',
285 templateUrl: 'views/doc/license.html',
286 resolve: {
287 content: function(Model, $q, $stateParams, $state) {
288 var d = $q.defer();
289 Model.loadEntityLicenseContent($stateParams.id, d.resolve,
290 function() {
291 $state.go('404', null, { location: false })
292 });
293 return d.promise;
294 }
295 },
296 controller: function(mentity, content) {
297 this.mentity = mentity;
298 this.content = content;
299 },
300 controllerAs: 'vm',
301 })
302 .state('doc.entity.contrib', {
303 url: '/contrib',
304 templateUrl: 'views/doc/contrib.html',
305 resolve: {
306 content: function(Model, $q, $stateParams, $state) {
307 var d = $q.defer();
308 Model.loadEntityContribContent($stateParams.id, d.resolve,
309 function() {
310 $state.go('404', null, { location: false })
311 });
312 return d.promise;
313 }
314 },
315 controller: function(mentity, content) {
316 this.mentity = mentity;
317 this.content = content;
318 },
319 controllerAs: 'vm',
320 })
321 })
322
323 /* Model */
324
325 .factory('Model', [ '$http', function($http) {
326 return {
327
328 loadEntity: function(id, cb, cbErr) {
329 $http.get('/api/entity/' + id)
330 .success(cb)
331 .error(cbErr);
332 },
333
334 loadEntityDoc: function(id, cb, cbErr) {
335 $http.get('/api/doc/' + id + '?format=html')
336 .success(cb)
337 .error(cbErr);
338 },
339
340 loadEntityLin: function(id, cb, cbErr) {
341 $http.get('/api/lin/' + id)
342 .success(cb)
343 .error(cbErr);
344 },
345
346 loadEntityDefs: function(id, cb, cbErr) {
347 $http.get('/api/defs/' + id)
348 .success(cb)
349 .error(cbErr);
350 },
351
352 loadEntityIntros: function(id, cb, cbErr) {
353 $http.get('/api/intros/' + id)
354 .success(cb)
355 .error(cbErr);
356 },
357
358 loadEntityRedefs: function(id, cb, cbErr) {
359 $http.get('/api/redefs/' + id)
360 .success(cb)
361 .error(cbErr);
362 },
363
364 loadEntityAll: function(id, cb, cbErr) {
365 $http.get('/api/all/' + id)
366 .success(cb)
367 .error(cbErr);
368 },
369
370 loadEntityCode: function(id, cb, cbErr) {
371 $http.get('/api/code/' + id + '?format=html')
372 .success(cb)
373 .error(cbErr);
374 },
375
376 loadEntityAncestors: function(id, cb, cbErr) {
377 $http.get('/api/ancestors/' + id)
378 .success(cb)
379 .error(cbErr);
380 },
381
382 loadEntityParents: function(id, cb, cbErr) {
383 $http.get('/api/parents/' + id)
384 .success(cb)
385 .error(cbErr);
386 },
387
388 loadEntityChildren: function(id, cb, cbErr) {
389 $http.get('/api/children/' + id)
390 .success(cb)
391 .error(cbErr);
392 },
393
394 loadEntityDescendants: function(id, cb, cbErr) {
395 $http.get('/api/descendants/' + id)
396 .success(cb)
397 .error(cbErr);
398 },
399
400 loadEntityMeta: function(id, cb, cbErr) {
401 $http.get('/api/meta/' + id)
402 .success(cb)
403 .error(cbErr);
404 },
405
406 loadEntityGraph: function(id, cb, cbErr) {
407 $http.get('/api/graph/inheritance/' + id + '?format=svg&cdepth=3')
408 .success(cb)
409 .error(cbErr);
410 },
411
412 loadEntityLicenseContent: function(id, cb, cbErr) {
413 $http.get('/api/ini/license-content/' + id)
414 .success(cb)
415 .error(cbErr);
416 },
417
418 loadEntityContribContent: function(id, cb, cbErr) {
419 $http.get('/api/ini/contrib-content/' + id)
420 .success(cb)
421 .error(cbErr);
422 },
423
424 loadEntityGraph: function(id, cb, cbErr) {
425 $http.get('/api/graph/inheritance/' + id + '?format=svg&cdepth=3')
426 .success(cb)
427 .error(cbErr);
428 },
429
430 search: function(q, p, n, cb, cbErr) {
431 $http.get('/api/search?q=' + q + '&p=' + p + '&l=' + n)
432 .success(cb)
433 .error(cbErr);
434 }
435 };
436 }])
437
438 /* Directives */
439
440 .directive('entityLink', function() {
441 return {
442 restrict: 'E',
443 scope: {
444 mentity: '='
445 },
446 replace: true,
447 templateUrl: '/directives/entity/link.html'
448 };
449 })
450
451 .directive('entityDoc', function() {
452 return {
453 restrict: 'E',
454 scope: {
455 mentity: '='
456 },
457 templateUrl: '/directives/entity/doc.html'
458 };
459 })
460
461 .directive('entitySignature', function() {
462 return {
463 restrict: 'E',
464 scope: {
465 mentity: '='
466 },
467 templateUrl: '/directives/entity/signature.html'
468 };
469 })
470
471 .directive('entityNamespace', function() {
472 return {
473 restrict: 'E',
474 scope: {
475 namespace: '='
476 },
477 templateUrl: '/directives/entity/namespace.html',
478 link: function ($scope, element, attrs) {
479 $scope.isObject = function(obj) {
480 return typeof obj === 'object';
481 };
482 $scope.isArray = function(obj) {
483 return Array.isArray(obj);
484 };
485 $scope.isString = function(obj) {
486 return typeof obj === 'string';
487 };
488 }
489 };
490 })
491
492 .directive('entityTag', function() {
493 return {
494 restrict: 'E',
495 scope: {
496 mentity: '='
497 },
498 replace: true,
499 templateUrl: '/directives/entity/tag.html'
500 };
501 })
502
503 .directive('entityLocation', function() {
504 return {
505 restrict: 'E',
506 replace: true,
507 scope: {},
508 bindToController: {
509 loc: '='
510 },
511 controller: function() {},
512 controllerAs: 'vm',
513 templateUrl: '/directives/entity/location.html'
514 };
515 })
516
517 .directive('entityGraph', function() {
518 return {
519 restrict: 'E',
520 scope: {
521 mentity: '=',
522 graph: '='
523 },
524 replace: true,
525 templateUrl: '/directives/entity/graph.html'
526 };
527 })
528
529 .directive('entityCard', ['Feedback', function(Feedback) {
530 return {
531 restrict: 'E',
532 scope: {
533 mentity: '='
534 },
535 replace: true,
536 templateUrl: '/directives/entity/card.html'
537 };
538 }])
539
540 .directive('entityList', function() {
541 return {
542 restrict: 'E',
543 scope: {
544 listEntities: '=',
545 listId: '@',
546 listTitle: '@',
547 listObjectFilter: '=',
548 },
549 templateUrl: '/directives/entity/list.html',
550 link: function ($scope, element, attrs) {
551 $scope.showFilters = false;
552 if(!$scope.listObjectFilter) {
553 $scope.listObjectFilter = {};
554 }
555 if(!$scope.visibilityFilter) {
556 $scope.visibilityFilter = {
557 public: true,
558 protected: true,
559 private: false
560 };
561 }
562 $scope.toggleFilters = function() {
563 $scope.showFilters = !$scope.showFilters;
564 };
565 }
566 };
567 })
568
569 .directive('entityLinearization', function() {
570 return {
571 restrict: 'E',
572 scope: {
573 listEntities: '=',
574 listTitle: '@',
575 listFocus: '='
576 },
577 templateUrl: '/directives/entity/linearization.html'
578 };
579 })
580
581 .directive('entityDef', ['Model', function(Model, Code) {
582 return {
583 restrict: 'E',
584 scope: {
585 definition: '=',
586 focus: '='
587 },
588 templateUrl: '/directives/entity/defcard.html',
589 link: function ($scope, element, attrs) {
590 $scope.codeId = 'code_' + $scope.definition.full_name.replace(/[^a-zA-Z0-9]/g, '_');
591
592 $scope.isActive = function() {
593 return $scope.focus == $scope.definition.full_name;
594 }
595
596 $scope.loadCardCode = function() {
597 if(!$scope.code) {
598 Model.loadEntityCode($scope.definition.full_name,
599 function(data) {
600 $scope.code = data;
601 setTimeout(function() { // smooth collapse
602 $('#' + $scope.codeId).collapse('show')
603 }, 1);
604 }, function(err) {
605 $scope.code = err;
606 });
607 } else {
608 if($('#' + $scope.codeId).hasClass('in')) {
609 $('#' + $scope.codeId).collapse('hide');
610 } else {
611 $('#' + $scope.codeId).collapse('show');
612 }
613 }
614 };
615
616 $scope.$watch('focus', function() {
617 if($scope.isActive()) $scope.loadCardCode();
618 });
619 }
620 };
621 }])
622
623 .controller('StarsCtrl', ['Feedback', '$scope', function(Feedback, $scope) {
624 $ctrl = this;
625
626 this.postStar = function(rating) {
627 Feedback.postEntityStarDimension($scope.mentity.full_name,
628 $scope.dimension, rating,
629 function(data) {
630 $scope.mean = data.mean;
631 $scope.list = data.ratings;
632 $scope.user = data.user;
633 $ctrl.loadEntityStars($scope);
634 }, function(err) {
635 $scope.err = err;
636 });
637 }
638
639 this.loadEntityStars = function($scope) {
640 Feedback.loadEntityStars($scope.mentity.full_name,
641 function(data) {
642 $scope.ratings = data;
643 }, function(message, status) {
644 $scope.error = {message: message, status: status};
645 });
646 };
647 }])
648
649 .directive('entityRating', ['Feedback', function(Feedback) {
650 return {
651 restrict: 'E',
652 scope: {
653 mentity: '=',
654 ratings: '='
655 },
656 controller: 'StarsCtrl',
657 controllerAs: 'ratingsCtrl',
658 templateUrl: '/directives/entity/rating.html'
659 };
660 }])
661
662 .directive('entityStars', ['Feedback', function(Feedback) {
663 return {
664 restrict: 'E',
665 scope: {
666 mentity: '=',
667 dimension: '@',
668 mean: '=',
669 list: '=',
670 user: '=',
671 refresh: '=',
672 ratings: '='
673 },
674 controller: 'StarsCtrl',
675 controllerAs: 'starsCtrl',
676 templateUrl: '/directives/entity/stars.html'
677 };
678 }])
679 })();