Browse Source

Pull request #9506: REPORT-72635 - 数据连接面板为空的问题(含控制权限)

Merge in DESIGN/design from ~YVAN/design:feature/x to feature/x

* commit '87123b36be35e84d22c66f5b27ceb51aed58540a':
  REPORT-72635 - 数据连接面板为空的问题(含控制权限) 【问题原因】迭代任务,问题与改动思路详见https://kms.fineres.com/pages/viewpage.action?pageId=443822299 【改动思路】同上 【review建议】无
feature/x
Yvan 2 years ago
parent
commit
af48da234d
  1. 51
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  2. 40
      designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java
  3. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  4. 100
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  5. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  6. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  7. 23
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java
  8. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java
  9. 45
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java

51
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -13,6 +13,7 @@ import com.fr.design.data.BasicTableDataTreePane;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.StrategyConfigAttrUtils;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.datapane.management.clip.TableDataTreeClipboard;
import com.fr.design.data.datapane.management.search.pane.TableDataSearchRemindPane;
import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane;
@ -22,6 +23,7 @@ import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
@ -39,7 +41,6 @@ import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.i18n.Toolkit;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.LineSeparator;
@ -87,6 +88,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -1017,10 +1019,57 @@ public class TableDataTreePane extends BasicTableDataTreePane {
AbstractTableDataPane<?> tableDataPane = wrapper.creatTableDataPane();
String tableDataName = wrapper.getTableDataName();
if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) {
// 先打开一个Loading面板
TableDataLoadingPane loadingPane = new TableDataLoadingPane();
BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() {
@Override
public void doOk() {
super.doOk();
}
@Override
public void doCancel() {
super.doCancel();
}
});
loadingDialog.setVisible(true);
// 查询权限
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
Collection<String> noAuthConnections = TableDataAuthHelper.getNoAuthConnections();
return !noAuthConnections.contains(tableDataName);
}
@Override
protected void done() {
try {
Boolean hasAuth = get();
if (hasAuth) {
// 有权限时,关闭Loading面板,打开编辑面板
loadingDialog.setVisible(false);
dgEdit(tableDataPane, dsName, false);
} else {
// 无权限时,给出无权限提示
loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage());
// 查询权限失败时,给出报错提示
loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME);
}
}
}.execute();
} else {
// 无需检查权限时,直接打开数据库查询编辑面板
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
}
}
}
private class RemoveAction extends UpdateAction {

40
designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java

@ -0,0 +1,40 @@
package com.fr.design.data.datapane.auth;
import com.fr.base.TableData;
import com.fr.data.impl.DBTableData;
import com.fr.decision.base.util.CollectionUtil;
import com.fr.stable.collections.CollectionUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import javax.swing.SwingWorker;
import java.util.Collection;
import java.util.Collections;
/**
* 数据连接权限相关的工具类
* @author Yvan
*/
public class TableDataAuthHelper {
/**
* 编辑数据集时是否需要检查权限
* @param tableData
* @return
*/
public static boolean needCheckAuthWhenEdit(TableData tableData) {
// 远程设计下,编辑DBTableData时需要判断权限
return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData;
}
/**
* 获取无权限数据连接集合
* 远程下需要调用RPC为耗时操作谨慎使用
* @return
*/
public static Collection<String> getNoAuthConnections() {
// 获取无权限连接集合
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections();
return noAuthConnections == null ? Collections.emptyList() : noAuthConnections;
}
}

16
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -138,6 +138,14 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
if (connection instanceof NameDatabaseConnection) {
this.setSelectedItem(((NameDatabaseConnection) connection).getName());
} else {
setRecentConnection();
}
}
/**
* 下拉框选项设置成最近选择的connection如果最近选择不存在则选择列表中的第一个
*/
protected void setRecentConnection() {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isNotBlank(s)) {
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
@ -151,5 +159,13 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
this.setSelectedItem(this.getConnection(0));
}
}
/**
* 是否无选中状态空白item也视为无选中
* @return
*/
protected boolean isSelectedItemEmpty() {
String selectedItem = this.getSelectedItem();
return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString());
}
}

100
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java

