IDEMPIERE-3562 Timeline view of record changes.
This commit is contained in:
parent
6265a1bc5c
commit
e65edd9e51
|
@ -0,0 +1,11 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-3562 Timeline view of record changes
|
||||
-- Mar 28, 2019, 3:57:53 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Time Line',0,0,'Y',TO_DATE('2019-03-28 15:57:52','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-28 15:57:52','YYYY-MM-DD HH24:MI:SS'),100,200491,'TimeLine','D','744a1b33-8052-457e-b763-73a75d7b4d52')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201903281500_IDEMPIERE-3562.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-- IDEMPIERE-3562 Timeline view of record changes
|
||||
-- Mar 28, 2019, 3:57:53 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Time Line',0,0,'Y',TO_TIMESTAMP('2019-03-28 15:57:52','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-28 15:57:52','YYYY-MM-DD HH24:MI:SS'),100,200491,'TimeLine','D','744a1b33-8052-457e-b763-73a75d7b4d52')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201903281500_IDEMPIERE-3562.sql') FROM dual
|
||||
;
|
||||
|
|
@ -131,6 +131,7 @@ public class SystemIDs
|
|||
|
||||
public final static int REFERENCE_AD_USER = 110;
|
||||
public final static int REFERENCE_DOCUMENTACTION = 135;
|
||||
public final static int REFERENCE_DOCUMENTSTATUS = 131;
|
||||
public final static int REFERENCE_PAYMENTRULE = 195;
|
||||
public final static int REFERENCE_POSTING_TYPE = 125;
|
||||
public final static int REFERENCE_POSTED = 234;
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.compiere.model.MRMA;
|
|||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.SystemIDs;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
|
@ -1354,4 +1355,62 @@ public class DocumentEngine implements DocAction
|
|||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill Vector with DocAction Ref_List(131) values
|
||||
* @param v_value
|
||||
* @param v_name
|
||||
* @param v_description
|
||||
*/
|
||||
public static void readStatusReferenceList(ArrayList<String> v_value, ArrayList<String> v_name,
|
||||
ArrayList<String> v_description)
|
||||
{
|
||||
if (v_value == null)
|
||||
throw new IllegalArgumentException("v_value parameter is null");
|
||||
if (v_name == null)
|
||||
throw new IllegalArgumentException("v_name parameter is null");
|
||||
if (v_description == null)
|
||||
throw new IllegalArgumentException("v_description parameter is null");
|
||||
|
||||
String sql;
|
||||
if (Env.isBaseLanguage(Env.getCtx(), "AD_Ref_List"))
|
||||
sql = "SELECT Value, Name, Description FROM AD_Ref_List "
|
||||
+ "WHERE AD_Reference_ID=? ORDER BY Name";
|
||||
else
|
||||
sql = "SELECT l.Value, t.Name, t.Description "
|
||||
+ "FROM AD_Ref_List l, AD_Ref_List_Trl t "
|
||||
+ "WHERE l.AD_Ref_List_ID=t.AD_Ref_List_ID"
|
||||
+ " AND t.AD_Language='" + Env.getAD_Language(Env.getCtx()) + "'"
|
||||
+ " AND l.AD_Reference_ID=? ORDER BY t.Name";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql, null);
|
||||
pstmt.setInt(1, SystemIDs.REFERENCE_DOCUMENTSTATUS);
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
{
|
||||
String value = rs.getString(1);
|
||||
String name = rs.getString(2);
|
||||
String description = rs.getString(3);
|
||||
if (description == null)
|
||||
description = "";
|
||||
//
|
||||
v_value.add(value);
|
||||
v_name.add(name);
|
||||
v_description.add(description);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
log.log(Level.SEVERE, sql, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
}
|
||||
} // DocumentEnine
|
||||
|
|
|
@ -1390,7 +1390,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
|||
if (logger.isLoggable(Level.INFO)) logger.info(dbInfo);
|
||||
if (adTabbox.getSelectedGridTab() != null && adTabbox.getSelectedGridTab().isQueryActive())
|
||||
dbInfo = "[ " + dbInfo + " ]";
|
||||
breadCrumb.setStatusDB(dbInfo, e);
|
||||
breadCrumb.setStatusDB(dbInfo, e, adTabbox.getSelectedGridTab());
|
||||
|
||||
String adInfo = e.getAD_Message();
|
||||
if ( adInfo == null
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.adempiere.webui.theme.ThemeManager;
|
|||
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||
import org.adempiere.webui.window.WRecordInfo;
|
||||
import org.compiere.model.DataStatusEvent;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
|
@ -88,6 +89,8 @@ public class BreadCrumb extends Div implements EventListener<Event> {
|
|||
|
||||
protected Menupopup linkPopup;
|
||||
|
||||
private GridTab m_gridTab;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -300,7 +303,7 @@ public class BreadCrumb extends Div implements EventListener<Event> {
|
|||
return;
|
||||
|
||||
String title = Msg.getMsg(Env.getCtx(), "Who") + m_text;
|
||||
new WRecordInfo (title, m_dse);
|
||||
new WRecordInfo (title, m_dse, m_gridTab);
|
||||
} else if (event.getTarget() == btnFirst) {
|
||||
if (toolbarListener != null)
|
||||
toolbarListener.onFirst();
|
||||
|
@ -409,14 +412,15 @@ public class BreadCrumb extends Div implements EventListener<Event> {
|
|||
*/
|
||||
public void setStatusDB (String text)
|
||||
{
|
||||
setStatusDB(text, null);
|
||||
setStatusDB(text, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text
|
||||
* @param dse
|
||||
* @param gridTab
|
||||
*/
|
||||
public void setStatusDB (String text, DataStatusEvent dse)
|
||||
public void setStatusDB (String text, DataStatusEvent dse, GridTab gridTab)
|
||||
{
|
||||
if (text == null || text.length() == 0)
|
||||
{
|
||||
|
@ -435,6 +439,7 @@ public class BreadCrumb extends Div implements EventListener<Event> {
|
|||
enableFirstNavigation(m_dse.getCurrentRow() > 0);
|
||||
enableLastNavigation(m_dse.getTotalRows() > m_dse.getCurrentRow()+1);
|
||||
}
|
||||
m_gridTab = gridTab;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -322,7 +322,7 @@ public class StatusBarPanel extends Panel implements EventListener<Event>, IStat
|
|||
return;
|
||||
|
||||
String title = Msg.getMsg(Env.getCtx(), "Who") + m_text;
|
||||
new WRecordInfo (title, m_dse);
|
||||
new WRecordInfo (title, m_dse, null);
|
||||
}
|
||||
else if (Events.ON_CLICK.equals(event.getName()) && event.getTarget() == popup)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
**********************************************************************/
|
||||
package org.adempiere.webui.window;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MUser;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.DisplayType;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.zkoss.util.Pair;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Html;
|
||||
import org.zkoss.zul.Vlayout;
|
||||
|
||||
/**
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class RecordTimeLinePanel extends Vlayout {
|
||||
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = 3420422470180313180L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public RecordTimeLinePanel() {
|
||||
setStyle("height:100%;width:100%;overflow:auto");
|
||||
}
|
||||
|
||||
public void render(GridTab gridTab) {
|
||||
getChildren().clear();
|
||||
if (gridTab == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gridTab.getRowCount() == 0 || gridTab.isNew()) {
|
||||
return;
|
||||
}
|
||||
int recordId = gridTab.getRecord_ID();
|
||||
int tableId = gridTab.getAD_Table_ID();
|
||||
ArrayList<String> docActionValues = new ArrayList<String>();
|
||||
ArrayList<String> docActionNames = new ArrayList<String>();
|
||||
DocumentEngine.readReferenceList(docActionValues, docActionNames, new ArrayList<String>());
|
||||
|
||||
ArrayList<String> docStatusValues = new ArrayList<String>();
|
||||
ArrayList<String> docStatusNames = new ArrayList<String>();
|
||||
DocumentEngine.readStatusReferenceList(docStatusValues, docStatusNames, new ArrayList<String>());
|
||||
String reversedStatusName = null;
|
||||
for(int i = 0; i < docStatusValues.size(); i++) {
|
||||
if (DocAction.STATUS_Reversed.equals(docStatusValues.get(i)))
|
||||
reversedStatusName = docStatusNames.get(i);
|
||||
}
|
||||
StringBuilder sql = new StringBuilder("SELECT u.AD_User_ID, l.created, c.columnName, l.oldValue, l.newValue, l.trxname ")
|
||||
.append("FROM AD_ChangeLog l ")
|
||||
.append("JOIN AD_Column c ON l.ad_column_id=c.ad_column_id ")
|
||||
.append("JOIN AD_User u ON l.createdby=u.ad_user_id ")
|
||||
.append("WHERE l.AD_Table_ID=? ")
|
||||
.append("AND l.Record_ID=? ")
|
||||
.append("ORDER BY l.created desc, l.trxName ");
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
stmt = DB.prepareStatement(sql.toString(), (String)null);
|
||||
stmt.setInt(1, tableId);
|
||||
stmt.setInt(2, recordId);
|
||||
rs = stmt.executeQuery();
|
||||
List<String> columns = null;
|
||||
List<Pair<String, String>> changes = null;
|
||||
String currentTrx = null;
|
||||
String currentDocStatusOld = null;
|
||||
String currentDocStatusNew = null;
|
||||
Timestamp updated = null;
|
||||
int userId = -1;
|
||||
while (rs.next()) {
|
||||
String columnName = rs.getString(3);
|
||||
String trxName = rs.getString(6);
|
||||
String oldValue = rs.getString(4);
|
||||
String newValue = rs.getString(5);
|
||||
if (columns == null) {
|
||||
columns = new ArrayList<String>();
|
||||
changes = new ArrayList<>();
|
||||
}
|
||||
if (currentTrx == null || currentTrx.equals(trxName)) {
|
||||
if (currentTrx == null)
|
||||
currentTrx = trxName;
|
||||
if (columnName.equals("DocAction")) {
|
||||
continue;
|
||||
} else if (columnName.equals("DocStatus")) {
|
||||
if (currentDocStatusNew == null)
|
||||
currentDocStatusNew = newValue;
|
||||
currentDocStatusOld = oldValue;
|
||||
} else {
|
||||
GridField field = gridTab.getField(columnName);
|
||||
if (field != null && field.isDisplayed(true)) {
|
||||
columns.add(field.getHeader());
|
||||
changes.add(new Pair<String, String>(oldValue, newValue));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buildChangeLogMessage(gridTab, docActionValues,
|
||||
docActionNames, reversedStatusName, columns,
|
||||
currentDocStatusOld, currentDocStatusNew,
|
||||
updated, userId, changes);
|
||||
currentTrx = trxName;
|
||||
currentDocStatusOld = null;
|
||||
currentDocStatusNew = null;
|
||||
columns = new ArrayList<String>();
|
||||
changes = new ArrayList<>();
|
||||
if (columnName.equals("DocAction")) {
|
||||
continue;
|
||||
} else if (columnName.equals("DocStatus")) {
|
||||
if (currentDocStatusOld == null)
|
||||
currentDocStatusOld = oldValue;
|
||||
currentDocStatusNew = newValue;
|
||||
} else {
|
||||
GridField field = gridTab.getField(columnName);
|
||||
if (field != null && field.isDisplayed(true)) {
|
||||
columns.add(field.getHeader());
|
||||
changes.add(new Pair<String, String>(oldValue, newValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
userId = rs.getInt(1);
|
||||
updated = rs.getTimestamp(2);
|
||||
}
|
||||
buildChangeLogMessage(gridTab, docActionValues, docActionNames,
|
||||
reversedStatusName, columns, currentDocStatusOld,
|
||||
currentDocStatusNew, updated, userId, changes);
|
||||
if (gridTab != null && gridTab.getValue("CreatedBy") != null) {
|
||||
MUser createdBy = MUser.get(Env.getCtx(), (int) gridTab.getValue("CreatedBy"));
|
||||
StringBuilder sb = new StringBuilder(" ")
|
||||
.append(Msg.getMsg(Env.getCtx(), "Created")).append(" ");
|
||||
if (gridTab.getTabNo() == 0) {
|
||||
sb.append(Env.getContext(Env.getCtx(), gridTab.getWindowNo(), "_WinInfo_WindowName", true));
|
||||
} else {
|
||||
sb.append(gridTab.getName());
|
||||
}
|
||||
buildActivityMessage((Timestamp) gridTab.getValue("Created"), sb.toString(), createdBy);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
DB.close(rs, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildChangeLogMessage(GridTab gridTab,
|
||||
ArrayList<String> docActionValues,
|
||||
ArrayList<String> docActionNames, String reversedStatusName,
|
||||
List<String> columns, String currentDocStatusOld,
|
||||
String currentDocStatusNew, Timestamp updated, int userId, List<Pair<String,String>> changes) {
|
||||
if (currentDocStatusOld != null && currentDocStatusNew != null) {
|
||||
buildDocActionMessage(docActionValues, docActionNames, reversedStatusName, updated, new MUser(Env.getCtx(), userId, (String)null),
|
||||
currentDocStatusOld, currentDocStatusNew, gridTab.getWindowNo());
|
||||
} else if (columns != null && columns.size() > 0) {
|
||||
StringBuilder sb = new StringBuilder(" ");
|
||||
sb.append(Msg.getMsg(Env.getCtx(), "Updated")).append(" ");
|
||||
for(int i = 0; i < columns.size(); i++) {
|
||||
if (i > 0) {
|
||||
if (i+1 == columns.size()) {
|
||||
sb.append(" ")
|
||||
.append(Msg.getMsg(Env.getCtx(), "AND").toLowerCase())
|
||||
.append(" ");
|
||||
} else {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
Pair<String, String> change = changes.get(i);
|
||||
sb.append("<i>")
|
||||
.append(columns.get(i));
|
||||
sb.append(" (")
|
||||
.append(change.getX() != null && !"NULL".equals(change.getX())? change.getX() : "")
|
||||
.append(" > ")
|
||||
.append(change.getY() != null && !"NULL".equals(change.getY()) ? change.getY() : "")
|
||||
.append(")");
|
||||
sb.append("</i>");
|
||||
}
|
||||
buildActivityMessage(updated, sb.toString(), new MUser(Env.getCtx(), userId, (String)null));
|
||||
}
|
||||
}
|
||||
|
||||
private void buildDocActionMessage(ArrayList<String> docActionValues,
|
||||
ArrayList<String> docActionNames, String reversedStatusName, Timestamp updated,
|
||||
MUser user, String fromStatus, String toStatus, int windowNo) {
|
||||
String docAction = null;
|
||||
if (DocAction.STATUS_Completed.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Complete;
|
||||
} else if (DocAction.STATUS_Approved.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Approve;
|
||||
} else if (DocAction.STATUS_Voided.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Void;
|
||||
} else if (DocAction.STATUS_Reversed.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Reverse_Accrual;
|
||||
} else if (DocAction.STATUS_NotApproved.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Reject;
|
||||
} else if (DocAction.STATUS_InProgress.equals(toStatus)) {
|
||||
if (DocAction.STATUS_Completed.equals(fromStatus)) {
|
||||
docAction = DocAction.ACTION_ReActivate;
|
||||
} else if (DocAction.STATUS_Drafted.equals(fromStatus) || DocAction.STATUS_Invalid.equals(fromStatus)) {
|
||||
docAction = DocAction.ACTION_Prepare;
|
||||
}
|
||||
} else if (DocAction.STATUS_Closed.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Close;
|
||||
} else if (DocAction.STATUS_Invalid.equals(toStatus)) {
|
||||
docAction = DocAction.ACTION_Invalidate;
|
||||
}
|
||||
|
||||
if (docAction == null)
|
||||
return;
|
||||
String docActionName = null;
|
||||
if (DocAction.ACTION_Reverse_Accrual.equals(docAction) || DocAction.ACTION_Reverse_Correct.equals(docAction)) {
|
||||
docActionName = reversedStatusName;
|
||||
} else {
|
||||
for(int i = 0; i < docActionValues.size(); i++) {
|
||||
if (docActionValues.get(i).equals(docAction)) {
|
||||
docActionName = docActionNames.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder("<i>")
|
||||
.append(docActionName).append("</i>")
|
||||
.append(" ").append(Env.getContext(Env.getCtx(), windowNo, "_WinInfo_WindowName", true));
|
||||
buildActivityMessage(updated, sb.toString(), user);
|
||||
}
|
||||
|
||||
private void buildActivityMessage(Timestamp activityDate, String activityMessage, MUser user) {
|
||||
|
||||
SimpleDateFormat dateFormat = DisplayType.getDateFormat(DisplayType.DateTime);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<div class=\"help-content\">\n");
|
||||
sb.append("<strong>").append(user.getName()).append("</strong> ").append(activityMessage);
|
||||
sb.append("<div> </div><div>").append(dateFormat.format(activityDate)).append("</div>");
|
||||
sb.append("</div>");
|
||||
Hbox hlayout = new Hbox();
|
||||
hlayout.setHflex("1");
|
||||
String hlayoutClass= "activity-card";
|
||||
if (getChildren().size() > 0)
|
||||
hlayoutClass = hlayoutClass + " activity-card-spacing";
|
||||
hlayout.setSclass(hlayoutClass);
|
||||
appendChild(hlayout);
|
||||
Html contents = new Html();
|
||||
contents.setContent(sb.toString());
|
||||
hlayout.appendChild(contents);
|
||||
}
|
||||
}
|
|
@ -63,9 +63,12 @@ import org.zkoss.zul.Borderlayout;
|
|||
import org.zkoss.zul.Center;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Hlayout;
|
||||
import org.zkoss.zul.Listhead;
|
||||
import org.zkoss.zul.Listheader;
|
||||
import org.zkoss.zul.North;
|
||||
import org.zkoss.zul.Radio;
|
||||
import org.zkoss.zul.Radiogroup;
|
||||
import org.zkoss.zul.South;
|
||||
|
||||
/**
|
||||
|
@ -92,15 +95,16 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
* Record Info
|
||||
* @param title title
|
||||
* @param dse data status event
|
||||
* @param gridTab
|
||||
*/
|
||||
public WRecordInfo (String title, DataStatusEvent dse)
|
||||
public WRecordInfo (String title, DataStatusEvent dse, GridTab gridTab)
|
||||
{
|
||||
super ();
|
||||
this.setTitle(title);
|
||||
if (!ThemeManager.isUseCSSForWindowSize())
|
||||
{
|
||||
ZKUpdateUtil.setWindowWidthX(this, 500);
|
||||
ZKUpdateUtil.setWindowHeightX(this, 400);
|
||||
ZKUpdateUtil.setWindowWidthX(this, 800);
|
||||
ZKUpdateUtil.setWindowHeightX(this, 600);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -118,7 +122,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
|
||||
try
|
||||
{
|
||||
init ( dynInit(dse, title) );
|
||||
init ( dynInit(gridTab, dse, title) );
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -130,6 +134,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
|
||||
|
||||
private Listbox table = new Listbox();
|
||||
private RecordTimeLinePanel timeLinePanel = new RecordTimeLinePanel();
|
||||
private ConfirmPanel confirmPanel = new ConfirmPanel (false);
|
||||
|
||||
/** Logger */
|
||||
|
@ -169,7 +174,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
Pre pre = new Pre();
|
||||
Text text = new Text(m_info.toString());
|
||||
text.setParent(pre);
|
||||
pre.setParent(div);
|
||||
pre.setParent(div);
|
||||
//
|
||||
|
||||
Borderlayout layout = new Borderlayout();
|
||||
|
@ -181,15 +186,41 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
center.setParent(layout);
|
||||
if (showTable)
|
||||
{
|
||||
table.setSclass("record-info-changelog-table");
|
||||
ZKUpdateUtil.setHflex(table, "true");
|
||||
ZKUpdateUtil.setVflex(table, "true");
|
||||
North north = new North();
|
||||
north.setParent(layout);
|
||||
north.appendChild(div);
|
||||
|
||||
north.appendChild(div);
|
||||
center.appendChild(table);
|
||||
ZKUpdateUtil.setWidth(table, "100%");
|
||||
ZKUpdateUtil.setVflex(table, true);
|
||||
|
||||
Radiogroup group = new Radiogroup();
|
||||
div.appendChild(group);
|
||||
Hlayout hlayout = new Hlayout();
|
||||
hlayout.setSclass("record-info-radiogroup");
|
||||
Radio radio = new Radio(Msg.getElement(Env.getCtx(), "AD_ChangeLog_ID"));
|
||||
radio.setRadiogroup(group);
|
||||
hlayout.appendChild(radio);
|
||||
radio = new Radio(Msg.getMsg(Env.getCtx(), "TimeLine"));
|
||||
radio.setRadiogroup(group);
|
||||
hlayout.appendChild(radio);
|
||||
div.appendChild(hlayout);
|
||||
group.setSelectedIndex(0);
|
||||
|
||||
group.addEventListener(Events.ON_CHECK, evt -> {
|
||||
int index = group.getSelectedIndex();
|
||||
if (index == 0) {
|
||||
if (table.getParent() == null && timeLinePanel.getParent() != null) {
|
||||
timeLinePanel.detach();
|
||||
center.appendChild(table);
|
||||
}
|
||||
} else if (index == 1) {
|
||||
if (table.getParent() != null && timeLinePanel.getParent() == null) {
|
||||
table.detach();
|
||||
center.appendChild(timeLinePanel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -197,6 +228,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
ZKUpdateUtil.setVflex(div, "true");
|
||||
center.appendChild(div);
|
||||
}
|
||||
|
||||
//
|
||||
South south = new South();
|
||||
south.setSclass("dialog-footer");
|
||||
|
@ -219,11 +251,12 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
|
||||
/**
|
||||
* Dynamic Init
|
||||
* @param gridTab
|
||||
* @param dse data status event
|
||||
* @param title title
|
||||
* @return true if table initialized
|
||||
*/
|
||||
private boolean dynInit(DataStatusEvent dse, String title)
|
||||
private boolean dynInit(GridTab gridTab, DataStatusEvent dse, String title)
|
||||
{
|
||||
if (dse.CreatedBy == null)
|
||||
return false;
|
||||
|
@ -250,10 +283,14 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
//get uuid
|
||||
GridTable gridTable = null;
|
||||
String tabName = null;
|
||||
if (dse.getSource() instanceof GridTab)
|
||||
if (gridTab != null)
|
||||
{
|
||||
GridTab gridTab = (GridTab) dse.getSource();
|
||||
gridTable = gridTab.getTableModel();
|
||||
}
|
||||
else if (dse.getSource() instanceof GridTab)
|
||||
{
|
||||
gridTab = (GridTab) dse.getSource();
|
||||
gridTable = gridTab.getTableModel();
|
||||
tabName = gridTab.getName();
|
||||
}
|
||||
else if (dse.getSource() instanceof GridTable)
|
||||
|
@ -300,6 +337,10 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
m_permalink.setVisible(po.get_KeyColumns().length == 1);
|
||||
}
|
||||
}
|
||||
if (gridTab != null)
|
||||
{
|
||||
timeLinePanel.render(gridTab);
|
||||
}
|
||||
|
||||
// Title
|
||||
if (tabName == null && dse.AD_Table_ID != 0)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
**********************************************************************/
|
||||
package org.adempiere.webui.window;
|
||||
|
||||
import org.adempiere.webui.component.Window;
|
||||
import org.compiere.model.GridTab;
|
||||
|
||||
/**
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class WRecordTimeLine extends Window {
|
||||
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -7887774385203335178L;
|
||||
private RecordTimeLinePanel activityLayout;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public WRecordTimeLine() {
|
||||
activityLayout = new RecordTimeLinePanel();
|
||||
appendChild(activityLayout);
|
||||
}
|
||||
|
||||
public void render(GridTab gridTab) {
|
||||
activityLayout.render(gridTab);
|
||||
}
|
||||
}
|
|
@ -277,3 +277,27 @@
|
|||
height: 80% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
border: 1px solid #d0cdc8;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom: 2px solid #d0cdc8;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.activity-card-spacing {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.activity-card .help-content {
|
||||
font-size: 13px;
|
||||
}
|
||||
.record-info-dialog .record-info-radiogroup {
|
||||
padding: 4px 4px 8px 4px;
|
||||
}
|
||||
.record-info-dialog .record-info-changelog-table {
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
|
|
@ -89,15 +89,15 @@
|
|||
}
|
||||
|
||||
.record-info-dialog {
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
}
|
||||
@media screen and (max-width: 500px) {
|
||||
@media screen and (max-width: 800px) {
|
||||
.record-info-dialog {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@media screen and (max-height: 400px) {
|
||||
@media screen and (max-height: 600px) {
|
||||
.record-info-dialog {
|
||||
height: 100%;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue