mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
Merge branch 'dev' of https://github.com/getrebuild/rebuild into dev
This commit is contained in:
commit
b48c5384d2
|
@ -25,6 +25,7 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rebuild.server.Application;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
import com.rebuild.server.service.bizz.RoleService;
|
||||
import com.rebuild.server.service.bizz.UserHelper;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
|
||||
|
@ -46,23 +47,25 @@ public class DashboardManager extends SharableManager {
|
|||
* @return
|
||||
*/
|
||||
public static JSON getDashList(ID user) {
|
||||
ID configUsed = detectUseConfig(user, "DashboardConfig");
|
||||
|
||||
ID configHas = detectUseConfig(user, "DashboardConfig");
|
||||
// 没有就初始化一个
|
||||
if (configUsed == null) {
|
||||
if (configHas == null) {
|
||||
Record record = EntityHelper.forNew(EntityHelper.DashboardConfig, user);
|
||||
record.setString("config", JSONUtils.EMPTY_ARRAY_STR);
|
||||
record.setString("title", "默认仪表盘");
|
||||
record.setString("title", UserHelper.isAdmin(user) ? "默认仪表盘" : "我的仪表盘");
|
||||
record.setString("shareTo", UserHelper.isAdmin(user) ? SHARE_ALL : SHARE_SELF);
|
||||
record = Application.getCommonService().create(record);
|
||||
configUsed = record.getPrimary();
|
||||
configHas = record.getPrimary();
|
||||
}
|
||||
|
||||
// TODO 多个仪表盘 ???
|
||||
Object[][] array = Application.createQueryNoFilter(
|
||||
"select configId,title,config,createdBy,shareTo from DashboardConfig where configId = ?")
|
||||
.setParameter(1, configUsed)
|
||||
.array();
|
||||
String sql = "select configId,title,config,createdBy,shareTo from DashboardConfig where ";
|
||||
if (UserHelper.isAdmin(user)) {
|
||||
sql += String.format("createdBy.roleId = '%s'", RoleService.ADMIN_ROLE.toLiteral());
|
||||
} else {
|
||||
sql += String.format("createdBy = '%s' or shareTo = 'ALL'", user.toLiteral());
|
||||
}
|
||||
sql += " order by title asc";
|
||||
Object[][] array = Application.createQueryNoFilter(sql).array();
|
||||
|
||||
// 补充图表标题
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.rebuild.server.Application;
|
||||
import com.rebuild.server.helper.manager.DashboardManager;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
import com.rebuild.server.service.bizz.UserHelper;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import com.rebuild.web.BasePageControll;
|
||||
|
||||
|
@ -95,11 +96,13 @@ public class DashboardControll extends BasePageControll {
|
|||
JSONObject item = (JSONObject) o;
|
||||
String chartId = item.getString("chart");
|
||||
Record chart = Application.createQueryNoFilter(
|
||||
"select belongEntity,type,title,config,createdBy from ChartConfig where chartId = ?")
|
||||
"select config,belongEntity,chartType,title,createdBy from ChartConfig where chartId = ?")
|
||||
.setParameter(1, ID.valueOf(chartId))
|
||||
.record();
|
||||
// 自己的直接使用
|
||||
if (user.equals(chart.getID("createdBy"))) {
|
||||
ID createdBy = chart.getID("createdBy");
|
||||
if (user.equals(createdBy)
|
||||
|| (UserHelper.isAdmin(createdBy) && UserHelper.isAdmin(user))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -137,4 +140,18 @@ public class DashboardControll extends BasePageControll {
|
|||
Application.getCommonService().update(record);
|
||||
writeSuccess(response);
|
||||
}
|
||||
|
||||
@RequestMapping("/dash-delete")
|
||||
public void dashDelete(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
ID dashid = getIdParameterNotNull(request, "id");
|
||||
ID user = getRequestUser(request);
|
||||
|
||||
if (!DashboardManager.allowedUpdate(user, dashid)) {
|
||||
writeFailure(response, "无权删除他人的仪表盘");
|
||||
return;
|
||||
}
|
||||
|
||||
Application.getCommonService().delete(dashid);
|
||||
writeSuccess(response);
|
||||
}
|
||||
}
|
||||
|
|
113
src/main/webapp/assets/css/dashboard.css
Normal file
113
src/main/webapp/assets/css/dashboard.css
Normal file
|
@ -0,0 +1,113 @@
|
|||
.gridster ul,
|
||||
.gridster ul>li {
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
.gridster ul>li {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.gridster ul>li>div {
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.gridster ul>li:hover {
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1), 0 16px 24px 0 rgba(81, 129, 228, .1)
|
||||
}
|
||||
|
||||
.gridster ul>li:hover .chart-oper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tools-bar {
|
||||
height: 44px;
|
||||
padding: 0 25px;
|
||||
padding-top: 7px
|
||||
}
|
||||
|
||||
.tools-bar h4 {
|
||||
margin: 10px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tools-bar h4:hover {
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
.chart-grid {
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
padding: 15px;
|
||||
padding-top: 0;
|
||||
padding-right: 0px
|
||||
}
|
||||
|
||||
.chart-add {
|
||||
display: block;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.chart-add i.zmdi {
|
||||
font-size: 71px;
|
||||
color: #ddd;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.dash-list .dash-head {
|
||||
display: inline-block;
|
||||
padding-right: 71px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dash-head .dash-action {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding-top: 9px;
|
||||
padding-left: 6px;
|
||||
display: none;
|
||||
text-align: left;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.dash-head:hover .dash-action {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dash-head .dash-action a {
|
||||
padding: 3px;
|
||||
margin-left: 3px
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog {
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog ul li+li {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog ul li a {
|
||||
display: block;
|
||||
border: 1px solid #eee;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog ul li a>.icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog ul li a:hover {
|
||||
color: #fff;
|
||||
background-color: #4285f4
|
||||
}
|
||||
|
||||
.dlg-dash-select .modal-dialog ul li a:hover>.icon {
|
||||
float: right;
|
||||
font-size: 1.3rem;
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable react/prop-types */
|
||||
/* eslint-disable react/no-string-refs */
|
||||
// $Id$
|
||||
let dashid = null
|
||||
let dash_editable = false
|
||||
$(document).ready(function () {
|
||||
|
@ -8,8 +8,10 @@ $(document).ready(function () {
|
|||
let d = $urlp('d')
|
||||
if (d) $storage.set('DashDefault', d)
|
||||
|
||||
let dash_list = null
|
||||
$.get(rb.baseUrl + '/dashboard/dash-gets', ((res) => {
|
||||
let d = res.data[0] // default
|
||||
dash_list = res.data
|
||||
let d = dash_list[0] // default
|
||||
if (res.data.length > 1) {
|
||||
let dset = $storage.get('DashDefault')
|
||||
if (dset) {
|
||||
|
@ -27,23 +29,25 @@ $(document).ready(function () {
|
|||
render_dashboard(d[2])
|
||||
$('.dash-list h4').text(d[1])
|
||||
|
||||
if (location.hash) {
|
||||
if (location.hash && location.hash.length > 20) {
|
||||
if (location.hash.substr(0, 5) === '#del=') {
|
||||
rb.hbsuccess('仪表盘已删除')
|
||||
location.hash = ''
|
||||
} else {
|
||||
let high = $('#chart-' + location.hash.substr(1) + ' > .chart-box').addClass('high')
|
||||
high.on('mouseleave', () => {
|
||||
high.removeClass('high')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 仅开放一个仪表盘
|
||||
if (dash_editable) $('.J_dash-new').remove()
|
||||
else $('.J_dash-edit, .J_chart-adds').remove()
|
||||
if (dash_editable !== true) $('.J_dash-edit, .J_chart-adds').remove()
|
||||
|
||||
$('.J_dash-new').click(() => { show_dlg('DlgDashAdd') })
|
||||
$('.J_dash-edit').click(() => { show_dlg('DlgDashSettings', { title: d[1], shareToAll: d[4] === 'ALL' }) })
|
||||
$('.J_chart-new').click(() => { show_dlg('DlgAddChart') })
|
||||
// TODO
|
||||
$('.J_dash-select').click(() => { })
|
||||
$('.J_chart-select').click(() => { })
|
||||
$('.J_dash-select').click(() => { show_dlg('DashSelect', { dashList: dash_list }) })
|
||||
$('.J_chart-select').click(() => { show_dlg('ChartSelect', { dlgClazz: 'dlg-chart-select', dlgTitle: '选择图表' }) })
|
||||
}))
|
||||
})
|
||||
let rendered_charts = []
|
||||
|
@ -62,6 +66,8 @@ const show_dlg = (t, props) => {
|
|||
else if (t === 'DlgAddChart') dlg_cached[t] = renderRbcomp(<DlgAddChart {...props} />)
|
||||
else if (t === 'DlgDashAdd') dlg_cached[t] = renderRbcomp(<DlgDashAdd {...props} />)
|
||||
else if (t === 'DlgDashSettings') dlg_cached[t] = renderRbcomp(<DlgDashSettings {...props} />)
|
||||
else if (t === 'DashSelect') dlg_cached[t] = renderRbcomp(<DashSelect {...props} />)
|
||||
else if (t === 'ChartSelect') dlg_cached[t] = renderRbcomp(<ChartSelect {...props} />)
|
||||
}
|
||||
|
||||
let gridster = null
|
||||
|
@ -172,6 +178,7 @@ class DlgAddChart extends RbFormHandler {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class DlgDashSettings extends RbFormHandler {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
@ -185,6 +192,7 @@ class DlgDashSettings extends RbFormHandler {
|
|||
<input className="form-control form-control-sm" value={this.state.title || ''} placeholder="默认仪表盘" data-id="title" onChange={this.handleChange} maxLength="40" />
|
||||
</div>
|
||||
</div>
|
||||
{rb.isAdminUser !== true ? null :
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div className="col-sm-7">
|
||||
|
@ -194,25 +202,40 @@ class DlgDashSettings extends RbFormHandler {
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="form-group row footer">
|
||||
<div className="col-sm-7 offset-sm-3">
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.save()}>确定</button>
|
||||
<button className="btn btn-primary btn-space" type="button" onClick={() => this.save()}>确定</button>
|
||||
<button className="btn btn-secondary btn-space" type="button" onClick={() => this.delete()}><i className="zmdi zmdi-delete icon" /> 删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</RbModal>)
|
||||
</RbModal >)
|
||||
}
|
||||
save() {
|
||||
let _data = { shareTo: this.state.shareToAll === true ? 'ALL' : 'SELF', title: this.state.title || '默认仪表盘' }
|
||||
_data.metadata = { id: this.props.dashid, entity: 'DashboardConfig' }
|
||||
$.post(rb.baseUrl + '/dashboard/dash-update', JSON.stringify(_data), (res) => {
|
||||
if (res.error_code === 0) {
|
||||
rb.hbsuccess('设置已保存')
|
||||
// rb.hbsuccess('设置已保存')
|
||||
$('.dash-head h4').text(_data.title)
|
||||
if (dlg_cached['DashSelect']) {
|
||||
dlg_cached['DashSelect'].setState({ 'dashTitle': _data.title })
|
||||
}
|
||||
this.hide()
|
||||
} else rb.hberror(res.error_msg)
|
||||
})
|
||||
}
|
||||
delete() {
|
||||
rb.alert('确认删除此仪表盘?', {
|
||||
confirm: function () {
|
||||
$.post(rb.baseUrl + '/dashboard/dash-delete?id=' + dashid, function (res) {
|
||||
if (res.error_code === 0) location.replace('home#del=' + dashid)
|
||||
else rb.hberror(res.error_msg)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class DlgDashAdd extends RbFormHandler {
|
||||
|
@ -257,3 +280,76 @@ class DlgDashAdd extends RbFormHandler {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
class DashPanel extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={'modal ' + (this.props.dlgClazz || 'dlg-dash-select')} ref="dlg" tabIndex="-1">
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header pb-0">
|
||||
<h4>{this.props.dlgTitle || ''}</h4>
|
||||
<button className="close" type="button" onClick={() => this.hide()}><span className="zmdi zmdi-close" /></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{this.renderPanel()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
renderPanel() {
|
||||
return (<ul className="list-unstyled">
|
||||
{(this.props.dashList || []).map((item) => {
|
||||
let title = item[1]
|
||||
if (item[0] === dashid) title = this.state.dashTitle || $('.dash-head h4').text() || title
|
||||
return <li key={'dash-' + item[0]}><a href={'?d=' + item[0]}>{title}<i className="icon zmdi zmdi-arrow-right"></i></a></li>
|
||||
})}
|
||||
</ul>)
|
||||
}
|
||||
componentDidMount() {
|
||||
this.show()
|
||||
}
|
||||
hide() {
|
||||
$(this.refs['dlg']).modal('hide')
|
||||
}
|
||||
show() {
|
||||
$(this.refs['dlg']).modal({ show: true, keyboard: true })
|
||||
}
|
||||
}
|
||||
|
||||
class DashSelect extends DashPanel {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = { dashTitle: null }
|
||||
}
|
||||
renderPanel() {
|
||||
return (
|
||||
<ul className="list-unstyled">
|
||||
{(this.props.dashList || []).map((item) => {
|
||||
let title = item[1]
|
||||
if (item[0] === dashid) title = this.state.dashTitle || $('.dash-head h4').text() || title
|
||||
return <li key={'dash-' + item[0]}><a href={'?d=' + item[0]}>{title}<i className="icon zmdi zmdi-arrow-right"></i></a></li>
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 从已有图表中选择图表
|
||||
// 添加的图表会在多个仪表盘共享(本身就是一个),修改时会同步修改
|
||||
class ChartSelect extends DashPanel {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
renderPanel() {
|
||||
return (<a>TODO</a>)
|
||||
}
|
||||
componentDidMount() {
|
||||
super.componentDidMount()
|
||||
}
|
||||
}
|
|
@ -6,22 +6,7 @@
|
|||
<title>首页</title>
|
||||
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/charts/jquery.gridster.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/css/charts.css">
|
||||
<style type="text/css">
|
||||
.gridster ul,.gridster ul>li{margin:0;padding:0}
|
||||
.gridster ul>li{background-color:#fff;}
|
||||
.gridster ul>li>div{height:100%}
|
||||
.gridster ul>li:hover{box-shadow:0 2px 4px 0 rgba(0, 0, 0, .1), 0 16px 24px 0 rgba(81, 129, 228, .1)}
|
||||
.gridster ul>li:hover .chart-oper{display:block;}
|
||||
.tools-bar{height:44px;padding:0 25px;padding-top:7px}
|
||||
.tools-bar h4{margin:10px 0}
|
||||
.chart-grid{overflow:scroll;overflow-x:hidden;padding:15px;padding-top:0;padding-right:0px}
|
||||
.chart-add{display:block;text-align:center;height:100%;padding-top:50px;}
|
||||
.chart-add i.zmdi{font-size:71px;color:#ddd;font-weight:lighter;}
|
||||
.dash-list .dash-head{display:inline-block;padding-right:71px;position:relative;}
|
||||
.dash-head .dash-action{position:absolute;top:0;right:0;padding-top:9px;padding-left:6px;display:none;text-align:left;width:70px;}
|
||||
.dash-head:hover .dash-action{display:block;}
|
||||
.dash-head .dash-action a{padding:3px;margin-left:3px}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/css/dashboard.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="rb-wrapper rb-fixed-sidebar rb-collapsible-sidebar rb-collapsible-sidebar-hide-logo">
|
||||
|
@ -40,7 +25,7 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-6 dash-list">
|
||||
<div class="dash-head">
|
||||
<h4 class="J_dash-select">仪表盘</h4>
|
||||
<h4 class="J_dash-select hover">仪表盘</h4>
|
||||
<div class="dash-action">
|
||||
<a class="zicon J_dash-edit"><i class="zmdi zmdi-settings"></i></a>
|
||||
<a class="zicon J_dash-new" title="添加仪表盘"><i class="zmdi zmdi-plus-circle-o"></i></a>
|
||||
|
|
Loading…
Reference in a new issue