Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 5096dd8

Browse files
alexwolfenaomiblack
authored andcommitted
Refactor of api filter page to include statues, types, queries
1 parent b88b25a commit 5096dd8

File tree

2 files changed

+197
-77
lines changed

2 files changed

+197
-77
lines changed

public/resources/css/module/_badge.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ $badges: (
4545
font-size: 11px;
4646
height: $unit * 3;
4747
line-height: ($unit * 3) - 2;
48-
margin: ($unit + 4) 0;
48+
margin: ($unit + 4) $unit ($unit + 4) 0;
4949
padding: 0 $unit;
5050
text-align: center;
5151
text-transform: uppercase;

public/resources/js/directives/api-list.js

Lines changed: 196 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,43 @@
1212
angularIO.directive('apiList', function () {
1313
var API_FILTER_KEY = 'apiFilter';
1414
var API_TYPE_KEY = 'apiType';
15+
var API_STATUS_KEY = 'statusType';
16+
var QUERY_KEY = 'query';
17+
var TYPE_KEY = 'type';
18+
var STATUS_KEY = 'status';
19+
1520
return {
1621
restrict: 'E',
1722
template:
1823
'<div ng-cloak="ng-cloak" class="banner is-plain api-filter clearfix">' +
1924
' <div class="form-select-menu">' +
20-
' <button ng-repeat="apiType in $ctrl.apiTypes" ng-if="$ctrl.apiType === apiType" class="form-select-button has-symbol" ng-click="$ctrl.toggleMenu()"><strong>Type:</strong><span class="symbol {{apiType.cssClass}}" ng-if="apiType.cssClass !== \'stable\'" ></span>{{apiType.title}}</button>'+
21-
' <button class="form-select-button is-default" ng-if="$ctrl.apiType === null" ng-click="$ctrl.toggleMenu()"><strong>All Types</strong></button>'+
22-
' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showMenu === true }">' +
23-
' <li ng-class="{ active: !$ctrl.apiType }" ng-click="$ctrl.clearType()">All Types</li>' +
24-
' <li ng-repeat="apiType in $ctrl.apiTypes" ng-class="{ active: $ctrl.apiType === apiType }" ng-click="$ctrl.setType(apiType)"><span class="symbol {{apiType.cssClass}}"></span>{{apiType.title}}</li>' +
25+
' <button ng-repeat="type in $ctrl.types" ng-if="$ctrl.type === type.matches[0]" class="form-select-button has-symbol" ng-click="$ctrl.toggleMenu(\'type\')"><strong>Type:</strong><span class="symbol {{type.cssClass}}" ng-if="type.cssClass !== \'stable\'" ></span>{{type.title}}</button>'+
26+
' <button class="form-select-button is-default" ng-if="$ctrl.type === null" ng-click="$ctrl.toggleMenu(\'type\')"><strong>All Types</strong></button>'+
27+
' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showTypeMenu === true }">' +
28+
' <li ng-class="{ active: !$ctrl.type }" ng-click="$ctrl.clear(\'type\')">All Types</li>' +
29+
' <li ng-repeat="type in $ctrl.types" ng-class="{ active: $ctrl.type === type }" ng-click="$ctrl.set(type, \'type\')"><span class="symbol {{type.cssClass}}"></span>{{type.title}}</li>' +
30+
' </ul>' +
31+
' <div class="overlay" ng-class="{ visible: $ctrl.showTypeMenu === true }" ng-click="$ctrl.toggleMenu(\'type\')"></div>' +
32+
' </div>' +
33+
' ' +
34+
' <div class="form-select-menu">' +
35+
' <button ng-repeat="status in $ctrl.statuses" ng-if="$ctrl.status === status.matches[0]" class="form-select-button" ng-click="$ctrl.toggleMenu(\'status\')"><strong>Status:</strong>{{status.title}}</button>'+
36+
' <button class="form-select-button is-default" ng-if="$ctrl.status === null" ng-click="$ctrl.toggleMenu(\'status\')"><strong>All Statuses</strong></button>'+
37+
' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showStatusMenu === true }">' +
38+
' <li ng-class="{ active: !$ctrl.status }" ng-click="$ctrl.clear(\'status\')">All Statuses</li>' +
39+
' <li ng-repeat="status in $ctrl.statuses" ng-class="{ active: $ctrl.status === status }" ng-click="$ctrl.set(status, \'status\')">{{status.title}}</li>' +
2540
' </ul>' +
26-
' <div class="overlay" ng-class="{ visible: $ctrl.showMenu === true }" ng-click="$ctrl.toggleMenu()"></div>' +
41+
' <div class="overlay" ng-class="{ visible: $ctrl.showStatusMenu === true }" ng-click="$ctrl.toggleMenu(\'status\')"></div>' +
2742
' </div>' +
43+
' ' +
2844
' <div class="form-search">' +
2945
' <i class="material-icons">search</i>' +
30-
' <input placeholder="Filter" ng-model="$ctrl.apiFilter" ng-model-options="{updateOn: \'default blur\', debounce: {\'default\': 350, \'blur\': 0}}">' +
46+
' <input placeholder="Filter" ng-model="$ctrl.query" ng-model-options="{updateOn: \'default blur\', debounce: {\'default\': 350, \'blur\': 0}}">' +
3147
' </div>' +
3248
'</div>' +
49+
' ' +
3350
'<article class="l-content-small grid-fluid docs-content">' +
34-
' <div ng-repeat="section in $ctrl.groupedSections" ng-if="$ctrl.isFiltered(section)" ng-cloak="ng-cloak">' +
51+
' <div ng-repeat="section in $ctrl.groupedSections" ng-if="$ctrl.filterSections(section)" ng-cloak="ng-cloak">' +
3552
' <h2>{{ section.title }}</h2>' +
3653
' <ul class="api-list">' +
3754
' <li ng-repeat="item in section.items" ng-show="item.show" class="api-item">' +
@@ -42,111 +59,214 @@ angularIO.directive('apiList', function () {
4259
'</article>',
4360
controllerAs: '$ctrl',
4461
controller: function($scope, $attrs, $http, $location) {
45-
// SET DEFAULTS
62+
// DEFAULT VALUES
4663
var $ctrl = this;
47-
$ctrl.showMenu = false;
48-
var isForDart = $attrs.lang === 'dart';
64+
$ctrl.showTypeMenu = false;
65+
$ctrl.showStatusMenu = false;
66+
$ctrl.status = null;
67+
$ctrl.query = null;
68+
$ctrl.type = null;
69+
$ctrl.groupedSections = [];
4970

50-
$ctrl.apiTypes = [
51-
{ cssClass: 'stable', title: 'Only Stable', matches: ['stable']},
71+
72+
// API TYPES
73+
$ctrl.types = [
5274
{ cssClass: 'directive', title: 'Directive', matches: ['directive'] },
5375
{ cssClass: 'pipe', title: 'Pipe', matches: ['pipe'] },
5476
{ cssClass: 'decorator', title: 'Decorator', matches: ['decorator'] },
5577
{ cssClass: 'class', title: 'Class', matches: ['class'] },
5678
{ cssClass: 'interface', title: 'Interface', matches: ['interface'] },
5779
{ cssClass: 'function', title: 'Function', matches: ['function'] },
5880
{ cssClass: 'enum', title: 'Enum', matches: ['enum'] },
81+
{ cssClass: 'type-alias', title: 'Type Alias', matches: ['type-alias'] },
5982
{ cssClass: 'const', title: 'Const', matches: ['var', 'let', 'const'] }
6083
];
6184

62-
if (isForDart) $ctrl.apiTypes = $ctrl.apiTypes.filter(function (t) {
63-
return !t.cssClass.match(/^(stable|directive|decorator|interface|enum)$/);
64-
});
85+
// STATUSES
86+
$ctrl.statuses = [
87+
{ cssClass: 'stable', title: 'Stable', matches: ['stable']},
88+
{ cssClass: 'deprecated', title: 'Deprecated', matches: ['deprecated']},
89+
{ cssClass: 'experimental', title: 'Experimental', matches: ['experimental']},
90+
{ cssClass: 'security', title: 'Security Risk', matches: ['security']}
91+
];
6592

66-
$ctrl.apiFilter = getApiFilterFromLocation();
67-
$ctrl.apiType = getApiTypeFromLocation();
68-
$ctrl.groupedSections = [];
6993

70-
$ctrl.setType = function (type) {
71-
if (type === $ctrl.apiType) $ctrl.apiType = null;
72-
else $ctrl.apiType = type;
73-
$ctrl.showMenu = !$ctrl.showMenu;
74-
};
94+
// SET FILTER VALUES
95+
getFilterValues();
7596

76-
// CLEAR FILTER
77-
$ctrl.clearType = function () {
78-
$ctrl.apiType = null;
79-
$ctrl.showMenu = !$ctrl.showMenu;
80-
};
8197

82-
// TOGGLE FILTER MENU
83-
$ctrl.toggleMenu = function () {
84-
$ctrl.showMenu = !$ctrl.showMenu;
85-
};
98+
// GRAB DATA FOR SECTIONS
99+
$http.get($attrs.src).then(function(response) {
100+
$ctrl.sections =  response.data;
86101

87-
$ctrl.isFiltered = function(section) {
88-
var apiFilter = ($ctrl.apiFilter || '').toLowerCase();
89-
var matchesModule = $ctrl.apiFilter === '' || $ctrl.apiFilter === null || section.title.toLowerCase().indexOf($ctrl.apiFilter.toLowerCase()) !== -1;
90-
var isVisible = false;
102+
$ctrl.groupedSections = Object.keys($ctrl.sections).map(function(title) {
103+
return { title: title, items: $ctrl.sections[title] };
104+
});
105+
});
91106

92-
section.items.forEach(function(item) {
93107

94-
// Filter by stability (ericjim: only 'stable' for now)
95-
if ($ctrl.apiType && $ctrl.apiType.matches.length === 1 &&
96-
$ctrl.apiType.matches[0] === 'stable' && item.stability === 'stable') {
97-
item.show = true;
98-
isVisible = true;
99-
return isVisible;
100-
} // NOTE: other checks can be performed for stability (experimental, deprecated, etc)
108+
// SET SELECTED VALUE FROM MENUS/FORM
109+
$ctrl.set = function(item, kind) {
110+
var value = (item && item.matches) ? item.matches[0] : null;
101111

102-
// Filter by docType
103-
var matchesDocType = !$ctrl.apiType || $ctrl.apiType.matches.indexOf(item.docType) !== -1;
104-
var matchesTitle = !apiFilter || item.title.toLowerCase().indexOf(apiFilter) !== -1;
105-
item.show = matchesDocType && (matchesTitle || matchesModule);
112+
switch(kind) {
113+
case 'type': $ctrl.type = value ; break;
114+
case 'query': $ctrl.query = value ; break;
115+
case 'status': $ctrl.status = value ; break;
116+
}
106117

107-
if (item.show) {
108-
isVisible = true;
109-
}
110-
});
118+
$ctrl.toggleMenu(kind);
119+
}
111120

112-
return isVisible;
121+
122+
// CLEAR SELECTED VALUE FROM MENUS/FORM
123+
$ctrl.clear = function (kind) {
124+
switch(kind) {
125+
case 'type': $ctrl.type = null ; break;
126+
case 'query': $ctrl.query = null ; break;
127+
case 'status': $ctrl.status = null ; break;
128+
}
129+
130+
$ctrl.toggleMenu(kind);
113131
};
114132

115-
$http.get($attrs.src).then(function(response) {
116-
$ctrl.sections = response.data;
117-
$ctrl.groupedSections = Object.keys($ctrl.sections).map(function(title) {
118-
return { title: title, items: $ctrl.sections[title] };
133+
134+
// TOGGLE MENU
135+
$ctrl.toggleMenu = function(kind) {
136+
console.log(kind);
137+
138+
switch(kind) {
139+
case 'type': $ctrl.showTypeMenu = !$ctrl.showTypeMenu; ; break;
140+
case 'status': $ctrl.showStatusMenu = !$ctrl.showStatusMenu; ; break;
141+
}
142+
}
143+
144+
145+
// UPDATE VALUES IF DART API
146+
var isForDart = $attrs.lang === 'dart';
147+
if (isForDart) {
148+
$ctrl.apiTypes = $ctrl.apiTypes.filter(function (t) {
149+
return !t.cssClass.match(/^(stable|directive|decorator|interface|enum)$/);
119150
});
120-
});
151+
}
121152

153+
154+
// SET URL WITH VALUES
122155
$scope.$watchGroup(
123-
[function() { return $ctrl.apiFilter; }, function() { return $ctrl.apiType; }, function() { return $ctrl.sections; }],
156+
[
157+
function() { return $ctrl.query; },
158+
function() { return $ctrl.type; },
159+
function() { return $ctrl.status; },
160+
function() { return $ctrl.sections; }
161+
],
162+
124163
function() {
125-
var apiFilter = ($ctrl.apiFilter || '').toLowerCase();
164+
var queryURL = $ctrl.query ? $ctrl.query.toLowerCase() : null;
165+
var typeURL = $ctrl.type || null;
166+
var statusURL = $ctrl.status || null;
126167

127-
$location.search(API_FILTER_KEY, apiFilter || null);
128-
$location.search(API_TYPE_KEY, $ctrl.apiType && $ctrl.apiType.title || null);
168+
// SET URLS
169+
$location.search(QUERY_KEY, queryURL);
170+
$location.search(STATUS_KEY, statusURL);
171+
$location.search(TYPE_KEY, typeURL);
129172
}
130173
);
131174

132-
function getApiFilterFromLocation() {
133-
return $location.search()[API_FILTER_KEY] || null;
175+
176+
// GET VALUES FORM URL
177+
function getFilterValues() {
178+
var urlParams = $location.search();
179+
180+
$ctrl.status = urlParams[STATUS_KEY] || null;
181+
$ctrl.query = urlParams[QUERY_KEY] || null;;
182+
$ctrl.type = urlParams[TYPE_KEY] || null;;
134183
}
135184

136-
function getApiTypeFromLocation() {
137-
var apiFilter = $location.search()[API_TYPE_KEY];
138-
if (!apiFilter) {
139-
return null;
140-
} else if (!$ctrl.apiFilter || $ctrl.apiFilter.title != apiFilter) {
141-
for (var i = 0, ii = $ctrl.apiTypes.length; i < ii; i++) {
142-
if ($ctrl.apiTypes[i].title == apiFilter) {
143-
return $ctrl.apiTypes[i];
144-
}
185+
186+
// CHECK IF IT'S A CONSTANT TYPE
187+
function isConst(item) {
188+
var isConst = false;
189+
190+
switch(item.docType) {
191+
case 'let': isConst = true; break;
192+
case 'var': isConst = true; break;
193+
case 'const': isConst = true; break;
194+
default: isConst = false;
195+
}
196+
197+
return isConst;
198+
}
199+
200+
// FILTER SECTION & ITEMS LOOP
201+
$ctrl.filterSections = function(section) {
202+
var showSection = false;
203+
204+
section.items.forEach(function(item) {
205+
item.show = false;
206+
207+
// CHECK IF TYPE IS NULL & STATUS, QUERY
208+
if (($ctrl.type === null) && statusSelected(item) && queryEntered(section, item)) {
209+
item.show = true;
210+
}
211+
212+
// CHECK IF TYPE IS SELECTED & STATUS, QUERY
213+
if (($ctrl.type === item.docType) && statusSelected(item) && queryEntered(section, item)) {
214+
item.show = true;
215+
}
216+
217+
// CHECK IF TYPE IS CONST & STATUS, QUERY
218+
if (($ctrl.type === 'const') && isConst(item) && statusSelected(item) && queryEntered(section, item)) {
219+
item.show = true;
145220
}
221+
222+
// SHOW SECTION IF ONE ITEM IS VISIBLE
223+
if(!showSection && item.show) {
224+
showSection = true;
225+
}
226+
});
227+
228+
return showSection;
229+
}
230+
231+
232+
// CHECK FOR QUERY
233+
function queryEntered(section, item) {
234+
var isVisible = false;
235+
236+
// CHECK IF QUERY MATCH SECTION OR ITEM
237+
var query = ($ctrl.query || '').toLowerCase();
238+
var matchesSection = $ctrl.query === '' || $ctrl.query === null || section.title.toLowerCase().indexOf($ctrl.query.toLowerCase()) !== -1;
239+
var matchesTitle = !query || item.title.toLowerCase().indexOf(query) !== -1;
240+
241+
// FILTER BY QUERY
242+
if(matchesTitle || matchesSection) {
243+
isVisible = true;
146244
}
147-
// If we get here then the apiType query didn't match any apiTypes
148-
$location.search(API_TYPE_KEY, null);
245+
246+
return isVisible;
149247
}
248+
249+
250+
// CHECK IF AN API ITEM IS VISIBLE BY STATUS
251+
function statusSelected(item) {
252+
var status = item.stability;
253+
var insecure = item.secure === 'false' ? false : true;
254+
var isVisible = false;
255+
256+
if($ctrl.status === null) {
257+
isVisible = true;
258+
}
259+
260+
if(status === $ctrl.status) {
261+
isVisible = true;
262+
}
263+
264+
if(($ctrl.status === 'security') && insecure) {
265+
isVisible = true;
266+
}
267+
268+
return isVisible;
269+
};
150270
}
151271
};
152272
});

0 commit comments

Comments
 (0)