nitweb: classdefs and propdefs link directly into class / property linerarization...
[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 controller: function(mentity) {
57 this.mentity = mentity;
58 },
59 controllerAs: 'vm',
60 })
61 .state('doc.entity.graph', {
62 url: '/graph',
63 templateUrl: 'views/doc/graph.html',
64 resolve: {
65 graph: function(Model, $q, $stateParams, $state) {
66 var d = $q.defer();
67 Model.loadEntityGraph($stateParams.id, d.resolve,
68 function() {
69 $state.go('404', null, { location: false })
70 });
71 return d.promise;
72 }
73 },
74 controller: function(graph, $sce) {
75 this.graph = $sce.trustAsHtml(graph);
76 },
77 controllerAs: 'vm',
78 })
79 .state('doc.entity.metrics', {
80 url: '/metrics',
81 templateUrl: 'views/doc/metrics.html',
82 resolve: {
83 metrics: function(Metrics, $q, $stateParams, $state) {
84 var d = $q.defer();
85 Metrics.loadStructuralMetrics($stateParams.id, d.resolve,
86 function() {
87 $state.go('404', null, { location: false })
88 });
89 return d.promise;
90 }
91 },
92 controller: function(mentity, metrics) {
93 this.mentity = mentity;
94 this.metrics = metrics;
95 },
96 controllerAs: 'vm',
97 })
98 .state('doc.entity.code', {
99 url: '/code',
100 templateUrl: 'views/doc/code.html',
101 resolve: {
102 code: function(Model, $q, $stateParams, $state) {
103 var d = $q.defer();
104 Model.loadEntityCode($stateParams.id, d.resolve,
105 function() {
106 $state.go('404', null, { location: false })
107 });
108 return d.promise;
109 }
110 },
111 controller: function(mentity, code) {
112 this.mentity = mentity;
113 this.code = code;
114 },
115 controllerAs: 'vm',
116 })
117 .state('doc.entity.defs', {
118 url: '/defs',
119 templateUrl: 'views/doc/defs.html',
120 resolve: {
121 defs: function(Model, $q, $stateParams, $state) {
122 var d = $q.defer();
123 Model.loadEntityDefs($stateParams.id, d.resolve,
124 function() {
125 $state.go('404', null, { location: false })
126 });
127 return d.promise;
128 }
129 },
130 controller: function(mentity, defs) {
131 this.mentity = mentity;
132 this.defs = defs;
133 },
134 controllerAs: 'vm',
135 })
136 .state('doc.entity.lin', {
137 url: '/lin',
138 templateUrl: 'views/doc/lin.html',
139 resolve: {
140 lin: function(Model, $q, $stateParams, $state) {
141 var d = $q.defer();
142 Model.loadEntityLinearization($stateParams.id, d.resolve,
143 function() {
144 $state.go('404', null, { location: false })
145 });
146 return d.promise;
147 }
148 },
149 controller: function(mentity, lin, $scope, $location, $anchorScroll) {
150 var vm = this;
151 vm.focus = $location.hash() ?
152 $location.hash() : mentity.intro.full_name;
153 vm.mentity = mentity;
154 vm.linearization = lin;
155 setTimeout(function() {
156 $anchorScroll();
157 }, 400);
158 $scope.$watch(function () {
159 return $location.hash();
160 }, function (value) {
161 vm.focus = $location.hash() ?
162 $location.hash() : mentity.intro.full_name;
163 $anchorScroll();
164 });
165 },
166 controllerAs: 'vm'
167 })
168 .state('doc.entity.all', {
169 url: '/all',
170 templateUrl: 'views/doc/all.html',
171 controller: function(mentity) {
172 this.mentity = mentity;
173 },
174 controllerAs: 'vm',
175 })
176 })
177
178 /* Model */
179
180 .factory('Model', [ '$http', function($http) {
181 return {
182
183 loadEntity: function(id, cb, cbErr) {
184 $http.get('/api/entity/' + id)
185 .success(cb)
186 .error(cbErr);
187 },
188
189 loadEntityLinearization: function(id, cb, cbErr) {
190 $http.get('/api/linearization/' + id)
191 .success(cb)
192 .error(cbErr);
193 },
194
195 loadEntityDefs: function(id, cb, cbErr) {
196 $http.get('/api/defs/' + id)
197 .success(cb)
198 .error(cbErr);
199 },
200
201 loadEntityCode: function(id, cb, cbErr) {
202 $http.get('/api/code/' + id)
203 .success(cb)
204 .error(cbErr);
205 },
206
207 loadEntityGraph: function(id, cb, cbErr) {
208 $http.get('/api/graph/inheritance/' + id + '?cdepth=3')
209 .success(cb)
210 .error(cbErr);
211 },
212
213 search: function(q, n, cb, cbErr) {
214 $http.get('/api/search?q=' + q + '&n=' + n)
215 .success(cb)
216 .error(cbErr);
217 }
218 };
219 }])
220
221 /* Directives */
222
223 .directive('entityLink', function() {
224 return {
225 restrict: 'E',
226 scope: {
227 mentity: '='
228 },
229 templateUrl: '/directives/entity/link.html'
230 };
231 })
232
233 .directive('entityDoc', function() {
234 return {
235 restrict: 'E',
236 scope: {
237 mentity: '='
238 },
239 templateUrl: '/directives/entity/doc.html'
240 };
241 })
242
243 .directive('entitySignature', function() {
244 return {
245 restrict: 'E',
246 scope: {
247 mentity: '='
248 },
249 templateUrl: '/directives/entity/signature.html'
250 };
251 })
252
253 .directive('entityNamespace', function() {
254 return {
255 restrict: 'E',
256 scope: {
257 namespace: '='
258 },
259 templateUrl: '/directives/entity/namespace.html',
260 link: function ($scope, element, attrs) {
261 $scope.isObject = function(obj) {
262 return typeof obj === 'object';
263 };
264 $scope.isArray = function(obj) {
265 return Array.isArray(obj);
266 };
267 $scope.isString = function(obj) {
268 return typeof obj === 'string';
269 };
270 }
271 };
272 })
273
274 .directive('entityTag', function() {
275 return {
276 restrict: 'E',
277 scope: {
278 mentity: '='
279 },
280 replace: true,
281 templateUrl: '/directives/entity/tag.html'
282 };
283 })
284
285 .directive('entityLocation', function() {
286 return {
287 restrict: 'E',
288 scope: {
289 mentity: '='
290 },
291 templateUrl: '/directives/entity/location.html'
292 };
293 })
294
295 .directive('entityGraph', function() {
296 return {
297 restrict: 'E',
298 scope: {
299 mentity: '=',
300 graph: '='
301 },
302 replace: true,
303 templateUrl: '/directives/entity/graph.html'
304 };
305 })
306
307 .directive('entityCard', ['Feedback', function(Feedback) {
308 return {
309 restrict: 'E',
310 scope: {
311 mentity: '=',
312 defaultTab: '@',
313 noSynopsis: '='
314 },
315 replace: true,
316 templateUrl: '/directives/entity/card.html',
317 link: function ($scope, element, attrs) {
318 $scope.currentTab = $scope.defaultTab ? $scope.defaultTab : 'signature';
319
320 $scope.loadEntityStars = function() {
321 Feedback.loadEntityStars($scope.mentity.full_name,
322 function(data) {
323 $scope.ratings = data;
324 }, function(message, status) {
325 $scope.error = {message: message, status: status};
326 });
327 };
328 }
329 };
330 }])
331
332 .directive('entityList', function() {
333 return {
334 restrict: 'E',
335 scope: {
336 listEntities: '=',
337 listId: '@',
338 listTitle: '@',
339 listObjectFilter: '=',
340 },
341 templateUrl: '/directives/entity/list.html',
342 link: function ($scope, element, attrs) {
343 $scope.showFilters = false;
344 if(!$scope.listObjectFilter) {
345 $scope.listObjectFilter = {};
346 }
347 if(!$scope.visibilityFilter) {
348 $scope.visibilityFilter = {
349 public: true,
350 protected: true,
351 private: false
352 };
353 }
354 $scope.toggleFilters = function() {
355 $scope.showFilters = !$scope.showFilters;
356 };
357 }
358 };
359 })
360
361 .directive('entityLinearization', function() {
362 return {
363 restrict: 'E',
364 scope: {
365 listEntities: '=',
366 listTitle: '@',
367 listFocus: '='
368 },
369 templateUrl: '/directives/entity/linearization.html'
370 };
371 })
372
373 .directive('entityDef', ['Model', function(Model, Code) {
374 return {
375 restrict: 'E',
376 scope: {
377 definition: '=',
378 focus: '='
379 },
380 templateUrl: '/directives/entity/defcard.html',
381 link: function ($scope, element, attrs) {
382 $scope.codeId = 'code_' + $scope.definition.full_name.replace(/[^a-zA-Z0-9]/g, '_');
383
384 $scope.isActive = function() {
385 return $scope.focus == $scope.definition.full_name;
386 }
387
388 $scope.loadCardCode = function() {
389 if(!$scope.code) {
390 Model.loadEntityCode($scope.definition.full_name,
391 function(data) {
392 $scope.code = data;
393 setTimeout(function() { // smooth collapse
394 $('#' + $scope.codeId).collapse('show')
395 }, 1);
396 }, function(err) {
397 $scope.code = err;
398 });
399 } else {
400 if($('#' + $scope.codeId).hasClass('in')) {
401 $('#' + $scope.codeId).collapse('hide');
402 } else {
403 $('#' + $scope.codeId).collapse('show');
404 }
405 }
406 };
407
408 $scope.$watch('focus', function() {
409 if($scope.isActive()) $scope.loadCardCode();
410 });
411 }
412 };
413 }])
414
415 .controller('StarsCtrl', ['Feedback', '$scope', function(Feedback, $scope) {
416 $ctrl = this;
417
418 this.postStar = function(rating) {
419 Feedback.postEntityStarDimension($scope.mentity.full_name,
420 $scope.dimension, rating,
421 function(data) {
422 $scope.mean = data.mean;
423 $scope.list = data.ratings;
424 $scope.user = data.user;
425 $ctrl.loadEntityStars($scope);
426 }, function(err) {
427 $scope.err = err;
428 });
429 }
430
431 this.loadEntityStars = function($scope) {
432 Feedback.loadEntityStars($scope.mentity.full_name,
433 function(data) {
434 $scope.ratings = data;
435 }, function(message, status) {
436 $scope.error = {message: message, status: status};
437 });
438 };
439 }])
440
441 .directive('entityRating', ['Feedback', function(Feedback) {
442 return {
443 restrict: 'E',
444 scope: {
445 mentity: '=',
446 ratings: '='
447 },
448 controller: 'StarsCtrl',
449 controllerAs: 'ratingsCtrl',
450 templateUrl: '/directives/entity/rating.html'
451 };
452 }])
453
454 .directive('entityStars', ['Feedback', function(Feedback) {
455 return {
456 restrict: 'E',
457 scope: {
458 mentity: '=',
459 dimension: '@',
460 mean: '=',
461 list: '=',
462 user: '=',
463 refresh: '=',
464 ratings: '='
465 },
466 controller: 'StarsCtrl',
467 controllerAs: 'starsCtrl',
468 templateUrl: '/directives/entity/stars.html'
469 };
470 }])
471 })();