未验证 提交 dcc68fb9 编写于 作者: 张乐 提交者: GitHub

Merge pull request #2321 from nobodyiam/search-app

search app from backend instead of loading all app and filter in frontend
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.dto.PageDTO;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
......@@ -77,7 +78,16 @@ public class AppController {
} else {
return appService.findByAppIds(Sets.newHashSet(appIds.split(",")));
}
}
@GetMapping("/search")
public PageDTO<App> searchByAppIdOrAppName(@RequestParam(value = "query", required = false) String query,
Pageable pageable) {
if (StringUtils.isEmpty(query)) {
return appService.findAll(pageable);
} else {
return appService.searchByAppIdOrAppName(query, pageable);
}
}
@GetMapping("/by-owner")
......
......@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.App;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
......@@ -21,6 +22,8 @@ public interface AppRepository extends PagingAndSortingRepository<App, Long> {
List<App> findByAppIdIn(Set<String> appIds, Pageable pageable);
Page<App> findByAppIdContainingOrNameContaining(String appId, String name, Pageable pageable);
@Modifying
@Query("UPDATE App SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1")
int deleteApp(String appId, String operator);
......
package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.common.dto.AppDTO;
import com.ctrip.framework.apollo.common.dto.PageDTO;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
......@@ -14,6 +15,7 @@ import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.portal.spi.UserService;
import com.ctrip.framework.apollo.tracer.Tracer;
import com.google.common.collect.Lists;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......@@ -65,6 +67,18 @@ public class AppService {
return Lists.newArrayList((apps));
}
public PageDTO<App> findAll(Pageable pageable) {
Page<App> apps = appRepository.findAll(pageable);
return new PageDTO<>(apps.getContent(), pageable, apps.getTotalElements());
}
public PageDTO<App> searchByAppIdOrAppName(String query, Pageable pageable) {
Page<App> apps = appRepository.findByAppIdContainingOrNameContaining(query, query, pageable);
return new PageDTO<>(apps.getContent(), pageable, apps.getTotalElements());
}
public List<App> findByAppIds(Set<String> appIds) {
return appRepository.findByAppIdIn(appIds);
}
......
......@@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<link rel="stylesheet" type="text/css" href="../vendor/select2/select2.min.css">
<title>比较配置</title>
<style>
.comment-toggle {
......@@ -122,6 +123,7 @@
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<script src="../vendor/select2/select2.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
......
......@@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<link rel="stylesheet" type="text/css" href="../vendor/select2/select2.min.css">
<title>发布历史</title>
</head>
......@@ -246,6 +247,7 @@
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<script src="../vendor/select2/select2.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
......
......@@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<link rel="stylesheet" type="text/css" href="../vendor/select2/select2.min.css">
<title>同步配置</title>
</head>
......@@ -213,6 +214,7 @@
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<script src="../vendor/select2/select2.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
......
......@@ -6,6 +6,7 @@
<!-- styles -->
<link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" href="vendor/select2/select2.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/font-awesome.min.css">
......@@ -115,6 +116,7 @@
<!-- jquery.js -->
<script src="vendor/jquery.min.js" type="text/javascript"></script>
<script src="vendor/select2/select2.min.js" type="text/javascript"></script>
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
......
......@@ -13,105 +13,64 @@ directive_module.directive('apollonav',
scope.pageSetting = setting;
});
scope.sourceApps = [];
scope.copiedApps = [];
AppService.find_apps().then(function (result) {
result.forEach(function (app) {
app.selected = false;
scope.sourceApps.push(app);
});
scope.copiedApps = angular.copy(scope.sourceApps);
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load apps error");
});
scope.searchKey = '';
scope.shouldShowAppList = false;
var selectedApp = {};
scope.selectApp = function (app) {
select(app);
scope.jumpToConfigPage();
};
scope.changeSearchKey = function () {
scope.copiedApps = [];
var searchKey = scope.searchKey.toLocaleLowerCase();
scope.sourceApps.forEach(function (app) {
if (app.name.toLocaleLowerCase().indexOf(searchKey) > -1
|| app.appId.toLocaleLowerCase().indexOf(searchKey) > -1) {
scope.copiedApps.push(app);
}
});
scope.shouldShowAppList = true;
};
scope.jumpToConfigPage = function () {
if (selectedApp.appId) {
if ($window.location.href.indexOf("config.html") > -1) {
$window.location.hash = "appid=" + selectedApp.appId;
$window.location.reload();
} else {
$window.location.href = '/config.html?#appid=' + selectedApp.appId;
}
}
};
$('#app-search-list').select2({
placeholder: '搜索项目(AppId、项目名)',
ajax: {
url: "/apps/search",
dataType: 'json',
delay: 400,
data: function (params) {
return {
query: params.term || '',
page: params.page ? params.page - 1 : 0,
size: 20
};
},
processResults: function (data) {
if (data && data.content) {
var hasMore = data.content.length
=== data.size;
var result = [];
data.content.forEach(function (app) {
result.push({
id: app.appId,
text: app.appId + ' / ' + app.name
})
});
return {
results: result,
pagination: {
more: hasMore
}
};
} else {
return {
results: [],
pagination: {
more: false
}
};
}
//up:38 down:40 enter:13
var selectedAppIdx = -1;
element.bind("keydown keypress", function (event) {
if (event.keyCode == 40) {
if (selectedAppIdx < scope.copiedApps.length - 1) {
clearAppsSelectedStatus();
scope.copiedApps[++selectedAppIdx].selected = true;
}
} else if (event.keyCode == 38) {
if (selectedAppIdx >= 1) {
clearAppsSelectedStatus();
scope.copiedApps[--selectedAppIdx].selected = true;
}
} else if (event.keyCode == 13) {
if (scope.shouldShowAppList && selectedAppIdx > -1) {
select(scope.copiedApps[selectedAppIdx]);
event.preventDefault();
} else {
scope.jumpToConfigPage();
}
}
//强制刷新
scope.$apply(function () {
scope.copiedApps = scope.copiedApps;
});
});
$(".search-input").on("click", function (event) {
event.stopPropagation();
});
$(document).on('click', function () {
scope.$apply(function () {
scope.shouldShowAppList = false;
});
$('#app-search-list').on('select2:select', function () {
var selected = $('#app-search-list').select2('data');
if (selected && selected.length) {
jumpToConfigPage(selected[0].id)
}
});
function clearAppsSelectedStatus() {
scope.copiedApps.forEach(function (app) {
app.selected = false;
})
}
function select(app) {
selectedApp = app;
scope.searchKey = app.name;
scope.shouldShowAppList = false;
clearAppsSelectedStatus();
selectedAppIdx = -1;
}
function jumpToConfigPage(selectedAppId) {
if ($window.location.href.indexOf("config.html") > -1) {
$window.location.hash = "appid=" + selectedAppId;
$window.location.reload();
} else {
$window.location.href = '/config.html?#appid=' + selectedAppId;
}
};
UserService.load_user().then(function (result) {
scope.userName = result.userId;
......
......@@ -6,6 +6,7 @@
<!-- styles -->
<link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" href="vendor/select2/select2.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="styles/common-style.css">
<title>应用配置</title>
......@@ -81,6 +82,7 @@
<!-- jquery.js -->
<script src="vendor/jquery.min.js" type="text/javascript"></script>
<script src="vendor/select2/select2.min.js" type="text/javascript"></script>
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
......
......@@ -805,3 +805,11 @@ table th {
padding-left: 30px;
}
.app-search-list .select2-container, .app-search-list .select2-container .select2-selection {
height: 34px;
}
.app-search-list .select2-container .select2-selection .select2-selection__rendered {
line-height: 34px;
font-size: 14px;
}
\ No newline at end of file
......@@ -49,19 +49,10 @@
</ul>
<div class="navbar-form navbar-right form-inline" role="search">
<div class="form-group">
<input type="text" class="form-control search-input" placeholder="搜索项目(AppId、项目名)"
style="width: 350px"
ng-model="searchKey" ng-change="changeSearchKey()" ng-focus="changeSearchKey()">
<div class="row app-list" ng-show="shouldShowAppList">
<div ng-repeat="app in copiedApps" class="app-item" ng-class="{'app-selected':app.selected}"
ng-click="selectApp(app)">{{app.appId}} / {{app.name}}
</div>
</div>
<div class="form-group app-search-list">
<select id="app-search-list" style="width: 350px"></select>
</div>
</div>
</div>
</div>
</nav>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册