@ -1,26 +1,32 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.AbstractDatabaseConnection;
import com.fr.data.impl.Connection;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.TableViewList;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.GeneralContext;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -45,7 +51,39 @@ public class ConnectionTableProcedurePane extends BasicPane {
private java.util.List<DoubleClickSelectedNodeOnTreeListener> listeners = new java.util.ArrayList<DoubleClickSelectedNodeOnTreeListener>();
public ConnectionTableProcedurePane() {
init(null);
}
/**
* 传入父容器
* @param parent
*/
public ConnectionTableProcedurePane(SwitchableTableDataPane parent) {
init(parent);
}
private void init(SwitchableTableDataPane parent) {
this.setLayout(new BorderLayout(4, 4));
// 初始化数据连接下拉框
initConnectionComboBox(parent);
// 初始化中间的面板
JPanel centerPane = initCenterPane();
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
}
private JPanel initCenterPane() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// 搜索面板
centerPane.add(createSearchPane(), BorderLayout.NORTH);
// 数据库表视图面板
centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER);
return centerPane;
}
private void initConnectionComboBox(SwitchableTableDataPane parent) {
connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) {
@Override
@ -60,10 +98,34 @@ public class ConnectionTableProcedurePane extends BasicPane {
search(true);
}
}
@Override
protected void afterRefreshItems() {
// 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置
if (isSelectedItemEmpty()) {
setRecentConnection();
}
// 获取数据连接之后,让父容器切换面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
@Override
protected void refreshItemsError() {
// 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
};
connectionComboBox.addComboBoxActionListener(filter);
}
private JPanel createTableViewBorderPane() {
tableViewList = new TableViewList();
ToolTipManager.sharedInstance().registerComponent(tableViewList);
connectionComboBox.addComboBoxActionListener(filter);
tableViewList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() >= 2) {
@ -80,23 +142,37 @@ public class ConnectionTableProcedurePane extends BasicPane {
}
}
});
JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER);
JPanel checkBoxgroupPane = createCheckBoxgroupPane();
if (checkBoxgroupPane != null) {
filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH);
tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH);
}
return tableViewBorderPane;
}
/**
* 创建搜索Panel用于搜索表或视图
* @return
*/
private JPanel createSearchPane() {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel searchPane = new JPanel(new BorderLayout(10, 0));
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.setBackground(Color.WHITE);
searchField = new UITextField();
searchPane.add(searchField, BorderLayout.CENTER);
searchField.setBorderPainted(false);
searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search"));
searchField.getDocument().addDocumentListener(searchListener);
filterPane.add(searchPane, BorderLayout.CENTER);
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(tableViewListPane, BorderLayout.CENTER);
this.add(filterPane, BorderLayout.SOUTH);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
// 搜索图标
UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search"));
searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
searchPane.add(searchField, BorderLayout.CENTER);
searchPane.add(searchLabel, BorderLayout.EAST);
panel.add(searchPane, BorderLayout.CENTER);
return panel;
}
protected void filter(Connection connection, String conName, List<String> nameList) {

16
designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java

@ -127,10 +127,12 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1);
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1);
}
afterRefreshItems();
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
refreshItemsError();
}
}
@ -160,6 +162,20 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
*/
protected abstract java.util.Iterator<String> items();
/**
* 刷新ComboBox.items之后
*/
protected void afterRefreshItems() {
// 空实现,供子类重写
}
/**
* 刷新ComboBox.items时出现异常
*/
protected void refreshItemsError() {
// 空实现,供子类重写
}
/*
* 弹出对话框编辑Items
*/

