Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit c30fa03

Browse files
authored
Merge pull request #434 from topcoder-platform/develop
Version 1.2.1
2 parents 35bb801 + 0f49c5c commit c30fa03

File tree

10 files changed

+361
-73
lines changed

10 files changed

+361
-73
lines changed

Diff for: src/common/db-helper.js

+45-5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ async function scan(model, scanParams) {
7070
});
7171
}
7272

73+
/**
74+
* Get data collection by scan parameters with paging
75+
* @param {Object} model The dynamoose model to scan
76+
* @param {Object} scanParams The scan parameters object
77+
* @param {String} size The size of result
78+
* @param {String} lastKey The lastKey param
79+
* @returns {Promise<void>}
80+
*/
81+
async function scanWithLimit(model, scanParams, size, lastKey) {
82+
return await new Promise((resolve, reject) => {
83+
const scanMethod = model.scan(scanParams).limit(size);
84+
if (lastKey) scanMethod.startAt(lastKey);
85+
scanMethod.exec((err, result) => {
86+
if (err) {
87+
logger.error(`DynamoDB scan error ${err}`);
88+
return reject(err);
89+
}
90+
return resolve(result.count === 0 ? [] : result);
91+
});
92+
});
93+
}
94+
7395
/**
7496
* Get data collection by scan parameters with paging
7597
* @param {Object} model The dynamoose model to scan
@@ -91,19 +113,35 @@ async function scanAll(model, size, lastKey) {
91113
});
92114
}
93115

116+
/**
117+
* Get data collection by scan parameters
118+
* @param {Object} model The dynamoose model to scan
119+
* @param {Object} scanParams The scan parameters object
120+
* @returns {Promise<void>}
121+
*/
122+
async function scanAllWithParams(model, scanParams) {
123+
return await new Promise((resolve, reject) => {
124+
model.scan(scanParams).all().exec((err, result) => {
125+
if (err) {
126+
logger.error(`DynamoDB scan error ${err}`);
127+
return reject(err);
128+
}
129+
130+
return resolve(result.count === 0 ? [] : result);
131+
});
132+
});
133+
}
134+
94135
/**
95136
* Get data collection by scan with search
96137
* @param {Object} model The dynamoose model to scan
97-
* @param {String} size The size of result
98-
* @param {String} lastKey The lastKey param
99138
* @param {String} containsKey The contains key param
100139
* @param {String} contains The contains value
101140
* @returns {Promise<void>}
102141
*/
103-
async function scanAllWithSearch(model, size, lastKey, containsKey, contains) {
142+
async function scanAllWithSearch(model, containsKey, contains) {
104143
return await new Promise((resolve, reject) => {
105-
const scanMethod = model.scan(containsKey).contains(contains).limit(size);
106-
if (lastKey) scanMethod.startAt(lastKey);
144+
const scanMethod = model.scan(containsKey).contains(contains).all();
107145
scanMethod.exec((err, result) => {
108146
if (err) {
109147
logger.error(`DynamoDB scan error ${err}`);
@@ -547,6 +585,8 @@ module.exports = {
547585
scan,
548586
scanAll,
549587
scanAllWithSearch,
588+
scanWithLimit,
589+
scanAllWithParams,
550590
create,
551591
update,
552592
removeById,

Diff for: src/controllers/ProjectController.js

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ async function getAll(req) {
4242
return await ProjectService.getAll(req.query, req.currentUser);
4343
}
4444

45+
/**
46+
* search all projects
47+
* @param {Object} req the request
48+
* @returns {Array} the result
49+
*/
50+
async function search(req) {
51+
return await ProjectService.search(req.query, req.currentUser);
52+
}
53+
4554
/**
4655
* create label
4756
* @param {Object} req the request
@@ -126,6 +135,7 @@ module.exports = {
126135
createHook,
127136
addWikiRules,
128137
transferOwnerShip,
138+
search,
129139
};
130140

131141
helper.buildController(module.exports);

Diff for: src/front/src/app/main/main.controller.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ angular.module('topcoderX')
151151

152152
//private function to get projects.
153153
$scope.getProjects = function (status) {
154-
ProjectService.getProjects(status, false).then(function (response) {
154+
ProjectService.getProjects(status, false, 1).then(function (response) {
155155
$scope.projects = response.data;
156156
if (!$scope.projects || $scope.projects.length === 0) {
157157
$scope.showTutorial();

Diff for: src/front/src/app/projects/project.service.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@ angular.module('topcoderX')
2323
};
2424

2525
/**
26-
* Get all projects
26+
* Get projects
2727
*/
28-
ProjectService.getProjects = function (status, showAll) {
29-
var url = Helper.baseUrl + '/api/v1/projects?status=' + status + '&showAll=' + showAll;
28+
ProjectService.getProjects = function (status, showAll, perPage, lastKey, query) {
29+
var url = Helper.baseUrl + '/api/v1/projects?status=' + status + '&showAll=' + showAll + '&perPage=' + perPage +
30+
(lastKey ? '&lastKey=' + lastKey : '' );
31+
if (query) {
32+
url = Helper.baseUrl + '/api/v1/projects/search?status=' + status + '&showAll=' + showAll + '&perPage=' + perPage +
33+
'&query=' + query;
34+
}
3035
if (projectsGetLock[url]) {
3136
return projectsDataPromise[url];
3237
}

Diff for: src/front/src/app/projects/projects.controller.js

+88-32
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

33
angular.module('topcoderX')
4-
.controller('ProjectsController', ['currentUser', '$scope', '$state', 'ProjectService', '$filter', '$rootScope', 'Alert', 'Helper', '$timeout',
5-
function (currentUser, $scope, $state, ProjectService, $filter, $rootScope, Alert, Helper, $timeout) {
4+
.controller('ProjectsController', ['currentUser', '$scope', '$state', 'ProjectService', '$filter', '$rootScope', 'Alert', 'Helper',
5+
function (currentUser, $scope, $state, ProjectService, $filter, $rootScope, Alert, Helper) {
66
//Current title
77
$scope.title = 'Project Management';
88

@@ -15,6 +15,15 @@ angular.module('topcoderX')
1515
$scope.state = {
1616
status: 'active',
1717
};
18+
$scope.tableConfig = {
19+
pageNumber: 1,
20+
pageSize: 10,
21+
isLoading: false,
22+
initialized: false,
23+
query: '',
24+
lastKey: [],
25+
pages: 1
26+
};
1827

1928
//go to a project detail
2029
$scope.goProject = function (project) {
@@ -44,13 +53,27 @@ angular.module('topcoderX')
4453
$scope.state.status = status;
4554
$scope.isLoaded = false;
4655
$scope.projects = [];
47-
ProjectService.getProjects(status, $scope.filter.showAll).then(function (response) {
56+
ProjectService.getProjects(
57+
status, $scope.filter.showAll,
58+
$scope.tableConfig.pageSize, $scope.tableConfig.lastKey[$scope.tableConfig.pageNumber],
59+
$scope.tableConfig.query).then(function (response) {
60+
var config = $scope.tableConfig;
61+
62+
if (config.query) {
63+
config.allItems = response.data.docs;
64+
$scope.projects = config.allItems.slice(0, config.pageSize);
65+
config.pages = Math.ceil(config.allItems.length / config.pageSize);
66+
}
67+
else {
68+
$scope.projects = response.data.docs;
69+
}
70+
if (response.data.lastKey) {
71+
config.lastKey[config.pageNumber + 1] = response.data.lastKey;
72+
if (!config.pages || config.pages <= config.pageNumber) {
73+
config.pages = config.pageNumber + 1;
74+
}
75+
}
4876
$scope.isLoaded = true;
49-
$scope.projects = response.data;
50-
$scope.allProjects = angular.copy($scope.projects);
51-
$timeout(function () {
52-
$scope.init();
53-
}, 1000);
5477
}).catch(function (error) {
5578
$scope.isLoaded = true;
5679
if (error.data) {
@@ -61,6 +84,51 @@ angular.module('topcoderX')
6184
});
6285
};
6386

87+
/**
88+
* get the number array that shows the pagination bar
89+
*/
90+
$scope.getPageArray = function () {
91+
var res = [];
92+
93+
var pageNo = $scope.tableConfig.pageNumber;
94+
var i = pageNo - 5;
95+
for (i; i <= pageNo; i++) {
96+
if (i > 0) {
97+
res.push(i);
98+
}
99+
}
100+
var j = pageNo + 1;
101+
for (j; j <= $scope.tableConfig.pages && j <= pageNo + 5; j++) {
102+
res.push(j);
103+
}
104+
return res;
105+
};
106+
107+
/**
108+
* handles the change page click
109+
* @param {Number} pageNumber the page number
110+
*/
111+
$scope.changePage = function (pageNumber) {
112+
if (pageNumber === 0 || pageNumber > $scope.tableConfig.pages ||
113+
(pageNumber === $scope.tableConfig.pages &&
114+
$scope.tableConfig.pageNumber === pageNumber)) {
115+
return false;
116+
}
117+
$scope.tableConfig.pageNumber = pageNumber;
118+
if ($scope.tableConfig.query && $scope.tableConfig.allItems) {
119+
var start = ($scope.tableConfig.pageNumber - 1) * $scope.tableConfig.pageSize - 1;
120+
if (pageNumber === 1) {
121+
start = 0;
122+
}
123+
$scope.projects = $scope.tableConfig.allItems.slice(
124+
start, $scope.tableConfig.pageSize);
125+
$scope.isLoaded = true;
126+
}
127+
else {
128+
$scope.getProjects($scope.state.status);
129+
}
130+
};
131+
64132
$scope.repoType = function (repo) {
65133
if (repo.toLocaleLowerCase().indexOf("github") >= 0) {
66134
return "Github";
@@ -82,31 +150,19 @@ angular.module('topcoderX')
82150
$scope.getProjects($scope.state.status);
83151
};
84152

85-
86-
$scope.onSearchChange = function (obj) {
87-
$scope.searchText = obj.searchText;
88-
if (!obj.searchText || obj.searchText.length === 0) {
89-
$scope.getProjects($scope.state.status);
90-
}
91-
92-
if ($scope.allProjects.length > 0) {
93-
_searchLocal(obj.searchText);
94-
}
95-
};
96-
97153
$scope.onSearchIconClicked = function () {
98-
if ($scope.allProjects.length > 0 && $scope.searchText) {
99-
_searchLocal($scope.searchText);
100-
}
154+
$scope.tableConfig.pageNumber = 1;
155+
$scope.tableConfig.pages = 1;
156+
$scope.tableConfig.allItems = [];
157+
$scope.getProjects($scope.state.status);
101158
};
102159

103-
function _searchLocal(query) {
104-
$scope.projects = $scope.allProjects.filter(function(value) {
105-
return value['title'].toLowerCase().includes(query.toLowerCase());
106-
})
107-
$timeout(function () {
108-
$('.footable').filter('[data-page="0"]').trigger('click');
109-
}, 1000);
110-
}
111-
160+
$scope.onSearchReset = function () {
161+
var config = $scope.tableConfig;
162+
config.query = '';
163+
config.pageNumber = 1;
164+
config.pages = 1;
165+
config.allItems = [];
166+
$scope.getProjects($scope.state.status);
167+
};
112168
}]);

Diff for: src/front/src/app/projects/projects.html

+48-14
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ <h2>{{title}}</h2>
3030
<uib-tab index="0" heading="Current Projects" select="getProjects('active')">
3131
<br />
3232
<div ng-if="isLoaded">
33-
<div ng-show="allProjects.length===0">
33+
<div ng-show="projects.length===0 && !tableConfig.query">
3434
<div class="text-center m-t-lg">
3535
<h4>You don't have active projects right now. Please
3636
<button class="btn btn-sm btn-info" ng-click="goProject()">
@@ -41,15 +41,18 @@ <h4>You don't have active projects right now. Please
4141
</h4>
4242
</div>
4343
</div>
44-
<div ng-hide="allProjects.length===0">
44+
<div ng-hide="projects.length===0 && !tableConfig.query">
4545
<div class="col-lg-4" style="padding-left: 0px">
4646
<div class="input-group custom-search-form">
47-
<input ng-model="searchText" type="text" class="form-control" placeholder="Find projects" ng-change="onSearchChange(this)">
47+
<input ng-model="tableConfig.query" type="text" class="form-control" placeholder="Find projects" ng-keyup="$event.keyCode == 13 && onSearchIconClicked()">
4848
<span class="input-group-btn">
49-
<button class="btn btn-default" type="button" ng-click="onSearchIconClicked('github')">
49+
<button class="btn btn-default" type="button" ng-click="onSearchIconClicked()">
5050
<span class="glyphicon glyphicon-search"></span>
5151
</button>
52-
</span>
52+
<button class="btn btn-danger" type="button" ng-click="onSearchReset()">
53+
<span class="glyphicon glyphicon-remove"></span>
54+
</button>
55+
</span>
5356
</div>
5457
</div>
5558
<table class="footable table table-stripped toggle-arrow-tiny"
@@ -94,10 +97,24 @@ <h4>You don't have active projects right now. Please
9497
</td>
9598
</tr>
9699
</tbody>
97-
<tfoot ng-hide="searchText">
100+
<tfoot>
98101
<tr>
99-
<td colspan="{{isAdminUser? 5: 4}}">
100-
<ul class="pagination pull-right"></ul>
102+
<td colspan="5">
103+
<ul class="pagination pull-right">
104+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === 1}">
105+
<a ng-click="changePage(1)">«</a>
106+
</li>
107+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === 1}">
108+
<a ng-click="changePage(tableConfig.pageNumber - 1)"></a>
109+
</li>
110+
<li class="footable-page" ng-class="{'active' : item === tableConfig.pageNumber}"
111+
ng-repeat="item in getPageArray()">
112+
<a ng-click="changePage(item)">{{item}}</a>
113+
</li>
114+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === tableConfig.pages}">
115+
<a ng-click="changePage(tableConfig.pageNumber + 1)"></a>
116+
</li>
117+
</ul>
101118
</td>
102119
</tr>
103120
</tfoot>
@@ -108,17 +125,20 @@ <h4>You don't have active projects right now. Please
108125
<uib-tab index="1" heading="Archived Projects" select="getProjects('archived')">
109126
<br />
110127
<div ng-if="isLoaded">
111-
<div ng-show="allProjects.length===0" class="text-center m-t-lg">
128+
<div ng-show="projects.length===0 && !tableConfig.query" class="text-center m-t-lg">
112129
<p>No projects have been archived.</p>
113130
</div>
114-
<div ng-hide="allProjects.length===0">
131+
<div ng-hide="projects.length===0 && !tableConfig.query">
115132
<div class="col-lg-4" style="padding-left: 0px">
116133
<div class="input-group custom-search-form">
117-
<input ng-model="searchText" type="text" class="form-control" placeholder="Find projects" ng-change="onSearchChange(this)">
134+
<input ng-model="tableConfig.query" type="text" class="form-control" placeholder="Find projects" ng-keyup="$event.keyCode == 13 && onSearchIconClicked()">
118135
<span class="input-group-btn">
119136
<button class="btn btn-default" type="button" ng-click="onSearchIconClicked()">
120137
<span class="glyphicon glyphicon-search"></span>
121138
</button>
139+
<button class="btn btn-danger" type="button" ng-click="onSearchReset()">
140+
<span class="glyphicon glyphicon-remove"></span>
141+
</button>
122142
</span>
123143
</div>
124144
</div>
@@ -148,10 +168,24 @@ <h4>You don't have active projects right now. Please
148168
</td>
149169
</tr>
150170
</tbody>
151-
<tfoot ng-hide="searchText">
171+
<tfoot>
152172
<tr>
153-
<td colspan="{{isAdminUser? 5: 4}}">
154-
<ul class="pagination pull-right"></ul>
173+
<td colspan="5">
174+
<ul class="pagination pull-right">
175+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === 1}">
176+
<a ng-click="changePage(1)">«</a>
177+
</li>
178+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === 1}">
179+
<a ng-click="changePage(tableConfig.pageNumber - 1)"></a>
180+
</li>
181+
<li class="footable-page" ng-class="{'active' : item === tableConfig.pageNumber}"
182+
ng-repeat="item in getPageArray()">
183+
<a ng-click="changePage(item)">{{item}}</a>
184+
</li>
185+
<li class="footable-page-arrow" ng-class="{'disabled': tableConfig.pageNumber === tableConfig.pages}">
186+
<a ng-click="changePage(tableConfig.pageNumber + 1)"></a>
187+
</li>
188+
</ul>
155189
</td>
156190
</tr>
157191
</tfoot>

0 commit comments

Comments
 (0)