This commit is contained in:
devezhao-mac 2019-03-03 20:41:19 +08:00
commit b48c5384d2
6 changed files with 275 additions and 61 deletions

View file

@ -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++) {

View file

@ -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);
}
}

View 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;
}

View file

@ -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()
}
}

View file

@ -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>