54
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -20,6 +20,8 @@ import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane;
import com.fr.design.data.datapane.sqlpane.SQLEditPane;
import com.fr.design.data.tabledata.strategy.StrategyConfigHandler;
import com.fr.design.data.tabledata.tabledatapane.db.StrategyConfigFrom;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
@ -36,6 +38,7 @@ import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
@ -70,6 +73,7 @@ import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
@ -86,7 +90,7 @@ import java.util.List;
* @version 10.0
* Created by rinoux on 2020/7/22
*/
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implements SwitchableTableDataPane {
private static final int BOTTOM = 6;
private static final String PREVIEW_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Preview");
@ -109,14 +113,42 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
private StrategyConfigHandler<DBTableData> configHandler;
private CardLayout card;
/** 数据库查询面板真正的内容面板 */
private JPanel contentPane;
/** 加载中面板 */
private JPanel loadingPane;
public DBTableDataPane() {
initCards();
initContentPane();
}
/**
* 初始化内容面板
*/
protected void initContentPane() {
init();
initMainSplitPane();
}
/**
* 初始化cardLayout以及LoadingPane等并且布局切到LoadingPane
*/
protected void initCards() {
card = new CardLayout();
setLayout(card);
loadingPane = new TipsPane(true);
contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
add(LOADING_PANE_NAME, loadingPane);
add(CONTENT_PANE_NAME, contentPane);
switchTo(LOADING_PANE_NAME);
}
private void init() {
setLayout(new BorderLayout(4, 4));
contentPane.setLayout(new BorderLayout(4, 4));
this.sqlTextPane = new SQLEditPane();
this.sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
@ -130,7 +162,7 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
editorPane = new UITableEditorPane<>(model);
this.connectionTableProcedurePane = new ConnectionTableProcedurePane() {
this.connectionTableProcedurePane = new ConnectionTableProcedurePane(this) {
@Override
protected void filter(Connection connection, String conName, List<String> nameList) {
connection.addConnection(nameList, conName, new Class[]{
@ -231,7 +263,21 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.connectionTableProcedurePane, sqlSplitPane);
mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor()));
mainSplitPane.setOneTouchExpandable(true);
add(mainSplitPane, BorderLayout.CENTER);
contentPane.add(mainSplitPane, BorderLayout.CENTER);
}
@Override
public void switchTo(String panelName) {
try {
if (panelName != null) {
card.show(this, panelName);
}
} catch (IllegalArgumentException ingore) {
// 有些直接继承此面板或者替换掉此面板的插件,在未适配此功能时会出现报错,因为不是CardLayout,无法切换,这里处理下
FineLoggerFactory.getLogger().info("cannot switch pane by {}", this.getClass().getName());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean isPreviewOrRefreshButton(FocusEvent e) {

23
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java

@ -0,0 +1,23 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
/**
* 可切换的DBTableData对应的数据集面板需要使用CardLayout布局
* 主要是给插件适配用的
* @author Yvan
*/
public interface SwitchableTableDataPane {
/** Loading面板 */
String LOADING_PANE_NAME = "Loading";
/** 内容面板 */
String CONTENT_PANE_NAME = "Content";
/**
* 根据面板名称切换面板
* @param paneName 面板名称
*/
void switchTo(String paneName);
}

54
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java

@ -0,0 +1,54 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.dialog.BasicPane;
import com.fr.design.i18n.Toolkit;
import javax.swing.JPanel;
import java.awt.CardLayout;
/**
* @author Yvan
*/
public class TableDataLoadingPane extends BasicPane {
/** Loading面板 */
public static final String LOADING_PANE_NAME = "Loading";
/** 无权限提示面板 */
public static final String NO_AUTH_PANE_NAME = "NoAuthority";
/** 错误提示面板 */
public static final String ERROR_NAME = "Error";
private CardLayout card;
/** 加载中面板 */
private JPanel loadingPane;
/** 错误提示面板 */
private JPanel errorPane;
/** 数据连接无权限面板 */
private JPanel noAuthorityPane;
public TableDataLoadingPane() {
initPanes();
}
private void initPanes() {
card = new CardLayout();
this.setLayout(card);
loadingPane = new TipsPane(true);
errorPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Error"));
noAuthorityPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_No_Auth"));
add(LOADING_PANE_NAME, loadingPane);
add(NO_AUTH_PANE_NAME, noAuthorityPane);
add(ERROR_NAME, errorPane);
switchTo(LOADING_PANE_NAME);
}
public void switchTo(String panelName) {
card.show(this, panelName);
}
@Override
protected String title4PopupWindow() {
return "数据集查询";
}
}

45
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java

@ -0,0 +1,45 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
/**
* 提示面板支持自定义提示支持进度条配置可选
* @author Yvan
*/
public class TipsPane extends JPanel {
/**
* 默认提示
*/
private static final String LOADING = Toolkit.i18nText("Fine-Design_Basic_Loading_And_Waiting");
public TipsPane () {
this(LOADING, false);
}
public TipsPane (String tip) {
this(tip, false);
}
public TipsPane (boolean needProgressBar) {
this(LOADING, needProgressBar);
}
public TipsPane (String tips, boolean needProgressBar) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
UILabel tipsLabel = new UILabel(tips, SwingConstants.CENTER);
this.add(tipsLabel, BorderLayout.CENTER);
if (needProgressBar) {
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
this.add(progressBar, BorderLayout.SOUTH);
}
}
}
Loading…
Cancel
Save