Files
TaskFlow/app/TaskFlow/frmMain.vb
Developer01 d086590eed Fix: Toten Pseudo-Fallback in GridViewWorkflows_MouseDown entfernt
Der InvalidRowHandle-Check in GridViewWorkflows_MouseDown (aus einem
vorherigen Commit) las GridViewWorkflows.FocusedRowHandle in eine
lokale Variable ein, verwendete sie aber nirgends - hi.RowHandle blieb
unverändert ungültig, sodass der Code ohnehin sofort in der nächsten
Prüfung (Not hi.InRow) abbrach. Zusätzlich trug die Debug-Zeile
fälschlich das Präfix "Item_Scope:" statt "MouseDown:" - offensichtlich
ein Kopier-Rest.

Anders als in Item_Scope (siehe vorheriger Commit) ist ein
FocusedRowHandle-Fallback hier bewusst NICHT sinnvoll: e.Location ist
in MouseDown immer die aktuelle Klick-Position (kein Caching-Problem),
und InvalidRowHandle ist der normale, erwartete Fall für legitime
Nicht-Zeilen-Klicks (Spaltenkopf, leerer Bereich, insb.
FilterPanelCloseButton). Ein Fallback auf FocusedRowHandle würde solche
Klicks fälschlich der aktuell fokussierten Zeile zuordnen (z.B. Klick
auf "Filter schließen" würde plötzlich CURRENT_CLICKED_PROFILE_ID
setzen) - neuer Bug statt Fix. Der ursprünglich gemeldete Fehler
(Doppelklick auf Gruppenkopf reagiert nicht) ist bereits durch den
Fallback in Item_Scope abgedeckt, unabhängig vom Ausgang dieses
MouseDown-Aufrufs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 15:25:34 +02:00

5233 lines
237 KiB
VB.net
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Imports System.ComponentModel
Imports System.Globalization
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports DevExpress.LookAndFeel
Imports DevExpress.Utils
Imports DevExpress.XtraBars.Ribbon
Imports DevExpress.XtraEditors
Imports DevExpress.XtraExport.Helpers
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.BandedGrid
Imports DevExpress.XtraGrid.Views.Base
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraGrid.Views.Grid.ViewInfo
Imports DevExpress.XtraNavBar
Imports DevExpress.XtraPrinting
Imports DevExpress.XtraSplashScreen
Imports DevExpress.XtraTreeList
Imports DigitalData.GUIs.Common
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.EDMI.API.Constants
Imports DigitalData.Modules.EDMI.API.DatabaseWithFallback
Imports DigitalData.Modules.Windream
Imports DigitalData.Modules.ZooFlow
Imports GdPicture.Internal.CAD.DWG.Entities
Imports System.Runtime.InteropServices
Public Class frmMain
Private Property FormHelper As FormHelper
Private UserLoggedin As Integer = 0
Private CURR_DT_VWPM_PROFILE_ACTIVE As DataTable
Private CURR_DT_VWPM_PROFILE_AH_WORKFLOW As DataTable
Private DT_CURR_WF_ITEMS As DataTable
Private _treeNodeCounts As New Dictionary(Of Integer, Integer)
Private OVERVIEW_ADDED_WHEN As String
Private OVERVIEW_CHANGED_WHEN As String
Private OVERVIEW_COUNT As Integer = 0
Private RedDocuments As Integer = 0
Private YellowDocuments As Integer = 0
Private GreenDocuments As Integer = 0
Private GridViewItem_Clicked = Nothing
Private GridCursorLocation As System.Drawing.Point
Private GRID_LOAD_TYPE As String = "OVERVIEW"
Private GRID_INV_COL_REMOVED As Boolean = False
Private NO_WORKFLOW_ITEMS As Boolean = False
Private InResetlayout As Boolean = False
Private RefreshHelper As RefreshHelper
Private _FormValidator As frmValidator
Private FormOpenClose As Boolean = False
Private FormShown As Boolean = False
Private GridIsLoaded As Boolean = False
Private OverviewOrDEtail As String = "OVERVIEW"
Private GridBuilder As GridBuilder
Private allgFunk As New ClassAllgemeineFunktionen
Private _Init As New ClassInit
'Private CurrNavBarGroup As NavBarGroup
'Private DataASorDB As ClassDataASorDB
Private DT_CHECKUSER_MODULE As DataTable
Private NOTIFICATIONS_DT As DataTable
Private IsFilterMode As Boolean
Private DetailLinkActive As Boolean = False
Private FRONTEND_ACTION As String = "NONE"
Private Ev_Filter_Panel_Closed As Boolean = False
Private _overlayActive As Boolean = False
Dim omsgOpenWorkflow As String
Dim omsgTitleWarning As String
Dim omsgTitleAttention As String
Private Const FullFilepatColName = "FULL_FILE_PATH"
Private Const FA_NONE = "NONE"
Public Const NAVBAR_CLICKED = "NAVBAR LINK CLICKED"
Private CUSTOM_OVERVIEW_SQL As String = String.Empty
Private _lastUsedOverviewSQL As String = String.Empty ' ← NEU: persistente Kopie
Private COCKPIT_PROFILE_SQL As String = String.Empty
Private COCKPIT_CONFIG_ID As Integer = 0
Private Class S
Inherits My.Resources.frmMain_Strings
End Class
Private Function GET_LAST_ADDED(pDatatable As DataTable) As String
Dim oADDED As String
Try
If IsNothing(pDatatable) Then
oADDED = "NOTHING"
ElseIf LAST_ADDED_COLUMN = FA_NONE Then
oADDED = Now.ToShortTimeString.ToString
Else
Dim result As Object
result = pDatatable.Compute($"MAX({LAST_ADDED_COLUMN})", "")
oADDED = result
End If
Catch ex As Exception
oADDED = "Exception"
End Try
Return oADDED
End Function
Private Function GET_LAST_CHANGED(pDatatable As DataTable) As String
Dim oCHANGED As String
Try
If IsNothing(pDatatable) Then
oCHANGED = "NOTHING"
ElseIf LAST_EDITED_COLUMN = FA_NONE Then
oCHANGED = Now.ToShortTimeString.ToString
Else
Dim result As Object
result = pDatatable.Compute($"MAX({LAST_EDITED_COLUMN})", "")
oCHANGED = result
End If
Catch ex As Exception
oCHANGED = "Exception"
End Try
Return oCHANGED
End Function
Public Sub SaveInheritanceConfirmationsToDatabase()
Try
LOGGER.Debug("Saving inheritance confirmations to database for user {0}", USER_ID.ToString)
Dim entries = UserInheritance_ConfirmationByColumn
If entries Is Nothing OrElse entries.Count = 0 Then
LOGGER.Debug("No confirmation entries to save")
Return
End If
For Each entry As UserInheritanceConfirmation In entries
Dim keyName As String = $"INHERITANCE_CONFIRM_{entry.ColumnName.ToUpperInvariant()}"
Dim valueText As String = entry.Count.ToString()
SaveOrUpdateKeyValuePair(keyName, valueText)
Next
LOGGER.Debug("Successfully saved {0} confirmation entries", entries.Count)
Catch ex As Exception
LOGGER.Error("Error saving inheritance confirmations to database")
LOGGER.Error(ex)
End Try
End Sub
Private Sub SaveOrUpdateKeyValuePair(keyName As String, valueText As String)
Try
' Prüfen ob der Eintrag bereits existiert
Dim oSQL As String = String.Format("DECLARE @Out_PK_ID bigint
EXECUTE [dbo].[PRDD_TBDD_USER_KEY_VALUE_PAIR_Upsert]
{0}
,'{1}'
,'{2}'
,{3}
,@Out_PK_ID OUTPUT;", USER_ID, keyName, valueText, USER_MODULE_ID)
If DatabaseFallback.ExecuteNonQueryECM(oSQL) Then
LOGGER.Debug("Saved/Updated key-value pair: {0} = {1}", keyName, valueText)
End If
Catch ex As Exception
LOGGER.Error("Error saving key-value pair for key {0}", keyName)
LOGGER.Error(ex)
End Try
End Sub
Private Sub frmMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Try
FormOpenClose = True
' Position und Größe speichern
My.Settings.frmMainSize = Me.Size
My.Settings.frmMainPosition = Me.Location
My.Settings.Save()
CONFIG.Config.MainTreeList_Width = TreeList_Cockpit.Width
CONFIG.Save()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Error in Save FormLayout: " & ex.Message)
End Try
SaveInheritanceConfirmationsToDatabase()
If IDB_ACTIVE = False Then
Try
If WINDREAM?.oSession?.aLoggedin = True Then
WINDREAM.Stop_WMCC_andCo()
End If
Catch ex As Exception
End Try
End If
If INACTIVITYRecognized Then
Exit Sub
End If
Try
ClassAllgemeineFunktionen.LoginOut("LOGOUT")
LOGGER.Info("taskFLOW closed - " & Now, False)
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Sub frmMain_KeyUp(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyCode
Case Keys.F12
frmLicense.ShowDialog()
End Select
End Sub
Private Sub frmMain_Load(sender As Object, e As System.EventArgs) Handles Me.Load
FormOpenClose = True
LOGGER.Debug("Initializing MainForm....")
GridBuilder = New GridBuilder(GridViewWorkflows)
GridBuilder.WithFontSizeDelta(CONFIG.Config.GridFontSizeDelta)
Dim oFontSettings = New List(Of FontSetting) From {
New FontSetting With {.Title = S.Kleiner, .Value = -2},
New FontSetting With {.Title = S.Normal, .Value = 0},
New FontSetting With {.Title = S.Größer, .Value = 2}
}
cmbGridFontSize.Items.Clear()
cmbGridFontSize.Items.AddRange(oFontSettings)
barItemGridFontSize.EditValue = oFontSettings.
Where(Function(item) item.Value = CONFIG.Config.GridFontSizeDelta).
FirstOrDefault()
' Create helper to save/load expanded GroupColumns at runtime
RefreshHelper = New RefreshHelper(LOGCONFIG, GridViewWorkflows, "GUID")
omsgOpenWorkflow = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("WorkflowIsActive1")
omsgTitleWarning = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("MsgboxTitleWarning")
omsgTitleAttention = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("MsgboxTitleAttention")
Dim oVErsion = My.Application.Info.Version.ToString 'String.Format("{0}.{1}.{2}", My.Application.Info.Version.Major, My.Application.Info.Version.Minor, My.Application.Info.Version.Build)
BSIVERSION1.Caption = oVErsion
If ERROR_STATE = "NO DB-CONNECTION" Or ERROR_STATE = "FAILED DBCONNECTION" Then
MsgBox(S.Bitte_konfigurieren_Sie_eine_Datenbankverbindung_, MsgBoxStyle.Critical, "Fehlende Konfiguration:")
frmKonfig.ShowDialog()
End If
Try
If CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName = "eng" Then
LOGGER.Info("## CurrentUICulture.Name: " & CultureInfo.CurrentUICulture.Name, False)
INDEX_DMS_ERSTELLT = "DMS Created"
INDEX_DMS_ERSTELLT_ZEIT = "DMS Created Time"
My.Settings.Save()
End If
Try
Dim oCultureInfo As System.Globalization.CultureInfo
oCultureInfo = New System.Globalization.CultureInfo(USER_LANGUAGE)
oCultureInfo.DateTimeFormat.ShortDatePattern = USER_DATE_FORMAT
Thread.CurrentThread.CurrentCulture = oCultureInfo
Thread.CurrentThread.CurrentUICulture = oCultureInfo
CultureInfo.DefaultThreadCurrentCulture = oCultureInfo
CultureInfo.DefaultThreadCurrentUICulture = oCultureInfo
Catch ex As Exception
End Try
Catch ex As Exception
LOGGER.Error(ex)
MessageBox.Show("Error loading CurrentUICulture-Info!", "Attention:", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Try
Try
'DataASorDB = New ClassDataASorDB
If User.IsAdmin = True Then
'Dim oCaption As String = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("NumberLicenses")
'bsiLicenses.Caption = $"{oCaption} {LICENSE_COUNT}"
Dim oCaption As String = String.Format(S.Anzahl_Lizenzen___0_, LICENSE_COUNT)
bsiLicenses.Caption = oCaption
bsiLicenses.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
bsiLicenses.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
LOGGER.Debug("Initializing MainForm....")
If ERROR_STATE = "NO USER" Then
Dim oDT As DataTable = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("No Userconfig")
MsgBox(oDT.Rows(0).Item("STRING1") & vbNewLine & oDT.Rows(0).Item("STRING2"), MsgBoxStyle.Critical, "Exception")
Me.Close()
ElseIf USER_IN_MODULE = False Then
If USER_IS_ADMIN = False Then
Dim oDT As DataTable = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("No Module Configuration")
MsgBox(oDT.Rows(0).Item("STRING1") & vbNewLine & oDT.Rows(0).Item("STRING2"), MsgBoxStyle.Critical, "Exception")
Me.Close()
End If
ElseIf SYS_LOCKED_MAINTENANCE = True Then
Dim msg = $"Wegen Wartungsarbeiten ist der Zugriff auf den Workflow aktuell gesperrt!" & vbNewLine & "Vielen Dank für Ihre Geduld!"
If USER_LANGUAGE <> "de-DE" Then
msg = $"Due to maintenance work, access to the workflow is currently blocked!" & vbNewLine & "Thank You for Your patience!"
End If
MsgBox(msg, MsgBoxStyle.Exclamation, ADDITIONAL_TITLE)
Me.Close()
Else
LOGGER.Info("Username: " & USER_USERNAME, False)
'Wenn license abgelaufen und der User nicht admin ist!
If LICENSE_EXPIRED = True Then
If USER_IS_ADMIN = False Then
MsgBox("License expired or invalid!" & vbNewLine & "Please contact the AdminTeam!", MsgBoxStyle.Critical, "Attention:")
Me.Close()
End If
End If
If USER_IS_ADMIN = True Then
RibbonPageGroup3.Visible = True
'Anzahl der eingeloggten User
bsiUserLoggedIn.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
'Dim oCaption As String = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("NumberUserLoggedIn")
'bsiUserLoggedIn.Caption = $"{oCaption} {USERCOUNT_LOGGED_IN}"
Dim oCaption As String = String.Format(S.Anzahl_angemeldete_Benutzer___0_, USERCOUNT_LOGGED_IN)
bsiUserLoggedIn.Caption = oCaption
If GHOSTMODE_ACTIVE = True Then
bbtnitmGhostMode.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
bbtnitmGhostMode.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
Else
RibbonPageGroup3.Visible = False
bsiUserLoggedIn.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
bbtnitmGhostMode.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
Try
If SEARCH1 <> String.Empty Then
Dim oindex = SEARCH1.IndexOf("~")
Dim oCaption = SEARCH1.Substring(0, oindex)
Dim oCommand = SEARCH1.Replace(oCaption + "~", "")
SearchItem1.Caption = oCaption
SearchItem1.Tag = oCommand
SearchItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
RibbonPageGroup4.Visible = True
End If
Catch ex As Exception
End Try
Try
If SEARCH2 <> String.Empty Then
Dim oindex = SEARCH2.IndexOf("~")
Dim oCaption = SEARCH2.Substring(0, oindex)
Dim oCommand = SEARCH2.Replace(oCaption + "~", "")
SearchItem2.Caption = oCaption
SearchItem2.Tag = oCommand
SearchItem2.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
RibbonPageGroup4.Visible = True
End If
Catch ex As Exception
End Try
If START_CW = True Then
Dim oPath
Select Case START_CW_LOC_VARIANT
Case "-1"
oPath = Directory.GetParent(Application.StartupPath).ToString
Case "0"
oPath = Application.StartupPath.ToString
End Select
oPath &= "\easyFLOW\easyFLOW.exe"
If File.Exists(oPath) Then
bbtniCW.Caption = START_CW_CAPTION
bbtniCW.Tag = oPath
bbtniCW.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
RibbonPageGroup4.Visible = True
Else
LOGGER.Warn($"Error in CW-Button init: Could not find CW.Exe {oPath}")
End If
End If
End If
Catch ex As Exception
LOGGER.Error(ex)
MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Error in User Check:")
End Try
bsiUser.Caption = USER_USERNAME
GetBaseData("Load")
Try
If TimerRefresh.Enabled = False Then
TimerRefresh.Start()
End If
Timer5Mins.Start()
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Unexpected Error in LoadForm - Step 4: " & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Attention:")
End Try
Load_Treeview()
' LoadNavBar()
' AddHandler NavBarControl1.LinkClicked, AddressOf navBar_LinkClicked
If Not IsNothing(CURR_DT_VWPM_PROFILE_AH_WORKFLOW) Then
If CURR_DT_VWPM_PROFILE_AH_WORKFLOW.Rows.Count > 0 And LIC_MODULES.Contains("MOD_AdhocWorkflow_BlindFile") Then
RibbonPageGroupAHW.Visible = True
Dim OCounter As Integer = 1
For Each oRow As DataRow In CURR_DT_VWPM_PROFILE_AH_WORKFLOW.Rows
Select Case OCounter
Case 1
BbtnitmAHWF1.Caption = oRow.Item("TITLE")
BbtnitmAHWF1.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BbtnitmAHWF1.Tag = oRow.Item("GUID")
Case 2
BbtnitmAHWF2.Caption = oRow.Item("TITLE")
BbtnitmAHWF2.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BbtnitmAHWF2.Tag = oRow.Item("GUID")
Case 3
BbtnitmAHWF3.Caption = oRow.Item("TITLE")
BbtnitmAHWF3.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BbtnitmAHWF3.Tag = oRow.Item("GUID")
Case 4
End Select
OCounter += 1
Next
Else
LOGGER.Info($"NO ADHOC-WFs Blindfiles ({CURR_DT_VWPM_PROFILE_AH_WORKFLOW.Rows.Count}) or License AHWF_NoBlindFile not integrated...")
End If
Else
LOGGER.Debug("NO ADHOC-WFs Blindfiles (Nothing)...")
End If
Check_Timer_Notification()
Timer_Inactivity_Reset_Disable("FormLoad")
'Restore_Form_Position()
Dim oSavedPosition As System.Drawing.Point = My.Settings.frmMainPosition
' Prüfen, ob die Position sichtbar ist
If IsPositionVisible(oSavedPosition) Then
' Position ist sichtbar, das Formular wird dort angezeigt
ScreenEx.RestoreFormPosition(Me, My.Settings.frmMainPosition)
ScreenEx.RestoreFormState(Me, My.Settings.frmMainWindowState)
ScreenEx.RestoreFormSize(Me, My.Settings.frmMainSize)
Else
' Position ist unsichtbar, Standardposition verwenden
Me.StartPosition = FormStartPosition.CenterScreen
End If
If IDB_ACTIVE = False And ERROR_STATE = "" Then
Try
If Init_windream() = True Then
WINDREAM.Start_WMCC_andCo()
BarButtonItemFileLink.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
If Not IsNothing(WINDREAM.oSession) Then
If WINDREAM.oSession.aLoggedin = False Then
LOGGER.Warn("⚠️ You could not be logged in to windream")
MsgBox(S.Es_ist_keine_Windream_Session_vorhanden__Bitte_überprüfen_Sie_das_Log_, MsgBoxStyle.Critical)
End If
Else
LOGGER.Warn("⚠️ Login on windream was not possible.")
MsgBox(S.Es_ist_keine_Windream_Session_vorhanden__Bitte_überprüfen_Sie_das_Log_, MsgBoxStyle.Critical)
End If
End If
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Unexpected Error in windream-login - Step 5: " & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Attention:")
End Try
Else
BarButtonItemFileLink.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
SOURCE_INIT = Init_IDB()
If SOURCE_INIT = True Then
Dim oSQL = $"SELECT SQL_COMMAND FROM TBDD_SQL_COMMANDS WITH (NOLOCK) WHERE TITLE = 'PM_IDB_DOC_DATA'"
Dim DTIDB_DOC_DATA_SQL = DatabaseFallback.GetDatatable("TBDD_SQL_COMMANDS", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = "TITLE = 'PM_IDB_DOC_DATA'"
})
IDB_DOC_DATA_SQL = DTIDB_DOC_DATA_SQL.Rows(0).Item("SQL_COMMAND")
LOGGER.Debug($"Got the IDB_DOC_DATA_SQL..{IDB_DOC_DATA_SQL}")
End If
bsiGeneralInfo.Caption = S.IDB_Aktiv
End If
If EDMIAppServerActive = True Then
BarStaticItemAppServer.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
BarStaticItemAppServer.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
If BASIC_CONF_VISIBLE = False Then
RibbonPageGroupBasicConf.Visible = False
barbtnitmsaveLogfiles.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
RibbonPageGroupBasicConf.Visible = True
End If
If MAINFORM_CREATE_LOG_FILES = True Then
barbtnitmsaveLogfiles.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
End If
If EXCEL_OVERVIEW = True Then
BarButtonItemExportExcel.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
BarButtonItemExportExcel.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
If BASEDATA_DT_LANGUAGE.Rows.Count > 1 Then
bbtnitmLanguage_Change.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
bbtnitmLanguage_Change.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
' ===== CHECKBOX AUS CONFIG INITIALISIEREN (VOR Decide_Load) =====
' Ohne diesen Block ist Checked immer False nach Neustart, unabhängig vom gespeicherten Config-Wert
Try
Bchkitm_load_empty_wf.Checked = CONFIG.Config.Hide_Empty_Workflows
LOGGER.Debug($"frmMain_Shown: Bchkitm_load_empty_wf.Checked initialized from config: [{CONFIG.Config.Hide_Empty_Workflows}]")
Catch ex As Exception
LOGGER.Warn($"frmMain_Shown: Could not initialize Bchkitm_load_empty_wf.Checked - {ex.Message}")
End Try
LoadCURRENT_DT_PROFILES()
LoadVWPM_CONTROL_INDEX()
LOGGER.Debug("MainForm initialized!")
FormOpenClose = False
End Sub
Private Sub Load_Treeview()
Try
Me.Cursor = Cursors.WaitCursor
Dim oSQL = $"SELECT * FROM [dbo].[FNTF_GET_COCKPIT_DEFINITION] ({USER_ID},'{USER_LANGUAGE}')"
Dim oDT_STRUCTURE_NODES As DataTable = DatabaseFallback.GetDatatableECM(oSQL)
If oDT_STRUCTURE_NODES Is Nothing OrElse oDT_STRUCTURE_NODES.Rows.Count = 0 Then
Dim oMsg As String
Dim oTitle As String
Select Case USER_LANGUAGE
Case "fr-FR", "fr-BE", "fr-CH"
oMsg = "Aucune configuration de cockpit n'a pu être lue. Veuillez contacter votre équipe d'administration!"
oTitle = "Erreur de configuration"
Case "es-ES", "es-MX", "es-AR"
oMsg = "No se pudo leer ninguna configuración de cockpit. ¡Póngase en contacto con su equipo de administración!"
oTitle = "Error de configuración"
Case "de-DE", "de-AT", "de-CH"
oMsg = "Es konnte keine Cockpit-Konfiguration ausgelesen werden. Kontaktieren Sie Ihr Administrationsteam!"
oTitle = "Konfigurationsfehler"
Case Else ' en-US, en-GB und alle weiteren
oMsg = "No cockpit configuration could be read. Please contact your administration team!"
oTitle = "Configuration Error"
End Select
LOGGER.Warn($"Load_Treeview: No node configuration found for USER_ID [{USER_ID}] - USER_LANGUAGE [{USER_LANGUAGE}]")
MsgBox(oMsg, MsgBoxStyle.Critical, oTitle)
Exit Sub
End If
' ===== NUR AKTIVE KNOTEN BEHALTEN =====
If oDT_STRUCTURE_NODES.Columns.Contains("ACTIVE") Then
Dim oInactiveRows As DataRow() = oDT_STRUCTURE_NODES.Select("ACTIVE = 0 OR ACTIVE IS NULL")
If oInactiveRows.Length > 0 Then
LOGGER.Debug($"Load_Treeview: Removing [{oInactiveRows.Length}] inactive node(s) (ACTIVE=0 or NULL)")
For Each oRow As DataRow In oInactiveRows
oRow.Delete()
Next
oDT_STRUCTURE_NODES.AcceptChanges()
End If
Else
LOGGER.Warn("Load_Treeview: ACTIVE column not found in FNTF_GET_COCKPIT_DEFINITION result")
End If
' ===== ANZAHL DER OVERVIEW-KNOTEN ERMITTELN (VOR WEITEREN FILTERN) =====
Dim oOverviewRows As DataRow() = oDT_STRUCTURE_NODES.Select("TYPE_ID = 0")
LOGGER.Debug($"Load_Treeview: Found [{oOverviewRows.Length}] node(s) with TYPE_ID=0 (Overview)")
' ===== MONITOR-KNOTEN ENTFERNEN WENN KEIN RECHT =====
If MONITORING_ACTIVE = False AndAlso oDT_STRUCTURE_NODES.Columns.Contains("TYPE_ID") Then
Dim oMonitorRows As DataRow() = oDT_STRUCTURE_NODES.Select("TYPE_ID = 2")
If oMonitorRows.Length > 0 Then
LOGGER.Debug($"Load_Treeview: MONITORING_ACTIVE=False - removing [{oMonitorRows.Length}] monitor node(s) from TreeList datasource")
For Each oRow As DataRow In oMonitorRows
oRow.Delete()
Next
oDT_STRUCTURE_NODES.AcceptChanges()
End If
End If
' ===== CHART-KNOTEN ENTFERNEN WENN KEIN RECHT =====
If SHOW_CHARTS = False AndAlso oDT_STRUCTURE_NODES.Columns.Contains("TYPE_ID") Then
Dim oChartRows As DataRow() = oDT_STRUCTURE_NODES.Select("TYPE_ID = 3")
If oChartRows.Length > 0 Then
LOGGER.Debug($"Load_Treeview: SHOW_CHARTS=False - removing [{oChartRows.Length}] chart node(s) from TreeList datasource")
For Each oRow As DataRow In oChartRows
oRow.Delete()
Next
oDT_STRUCTURE_NODES.AcceptChanges()
End If
End If
TreeList_Cockpit.BeginUpdate()
Try
TreeList_Cockpit.DataSource = oDT_STRUCTURE_NODES
AddHandler TreeList_Cockpit.CustomDrawNodeCell, AddressOf TreeList_Cockpit_CustomDrawNodeCell
TreeList_Cockpit.KeyFieldName = "PK_CFG_COCKPIT_DEFINITION_ID"
TreeList_Cockpit.ParentFieldName = "PARENT_ID"
TreeList_Cockpit.Columns("PK_RESULT_ID").SortOrder = SortOrder.Ascending
' ===== MODERNES DESIGN =====
' Schriftgröße und -art
TreeList_Cockpit.Appearance.Row.Font = New Font("Segoe UI", 12, FontStyle.Regular)
TreeList_Cockpit.Appearance.FocusedRow.Font = New Font("Segoe UI", 12, FontStyle.Bold)
TreeList_Cockpit.Appearance.HideSelectionRow.Font = New Font("Segoe UI", 12, FontStyle.Regular)
' Modernes Farbschema (passend zum Office2019-Skin)
TreeList_Cockpit.Appearance.Row.BackColor = Color.White
TreeList_Cockpit.Appearance.Row.ForeColor = Color.FromArgb(50, 50, 50)
TreeList_Cockpit.Appearance.FocusedRow.BackColor = Color.FromArgb(210, 230, 255)
TreeList_Cockpit.Appearance.FocusedRow.ForeColor = Color.FromArgb(20, 20, 20)
TreeList_Cockpit.Appearance.HideSelectionRow.BackColor = Color.FromArgb(225, 235, 250)
TreeList_Cockpit.Appearance.HideSelectionRow.ForeColor = Color.FromArgb(50, 50, 50)
' Zeilenhöhe erhöhen für bessere Lesbarkeit
TreeList_Cockpit.RowHeight = 28
Dim oVisibleColumns As New System.Collections.Generic.HashSet(Of String)(StringComparer.OrdinalIgnoreCase) From {"NAME"}
For Each oColumn As DevExpress.XtraTreeList.Columns.TreeListColumn In TreeList_Cockpit.Columns
oColumn.Visible = oVisibleColumns.Contains(oColumn.FieldName)
Next
Finally
TreeList_Cockpit.EndUpdate()
End Try
' ===== KNOTEN AUF-/ZUKLAPPEN BASIEREND AUF ANZAHL DER OVERVIEW-KNOTEN =====
If oOverviewRows.Length = 1 Then
LOGGER.Debug("Load_Treeview: Only 1 overview node found - expanding all nodes")
For Each oNode As DevExpress.XtraTreeList.Nodes.TreeListNode In TreeList_Cockpit.Nodes
oNode.Expanded = True
Next
ElseIf oOverviewRows.Length > 1 Then
LOGGER.Debug($"Load_Treeview: [{oOverviewRows.Length}] overview nodes found - collapsing all nodes")
For Each oNode As DevExpress.XtraTreeList.Nodes.TreeListNode In TreeList_Cockpit.Nodes
oNode.Expanded = False
Next
Else
LOGGER.Warn("Load_Treeview: No overview nodes (TYPE_ID=0) found - keeping default collapsed state")
End If
TreeList_Cockpit.Refresh()
' ===== ANZAHL ASYNCHRON NACHLADEN =====
If oDT_STRUCTURE_NODES.Columns.Contains("SQL_QUERY_COUNT") Then
AppendCountsToTreeAsync()
End If
Catch ex As Exception
LOGGER.Error(ex)
Finally
Me.Cursor = Cursors.Default
End Try
End Sub
Private Sub TreeList_Cockpit_CustomDrawNodeCell(sender As Object, e As DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs)
Try
Dim oPk As Object = e.Node.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk Is Nothing OrElse IsDBNull(oPk) Then
Exit Sub
End If
Dim oPkInt As Integer = CInt(oPk)
If Not _treeNodeCounts.ContainsKey(oPkInt) Then
Exit Sub
End If
If _treeNodeCounts(oPkInt) > 0 Then
e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Bold)
Else
e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Regular)
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Async Sub AppendCountsToTreeAsync()
Try
LOGGER.Debug("AppendCountsToTreeAsync: Starting background count queries...")
Dim oWorkItems As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, SQL As String, OriginalName As String))
TreeList_Cockpit.NodesIterator.DoOperation(
Sub(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode)
Dim oTypeId As Object = oNode.GetValue("TYPE_ID")
Dim oProfileID As Object = oNode.GetValue("FK_PROFILE_ID")
If oTypeId Is Nothing OrElse IsDBNull(oTypeId) Then
LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oNode.GetValue("NAME")}] has no TYPE_ID - skipping.")
Exit Sub
End If
Dim oTypeIdInt As Integer = CInt(oTypeId)
If oTypeIdInt <> 0 AndAlso oTypeIdInt <> 1 Then
Exit Sub
End If
Dim oSqlCount As Object = oNode.GetValue("SQL_QUERY_COUNT")
If oSqlCount IsNot Nothing AndAlso Not IsDBNull(oSqlCount) AndAlso Not String.IsNullOrWhiteSpace(oSqlCount.ToString()) Then
Dim oProfileIdInt As Integer = If(oProfileID IsNot Nothing AndAlso Not IsDBNull(oProfileID), CInt(oProfileID), 0)
Dim oRawSQL As String = oSqlCount.ToString()
LOGGER.Debug($"AppendCountsToTreeAsync: Preparing SQL for node [{oNode.GetValue("NAME")}] with PROFILE_ID [{oProfileIdInt}]")
LOGGER.Debug($"AppendCountsToTreeAsync: Original SQL: {oRawSQL}")
oRawSQL = oRawSQL.Replace("@PROFILE_ID", oProfileIdInt.ToString())
oRawSQL = oRawSQL.Replace("@PROFIL_ID", oProfileIdInt.ToString())
oRawSQL = oRawSQL.Replace("{#USER#PROFILE_ID}", oProfileIdInt.ToString())
oRawSQL = oRawSQL.Replace("{#USER#PROFIL_ID}", oProfileIdInt.ToString())
Dim oPreparedSQL As String = PrepareSQLWithReplacements(oRawSQL, oProfileIdInt)
' ===== COUNT-SUFFIX VOM VORHERIGEN DURCHLAUF ENTFERNEN =====
Dim oRawName As String = oNode.GetValue("NAME")?.ToString()
Dim oSuffixMatch = System.Text.RegularExpressions.Regex.Match(oRawName, "^(.*)\s+\(\d+\)$")
Dim oCleanName As String = If(oSuffixMatch.Success, oSuffixMatch.Groups(1).Value.Trim(), oRawName)
If Not String.IsNullOrWhiteSpace(oCleanName) Then
oWorkItems.Add((oNode, oPreparedSQL, oCleanName))
End If
Else
LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oNode.GetValue("NAME")}] has no valid SQL_QUERY_COUNT, skipping.")
End If
End Sub)
If oWorkItems.Count = 0 Then
LOGGER.Debug("AppendCountsToTreeAsync: No nodes with SQL_QUERY_COUNT found, exiting.")
Exit Sub
End If
LOGGER.Debug($"AppendCountsToTreeAsync: {oWorkItems.Count} node(s) with SQL_QUERY_COUNT found")
Dim oResults As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, OriginalName As String, Count As String))
Await Task.Run(Sub()
For Each oItem In oWorkItems
Try
Dim oResult As Object = DatabaseFallback.GetScalarValueECM(oItem.SQL)
If oResult IsNot Nothing AndAlso Not IsDBNull(oResult) Then
SyncLock oResults
oResults.Add((oItem.Node, oItem.OriginalName, oResult.ToString()))
End SyncLock
End If
Catch ex As Exception
LOGGER.Warn($"AppendCountsToTreeAsync: Count query failed for node [{oItem.OriginalName}] - {ex.Message}")
End Try
Next
End Sub)
_treeNodeCounts.Clear()
TreeList_Cockpit.BeginUpdate()
Try
For Each oResult In oResults
Dim oPk As Object = oResult.Node.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk IsNot Nothing AndAlso Not IsDBNull(oPk) Then
Dim oCount As Integer = 0
Integer.TryParse(oResult.Count, oCount)
_treeNodeCounts(CInt(oPk)) = oCount
End If
oResult.Node.SetValue("NAME", $"{oResult.OriginalName} ({oResult.Count})")
LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oResult.OriginalName}] → [{oResult.OriginalName} ({oResult.Count})]")
Next
Finally
TreeList_Cockpit.EndUpdate()
End Try
TreeList_Cockpit.Refresh()
LOGGER.Debug("AppendCountsToTreeAsync: Finished")
Decide_Show_Empty_Workflows(Not CONFIG.Config.Hide_Empty_Workflows)
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Function IsPositionVisible(position As System.Drawing.Point) As Boolean
For Each scr As Screen In Screen.AllScreens
If scr.WorkingArea.Contains(position) Then
Return True ' Punkt ist auf diesem Bildschirm sichtbar
End If
Next
Return False ' Punkt ist außerhalb aller sichtbaren Bereiche
End Function
Public Class FontSetting
Public Property Title As String
Public Property Value As Integer
Public Overrides Function ToString() As String
Return Title
End Function
End Class
Sub Check_Timer_Notification()
Try
If CONFIG.Config.ReminderTimer <> 0 Then
TimerReminder.Stop()
TimerReminder.Interval = CONFIG.Config.ReminderTimer * 60000
TimerReminder.Start()
Else
TimerReminder.Enabled = False
TimerReminder.Stop()
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Public Sub Timer_Inactivity_Reset_Disable(pTrigger As String)
Try
If Timer5Mins_running = True Or TimerRefresh_running = True Or FormShown = False Then
Exit Sub
End If
If INACTIVITY_DURATION <> 0 Then
TimerInactivity.Enabled = False
TimerInactivity.Stop()
TimerInactivity.Interval = INACTIVITY_DURATION * 60000
TimerInactivity.Enabled = True
TimerInactivity.Start()
bsiInactivityCheck.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Dim StartTime As DateTime = #12:00:00 AM#
Dim oStarttime As DateTime = Now
oStarttime = oStarttime.AddMinutes(INACTIVITY_DURATION)
If LOGCONFIG.Debug = False Then
pTrigger = ""
Else
pTrigger = $"({pTrigger})"
End If
bsiInactivityCheck.Caption = String.Format(S.Nächste_Aktivitätsüberprüfung___0___1_, oStarttime.ToShortTimeString, pTrigger)
Else
TimerInactivity.Enabled = False
TimerInactivity.Stop()
bsiInactivityCheck.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Sub Restore_Form_Position()
Try
'Sind Werte hinterlegt?
If My.Settings.frmMainPosition.IsEmpty = False Then
If My.Settings.frmMainPosition.X > 0 And My.Settings.frmMainPosition.Y > 0 Then
If Not My.Settings.frmMainSize.IsEmpty Then
If My.Settings.frmMainWindowState = "Normal" Then
Dim oisonscreen = IsOnScreen(My.Settings.frmMainPosition, My.Settings.frmMainSize)
If oisonscreen = False Then
Me.StartPosition = FormStartPosition.CenterScreen
Exit Sub
Else
' Gespeicherte Werte verwenden
Me.Location = Screen.AllScreens(UBound(Screen.AllScreens)).Bounds.Location + My.Settings.frmMainPosition
End If
Else
Me.WindowState = FormWindowState.Maximized
End If
End If
Else
LOGGER.Info("FormPosition is out of range!..Standard will be loaded!")
If My.Settings.frmMainWindowState = "Normal" Then
Me.StartPosition = FormStartPosition.CenterScreen
Else
Me.WindowState = FormWindowState.Maximized
End If
End If
End If
'Sind Werte hinterlegt?
'If Not My.Settings.frmMainSize.IsEmpty Then
' If My.Settings.frmMainWindowState = "Normal" Then
' Dim oisonscreen = IsOnScreen(My.Settings.frmMainPosition, My.Settings.frmMainSize)
' If oisonscreen = False Then
' Me.StartPosition = FormStartPosition.CenterScreen
' Exit Sub
' End If
' ' Gespeicherte Werte verwenden
' Try
' Me.Size = My.Settings.frmMainSize
' Catch ex As Exception
' End Try
' Else
' Me.WindowState = FormWindowState.Maximized
' End If
'End If
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Error in Load FormLayout: " & ex.Message)
End Try
End Sub
Function IsOnScreen(ByVal RecLocation As System.Drawing.Point, ByVal RecSize As System.Drawing.Size, Optional MinPercentOnScreen As Double = 0.2)
Try
Dim PixelsVisible As Double = 0
Dim Rec As System.Drawing.Rectangle = New System.Drawing.Rectangle(RecLocation, RecSize)
For Each Scrn As Screen In Screen.AllScreens
Dim r As System.Drawing.Rectangle = System.Drawing.Rectangle.Intersect(Rec, Scrn.WorkingArea)
'intersect rectangle with screen
If (r.Width <> 0 And r.Height <> 0) Then
PixelsVisible += (r.Width * r.Height)
'tally visible pixels
End If
Next
Return PixelsVisible >= (Rec.Width * Rec.Height) * MinPercentOnScreen
Catch ex As Exception
Return False
End Try
End Function
Private Function GetLayoutName_GridMain()
Dim oLoadTypeSuffix As String = GRID_LOAD_TYPE
' Bei mehreren Gesamtübersichten die COCKPIT_CONFIG_ID als Suffix anhängen
If GRID_LOAD_TYPE = "OVERVIEW" AndAlso COCKPIT_CONFIG_ID > 0 Then
oLoadTypeSuffix = $"OVERVIEW_{COCKPIT_CONFIG_ID}"
End If
Dim Filename As String = String.Format("DevExpressGridViewOverview_UserLayout_{0}_{1}.xml", oLoadTypeSuffix, USER_LANGUAGE)
LOGGER.Debug($"LayoutFilename is: {Filename}")
Return System.IO.Path.Combine(USER_CONFIG_DIRECTORY, Filename)
End Function
Private Sub SaveGridLayout()
Timer_Inactivity_Reset_Disable("SaveGridLayout")
If NO_WORKFLOW_ITEMS = True Then
Exit Sub
End If
Try
Dim oXmlPath As String = GetLayoutName_GridMain()
GridViewWorkflows.SaveLayoutToXml(oXmlPath, OptionsLayoutBase.FullLayout)
LOGGER.Debug("Layout saved successfully!")
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Error while saving GridLayout MainGrid: " & ex.Message)
End Try
End Sub
Private Sub RestoreLayout()
If NO_WORKFLOW_ITEMS = True Then
Exit Sub
End If
Try
Dim oXmlPath As String = GetLayoutName_GridMain()
If System.IO.File.Exists(oXmlPath) Then
GridViewWorkflows.RestoreLayoutFromXml(oXmlPath, OptionsLayoutBase.FullLayout)
Else
LOGGER.Info("oXmlPath not existing - Saving Layout")
COLUMNS_INVISIBLE()
SaveGridLayout()
End If
Catch ex As Exception
LOGGER.Info("Error while restoring layout MainGrid: " & ex.Message)
End Try
End Sub
Private Sub COLUMNS_INVISIBLE()
Try
If GridViewWorkflows.Columns.Count = 0 Then
Exit Sub
End If
' Sichere Prüfung für jede Spalte
If GridViewWorkflows.Columns.ColumnByFieldName("PROFILE_ID") IsNot Nothing Then
GridViewWorkflows.Columns.Item("PROFILE_ID").Visible = False
End If
If GridViewWorkflows.Columns.ColumnByFieldName("GUID") IsNot Nothing Then
GridViewWorkflows.Columns.Item("GUID").Visible = False
End If
Try
If GridViewWorkflows.Columns.ColumnByFieldName(FullFilepatColName) IsNot Nothing Then
GridViewWorkflows.Columns.Item(FullFilepatColName).Visible = False
End If
Catch ex As Exception
End Try
Try
If GridViewWorkflows.Columns.ColumnByFieldName("TL_STATE") IsNot Nothing Then
GridViewWorkflows.Columns.Item("TL_STATE").Visible = False
End If
Catch ex As Exception
End Try
Try
If GridViewWorkflows.Columns.ColumnByFieldName("CONV_YN") IsNot Nothing Then
GridViewWorkflows.Columns.Item("CONV_YN").Visible = False
End If
Catch ex As Exception
End Try
Catch ex As Exception
LOGGER.Warn($"Error in COLUMNS_INVISIBLE: {ex.Message}")
End Try
End Sub
Private Sub ResetLayout()
Try
Timer_Inactivity_Reset_Disable("ResetLayout")
Dim xml As String = GetLayoutName_GridMain()
IO.File.Delete(xml)
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
If IsNothing(GridViewWorkflows) Then
LOGGER.Warn("⚠️ Somehow GridViewWorkflows is nothing....")
Else
If IsNothing(GridViewWorkflows.Columns) Then
LOGGER.Warn("⚠️ Somehow GridViewWorkflows.Columns is nothing....")
End If
End If
Exit Sub
End Try
GridViewWorkflows.PopulateColumns()
If GridViewWorkflows.Columns.Count > 0 Then
Try
If TL_ICON = True Then
GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24
GridViewWorkflows.Columns.Item("ICON").MinWidth = 24
GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White
GridViewWorkflows.Columns.Item("ICON").Fixed = FixedStyle.Left
End If
Catch ex As Exception
End Try
'If IDB_ACTIVE = True Then
' Try
' If GridViewWorkflows.Columns.Item("CONV_YN") IsNot Nothing Then
' GridViewWorkflows.Columns.Item("CONV_YN").Visible = False
' End If
' Catch ex As Exception
' LOGGER.Info("ResetLayout - Check wether Column CONV_YN is part of select/view..now checking CONVERSATION")
' End Try
' Try
' GridViewWorkflows.Columns.Item("CONVERSATION").MaxWidth = 24
' GridViewWorkflows.Columns.Item("CONVERSATION").MinWidth = 24
' GridViewWorkflows.Columns.Item("CONVERSATION").Fixed = FixedStyle.Left
' Catch ex As Exception
' LOGGER.Info("ResetLayout - Column CONVERSATION obviously is not part of GridViewWorkflows")
' End Try
'End If
Dim oReducedColName As String
If Not IsNothing(GridViewWorkflows.Columns) Then
Try
oReducedColName = LAST_EDITED_COLUMN.Replace("[", "")
oReducedColName = oReducedColName.Replace("]", "")
'GridViewWorkflows.Columns(oReducedColName).DisplayFormat.FormatType = FormatType.DateTime
'GridViewWorkflows.Columns(oReducedColName).DisplayFormat.FormatString = "dd.MM.yyyy HH:MM:ss"
Catch ex As Exception
Try
If oReducedColName <> "Zuletzt bearbeitet" Then
End If
Catch ex1 As Exception
LOGGER.Warn($"(ResetLayout)Column [{oReducedColName}] or [Zuletzt bearbeitet] not part of OverviewSQL")
End Try
End Try
End If
Try
GridViewWorkflows.Columns.Item("GROUP_TEXT").Visible = False
GridViewWorkflows.Columns.Item("GROUP_COLOR").Visible = False
Catch ex As Exception
End Try
Try
If GridViewWorkflows.Columns.ColumnByFieldName("ROW_COLOR") IsNot Nothing Then
GridViewWorkflows.Columns.Item("ROW_COLOR").Visible = False
End If
Catch ex As Exception
End Try
' GridViewWorkflows.OptionsView.ShowIndicator = False
COLUMNS_INVISIBLE()
End If
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Error while resetting layout: " & ex.Message)
End Try
End Sub
'Sub LoadNavBar()
' Dim profileGroupOpen As Boolean = False
' If Not IsNothing(CurrNavBarGroup) Then
' NavBarControl1.BeginUpdate() ' <-- Hinzufügen
' Try
' profileGroupOpen = CurrNavBarGroup.Expanded
' Try
' CurrNavBarGroup.ItemLinks.Clear()
' Catch ex As Exception
' LOGGER.Error(ex)
' LOGGER.Info("CurrGroupClear - Error: " & ex.Message)
' End Try
' Catch ex As Exception
' Finally
' NavBarControl1.EndUpdate() ' <-- Hinzufügen
' End Try
' End If
' Try
' If Load_Profiles_for_User() = False Then
' Throw New Exception("Could not load Profiles. Datatable is empty")
' Exit Sub
' End If
' If NO_DETAIL_PROFILES = False Then
' NavBarControl1.Visible = True
' Dim oCountItems As Integer = 0
' For Each oProfileRow As DataRow In CURR_DT_VWPM_PROFILE_ACTIVE.Rows
' Dim ODisplayMode = oProfileRow.Item("DISPLAY_MODE")
' If (ODisplayMode = "Overview and Detail" Or ODisplayMode = "Detail") Then
' oCountItems += 1
' Dim item1 As NavBarItem = NavBarControl1.Items.Add()
' item1.Caption = oProfileRow.Item("TITLE")
' item1.Hint = oProfileRow.Item("TITLE")
' item1.Appearance.TextOptions.WordWrap = WordWrap.Wrap
' item1.Tag = "itmProfile#" & oProfileRow.Item("GUID").ToString
' Dim _image As Image = Nothing
' _image = DevExpress.Images.ImageResourceCache.Default.GetImage("images/business%20objects/bofileattachment_16x16.png")
' item1.LargeImage = _image
' item1.SmallImage = _image
' NavBarControl1.Groups(1).ItemLinks.Add(item1)
' End If
' Next
' If oCountItems > 0 Then
' If NavBarControl1.Groups(1).Visible = False Then
' NavBarControl1.Groups(1).Visible = True
' End If
' Else
' If NavBarControl1.Groups(1).Visible = True Then
' NavBarControl1.Groups(1).Visible = False
' End If
' End If
' If Not IsNothing(CurrNavBarGroup) Then
' CurrNavBarGroup.Expanded = profileGroupOpen
' Else
' NavBarControl1.Groups(1).Expanded = True
' End If
' Else
' LOGGER.Debug("NavBarControl - No Detail Profiles")
' NavBarControl1.Visible = False
' End If
' Catch ex As Exception
' LOGGER.Error(ex)
' LOGGER.Info("Load_Profile_items - Error: " & ex.Message)
' 'MsgBox("Unexpected Error in Load_Profile_items - Error: " & vbNewLine & ex.Message, MsgBoxStyle.Critical)
' End Try
'End Sub
'Private Async Sub navBar_LinkClicked(ByVal sender As Object, ByVal e As NavBarLinkEventArgs)
' If Application.OpenForms().OfType(Of frmValidator).Any Then
' FormHelper.ShowInfoMessage(S.Bitte_schließen_Sie_den_offenen_Workflow_, omsgTitleWarning)
' Exit Sub
' End If
' FRONTEND_ACTION = NAVBAR_CLICKED
' Dim _tag = e.Link.Item.Tag
' Timer_Inactivity_Reset_Disable("navBar_LinkClicked")
' Try
' If Not IsNothing(_tag) Then
' If _tag.ToString.Contains("itmProfile#") Then
' ' ========== PROFIL WURDE GEKLICKT ==========
' _tag = _tag.ToString.Replace("itmProfile#", "")
' If IsNumeric(_tag) Then
' If CURRENT_CLICKED_PROFILE_ID <> _tag Then
' LOGGER.Debug($"Profile with ID {_tag} clicked in NavBarControl...loading Profile...")
' OverviewOrDEtail = "DETAIL"
' If Not Application.OpenForms().OfType(Of frmValidator).Any Then
' CURRENT_CLICKED_PROFILE_ID = _tag
' CURRENT_CLICKED_PROFILE_TITLE = e.Link.Item.Caption
' End If
' GRID_LOAD_TYPE = "PROFILE#" & _tag.ToString
' DetailLinkActive = True
' ' RefreshHelper VORHER speichern
' If GridControlWorkflows.Visible = True And FormOpenClose = False Then
' RefreshHelper.SaveViewInfo()
' End If
' Me.Cursor = Cursors.WaitCursor
' Try
' LOGGER.Debug($"Loading profile with ID {_tag}...")
' ' Zentral über Decide_Load laden
' Await Decide_Load(False, True)
' Finally
' Me.Cursor = Cursors.Default
' End Try
' Else
' LOGGER.Debug($"Profile with ID {_tag} clicked in NavBarControl is already active...ignoring click.")
' End If
' End If
' ElseIf _tag = "OVERVIEW" Then
' ' ========== OVERVIEW WURDE GEKLICKT ==========
' OverviewOrDEtail = "OVERVIEW"
' GRID_LOAD_TYPE = "OVERVIEW"
' Dim oForce As Boolean = False
' If DetailLinkActive = True Then
' oForce = True
' DetailLinkActive = False
' OVERVIEW_ADDED_WHEN = ""
' End If
' ' RefreshHelper VORHER speichern
' If GridControlWorkflows.Visible = True And FormOpenClose = False Then
' RefreshHelper.SaveViewInfo()
' End If
' ' Zentral über Decide_Load laden
' Await Decide_Load(False, oForce)
' ' RefreshHelper NACHHER laden
' If GridControlWorkflows.Visible = True And FormOpenClose = False Then
' RefreshHelper.LoadViewInfo()
' End If
' ' Gruppierung prüfen
' If GridViewWorkflows.GroupCount = 0 And Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then
' LOGGER.Info("NO GROUPS AFTER CLICK OVERVIEW...CREATING GROUPS NEW...")
' Await Decide_Load(False, True)
' If GridControlWorkflows.Visible = True And FormOpenClose = False Then
' RefreshHelper.LoadViewInfo()
' End If
' End If
' End If
' End If
' Catch ex As Exception
' LOGGER.Error(ex)
' FormHelper.ShowInfoMessage($"Fehler beim Laden: {ex.Message}", omsgTitleWarning)
' Finally
' FRONTEND_ACTION = FA_NONE
' End Try
'End Sub
Function Load_Profiles_for_User() As Boolean
Try
LOGGER.Debug($"Load_Profiles_for_User ...")
If IsNothing(CURR_DT_VWPM_PROFILE_ACTIVE) Then
LOGGER.Info($"ATTENTION: CURR_DT_VWPM_PROFILE_ACTIVE is nothing!")
Return False
End If
LOGGER.Debug($"Load_Profiles_for_User: Current datatable has {CURR_DT_VWPM_PROFILE_ACTIVE.Rows.Count} rows")
Return True
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Load_Profiles_for_User - Error: " & ex.Message)
Return False
End Try
End Function
Sub GridControlWorkflows_Visible()
Try
If GridControlWorkflows.Visible = False Then
GridControlWorkflows.Visible = True
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Async Function Load_single_Profile(Optional ForceReload As Boolean = False) As Tasks.Task
Dim gridUpdateStarted As Boolean = False
Dim viewUpdateStarted As Boolean = False
Try
FRONTEND_ACTION = "Load_single_Profile"
Load_Profiles_for_User()
GridControlWorkflows_Visible()
Dim expression As String = "GUID = " & CURRENT_CLICKED_PROFILE_ID
Dim foundRow As DataRow = CURR_DT_VWPM_PROFILE_ACTIVE.Select(expression).FirstOrDefault()
If foundRow Is Nothing Then
Exit Function
End If
If GridControlWorkflows.Visible Then
GridControlWorkflows.BeginUpdate()
gridUpdateStarted = True
GridViewWorkflows.BeginUpdate()
viewUpdateStarted = True
End If
Dim oSQL = foundRow.Item("SQL_VIEW")
oSQL = clsPatterns.ReplaceInternalValues(oSQL)
oSQL = clsPatterns.ReplaceUserValues(oSQL)
oSQL = oSQL.Replace("@USER_ID", USER_ID)
oSQL = oSQL.Replace("@USERNAME", USER_USERNAME)
oSQL = oSQL.Replace("@MACHINE_NAME", System.Environment.MachineName)
oSQL = oSQL.Replace("@DATE", Now.ToShortDateString)
oSQL = oSQL.Replace("@PROFILE_ID", CURRENT_CLICKED_PROFILE_ID)
DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQL)
If IsNothing(DT_CURR_WF_ITEMS) Then
Exit Function
End If
Dim oADDED = GET_LAST_ADDED(DT_CURR_WF_ITEMS)
Dim oChanged = GET_LAST_CHANGED(DT_CURR_WF_ITEMS)
Dim oCOUNT = DT_CURR_WF_ITEMS.Rows.Count
' Workflowitems-Status setzen
NO_WORKFLOW_ITEMS = (oCOUNT = 0)
' Caption IMMER aktualisieren (vor Hash-Prüfung!)
UpdateGridCaption()
' Datenquelle bei leeren Items zurücksetzen
If NO_WORKFLOW_ITEMS Then
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Exit Function
End If
' Hash-Prüfung für Performance-Optimierung
If ForceReload = False Then
If oADDED = OVERVIEW_ADDED_WHEN And oChanged = OVERVIEW_CHANGED_WHEN And OVERVIEW_COUNT = oCOUNT Then
LOGGER.Debug("No data changes - skipping grid reload")
Exit Function
End If
OVERVIEW_ADDED_WHEN = oADDED
OVERVIEW_CHANGED_WHEN = oChanged
OVERVIEW_COUNT = oCOUNT
End If
Create_Basic_View()
RestoreLayout()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Load_single_Profile - Error: " & ex.Message)
Finally
If viewUpdateStarted Then
GridViewWorkflows.EndUpdate()
End If
If gridUpdateStarted Then
GridControlWorkflows.EndUpdate()
End If
FRONTEND_ACTION = FA_NONE
End Try
End Function
Sub Create_Basic_View()
Dim gridUpdateStarted As Boolean = False
Dim viewUpdateStarted As Boolean = False
Try
FRONTEND_ACTION = "Create_Basic_View"
If GridControlWorkflows.Visible Then
GridControlWorkflows.BeginUpdate()
gridUpdateStarted = True
GridViewWorkflows.BeginUpdate()
viewUpdateStarted = True
End If
GridControlWorkflows.DataSource = Nothing
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Warn("⚠️ Could not clear GridViewWorkflows.Columns")
End Try
' Prüfen, ob TL_STATE-Spalte vorhanden ist
Dim hasTLStateColumn As Boolean = False
If DT_CURR_WF_ITEMS IsNot Nothing Then
hasTLStateColumn = DT_CURR_WF_ITEMS.Columns.Contains("TL_STATE")
End If
' ICON-Spalte nur hinzufügen, wenn TL_ICON aktiv UND TL_STATE verfügbar ist
If TL_ICON = True AndAlso hasTLStateColumn AndAlso DT_CURR_WF_ITEMS IsNot Nothing AndAlso DT_CURR_WF_ITEMS.Columns.Contains("ICON") = False Then
Dim columnStateIcon As New DataColumn() With {
.DataType = GetType(Image),
.ColumnName = "ICON",
.Caption = ""
}
DT_CURR_WF_ITEMS.Columns.Add(columnStateIcon)
End If
RedDocuments = 0
YellowDocuments = 0
GreenDocuments = 0
' Icons nur setzen, wenn TL_STATE-Spalte vorhanden ist
If TL_ICON = True AndAlso hasTLStateColumn AndAlso DT_CURR_WF_ITEMS IsNot Nothing Then
Try
For Each row As DataRow In DT_CURR_WF_ITEMS.Rows
Dim State As Integer = CInt(row.Item("TL_STATE"))
Select Case State
Case 1
RedDocuments += 1
row.Item("ICON") = My.Resources.bullet_red
Case 2
YellowDocuments += 1
row.Item("ICON") = My.Resources.bullet_orange
Case 3
GreenDocuments += 1
row.Item("ICON") = My.Resources.bullet_green
End Select
Next
Catch ex As Exception
LOGGER.Warn($"Could not set ICON values: {ex.Message}")
End Try
ElseIf TL_ICON = True AndAlso Not hasTLStateColumn Then
LOGGER.Warn("⚠️ TL_ICON is enabled but TL_STATE column is missing in dataset")
End If
bindsourcegrid.DataSource = DT_CURR_WF_ITEMS
GridControlWorkflows.DataSource = bindsourcegrid
RestoreLayout()
COLUMNS_INVISIBLE()
Try
If TL_ICON = True AndAlso GridViewWorkflows.Columns.Count > 0 AndAlso GridViewWorkflows.Columns.ColumnByFieldName("ICON") IsNot Nothing Then
GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24
GridViewWorkflows.Columns.Item("ICON").MinWidth = 24
GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White
GridViewWorkflows.Columns.Item("ICON").Fixed = FixedStyle.Left
End If
Catch ex As Exception
LOGGER.Warn($"Could not configure ICON column: {ex.Message}")
End Try
Try
Dim oReducedColName = LAST_EDITED_COLUMN.Replace("[", "").Replace("]", "")
Catch ex As Exception
Try
Catch ex1 As Exception
LOGGER.Warn("⚠️ (CreateBasicView)Column [Last edited] or [Zuletzt bearbeitet] not part of OverviewSQL")
End Try
End Try
Try
If GridViewWorkflows.Columns.ColumnByFieldName("GROUP_TEXT") IsNot Nothing Then
GridViewWorkflows.Columns.Item("GROUP_TEXT").Visible = False
End If
If GridViewWorkflows.Columns.ColumnByFieldName("GROUP_COLOR") IsNot Nothing Then
GridViewWorkflows.Columns.Item("GROUP_COLOR").Visible = False
End If
Catch ex As Exception
If OverviewOrDEtail = "OVERVIEW" Then
LOGGER.Warn("⚠️ ATTENTION: GROUP COLUMNS NOT PART OF GRID")
End If
End Try
Catch ex As Exception
LOGGER.Error(ex)
Finally
If viewUpdateStarted Then
GridViewWorkflows.EndUpdate()
End If
If gridUpdateStarted Then
GridControlWorkflows.EndUpdate()
End If
FRONTEND_ACTION = FA_NONE
End Try
End Sub
Private Function GridLayoutChanged() As Boolean
Try
For Each oViewColumn As DataColumn In DT_CURR_WF_ITEMS.Columns
If oViewColumn.Caption = "" Then
Continue For
End If
Dim oViewColumn_exists As Boolean = False
For Each oActGridColumn As GridColumn In GridViewWorkflows.Columns
Dim oGridDXFieldName = oActGridColumn.FieldName
Dim GridDXColumnEditName = oActGridColumn.ColumnEditName
Dim GridDXFieldName = oActGridColumn.FieldName
If oViewColumn.Caption = oGridDXFieldName Then
If oActGridColumn.Visible = False Then
If oViewColumn.Caption <> "GUID" And oViewColumn.Caption <> "TL_STATE" And oViewColumn.Caption <> "PROFILE_ID" And oViewColumn.Caption <> "DocID" And
oViewColumn.Caption <> "GROUP_COLOR" And oViewColumn.Caption <> "GROUP_TEXT" Then 'And oViewColumn.Caption <> "CONV_YN"
Console.WriteLine($"ViewColumn [{oViewColumn.Caption}] is invisible")
Else
oViewColumn_exists = True
End If
Else
oViewColumn_exists = True
End If
End If
Next
If oViewColumn_exists = False Then
If oViewColumn.Caption = FullFilepatColName And IDB_ACTIVE = False Then
LOGGER.Info($"Following ViewColumn no longer exists in the view: [{oViewColumn.Caption}]")
Return True
End If
End If
Next
For Each oActGridColumn As GridColumn In GridViewWorkflows.Columns
If oActGridColumn.Caption = "" Then
Continue For
End If
Dim oGridColumn_exists As Boolean = False
Dim oGridDXFieldName = oActGridColumn.FieldName
For Each oViewColumn As DataColumn In DT_CURR_WF_ITEMS.Columns
If oViewColumn.Caption = oGridDXFieldName Then
oGridColumn_exists = True
End If
Next
If oGridColumn_exists = False Then
LOGGER.Info($"Following GridColumn no longer exists in the View: [{oGridDXFieldName}]")
Return True
End If
Next
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Unexpected Error in GridLayoutChanged: " & ex.Message)
Return False
End Try
End Function
Private Function Column_inGridViewLayout(Col2bChecked As String) As Boolean
Try
Dim oGridView As New GridView
Dim oXml As String = GetLayoutName_GridMain()
oGridView.RestoreLayoutFromXml(oXml, OptionsLayoutBase.FullLayout)
Dim oViewColumn_exists As Boolean = False
For Each oActGridColumn As GridColumn In oGridView.Columns
Dim oGridDXFieldName = oActGridColumn.FieldName
Dim GridDXColumnEditName = oActGridColumn.ColumnEditName
Dim GridDXFieldName = oActGridColumn.FieldName
If Col2bChecked = oGridDXFieldName Then
oViewColumn_exists = True
Exit For
End If
Next
If oViewColumn_exists = False Then
LOGGER.Info($"Following ViewColumn is not existing in the view: [{Col2bChecked}]")
Return Not False
End If
Catch ex As Exception
LOGGER.Info("Unexpected Error in Column_inGridViewLayout: " & ex.Message)
Return Not False
End Try
End Function
Private Sub NotifyIcon1_MouseDoubleClick(sender As System.Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
BringMonitor2Front()
End Sub
Sub BringMonitor2Front()
Me.BringToFront()
Visible = True
End Sub
Private Async Sub TimerRefresh_Tick(sender As System.Object, e As EventArgs) Handles TimerRefresh.Tick
Try
If TimerRefresh.Enabled = False Then
Exit Sub
End If
If bwBasicData.IsBusy Then
LOGGER.Info("backGroundWorker BasicData in Action - no Client-Sync")
bsiMessage.Caption = "bwBasicData is busy - no Refreshing"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Exit Sub
End If
TimerRefresh_running = True
LOGGER.Debug("TimerRefresh_Tick started")
' Cancel Refresh if a Validator Form or an Admin Form is opened
If Application.OpenForms().OfType(Of frmMassValidator).Any() Or
Application.OpenForms().OfType(Of frmValidator).Any() Or
Application.OpenForms().OfType(Of frmAdministration).Any() Or
Application.OpenForms().OfType(Of frmAdmin2).Any() Then
Exit Sub
End If
'bsilastsync.Caption = $"{ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("CaptLastSync")}: " & Now.ToLongTimeString
bsilastsync.Caption = String.Format(S.Letzte_Synchronisation___0_, Now.ToLongTimeString)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.SaveViewInfo()
End If
If bwSync.IsBusy Then
TimerRefresh_running = False
Exit Sub
End If
Try
'LoadNavBar()
Dim oStopWatch As New RefreshHelper.SW("Decide_Load")
Await Decide_Load(False)
oStopWatch.Done()
'bwSync.ReportProgress(95)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo()
' ===== TREELIST COUNTS AKTUALISIEREN =====
' Nur ausführen wenn TreeList Knoten mit SQL_QUERY_COUNT vorhanden sind
Dim oDatasource As DataTable = TryCast(TreeList_Cockpit.DataSource, DataTable)
If oDatasource IsNot Nothing AndAlso oDatasource.Columns.Contains("SQL_QUERY_COUNT") Then
LOGGER.Debug("TimerRefresh_Tick: Refreshing TreeList node counts...")
AppendCountsToTreeAsync()
End If
Handling_DEBUG_USER()
Catch ex As Exception
LOGGER.Error(ex)
End Try
Catch ex As Exception
LOGGER.Error(ex)
End Try
TimerRefresh_running = False
'BarEditItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
'' call this method to start your asynchronous Task.
'bwSync.RunWorkerAsync()
End Sub
Private Sub NotifyIcon1_Click(sender As System.Object, e As EventArgs) Handles NotifyIcon1.Click
BringMonitor2Front()
End Sub
' ========================================
' HAUPTLADEMETHODE - Koordiniert den gesamten Ladevorgang
' ========================================
Private Async Function Decide_Load(pIsFormLoad As Boolean, Optional ForceReload As Boolean = False) As Tasks.Task
Dim oHandle As Object = Nothing
Dim overlayStartedHere As Boolean = False
' Overlay nur anzeigen, wenn die Anwendung aktuell den Fokus hat
Dim appHasFocus As Boolean = Application.OpenForms().Cast(Of Form)().Any(Function(f) f.ContainsFocus)
If Not _overlayActive AndAlso appHasFocus Then
oHandle = SplashScreenManager.ShowOverlayForm(Me)
_overlayActive = True
overlayStartedHere = True
Else
LOGGER.Debug("Overlay wird nicht angezeigt, da bereits aktiv oder Anwendung keinen Fokus hat.")
End If
Dim perfStart As DateTime = DateTime.MinValue
Dim refreshWasEnabled As Boolean = False
If LOG_HOTSPOTS Then
perfStart = DateTime.Now
LOGGER.Info($"[PERF Decide_Load] START - pIsFormLoad:[{pIsFormLoad}] ForceReload:[{ForceReload}] GRID_LOAD_TYPE:[{GRID_LOAD_TYPE}]")
End If
Try
LOGGER.Debug($"Decide_Load: pIsFormLoad [{pIsFormLoad}] - ForceReload [{ForceReload}] - GRID_LOAD_TYPE [{GRID_LOAD_TYPE}]")
' ========== VORBEDINGUNGEN PRÜFEN ==========
If pIsFormLoad = True Then
FormShown = False
End If
GridIsLoaded = False
If USER_EXISTS = False Then
LOGGER.Warn($"USER IS NOT EXISTING - CHECK FNDD_LOGIN_USER_MODULE")
Exit Function
End If
' ========== TIMER MANAGEMENT ==========
If TimerRefresh.Enabled Then
refreshWasEnabled = True
TimerRefresh.Stop()
End If
FRONTEND_ACTION = "DECIDE_LOAD"
' ========== UI VORBEREITEN (NUR BEI OVERVIEW) ==========
Dim loadSuccess As Boolean = False
If GRID_LOAD_TYPE = "OVERVIEW" Then
If LOG_HOTSPOTS Then
LOGGER.Info("[PERF Decide_Load] ruft LoadOverviewData auf...")
End If
Await Task.Yield()
' Daten laden
loadSuccess = Await LoadOverviewData(pIsFormLoad, ForceReload)
ElseIf GRID_LOAD_TYPE.StartsWith("PROFILE#") Then
If LOG_HOTSPOTS Then
LOGGER.Info("[PERF Decide_Load] ruft LoadProfileData auf...")
End If
Await Task.Yield()
' Daten laden
loadSuccess = Await LoadProfileData(ForceReload)
End If
If Not loadSuccess Then
If GRID_LOAD_TYPE <> "OVERVIEW" Then
LOGGER.Warn($"LoadProfileData for Profile-ID [{CURRENT_CLICKED_PROFILE_ID}] - Title [{CURRENT_CLICKED_PROFILE_TITLE}] failed or has no Data - exiting Decide_Load")
Else
LOGGER.Warn($"LoadOverviewData failed or has no Data - exiting Decide_Load")
End If
Exit Function
End If
' ========== NACHBEARBEITUNG ==========
ApplyPostLoadSettings()
GridIsLoaded = True
' ========== CAPTION FINAL SICHERSTELLEN ==========
' ApplyPostLoadSettings kann durch Spalten-Events den Caption überschreiben,
' daher hier nochmals den korrekten Caption setzen
UpdateGridCaption()
Catch ex As Exception
GridIsLoaded = True
LOGGER.Error(ex)
LOGGER.Info("Unexpected error in Decide_load: " & ex.Message)
Finally
FRONTEND_ACTION = FA_NONE
If overlayStartedHere Then
_overlayActive = False
SplashScreenManager.CloseOverlayForm(oHandle)
End If
If refreshWasEnabled Then
TimerRefresh.Start()
End If
If pIsFormLoad = True Then
FormShown = True
End If
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF Decide_Load] GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms")
End If
End Try
End Function
' ========================================
' OVERVIEW DATEN LADEN - Spezialisiert auf Overview
' ========================================
Private Async Function LoadOverviewData(pFormLoad As Boolean, pForceReload As Boolean) As Task(Of Boolean)
Dim perfStart As DateTime = DateTime.MinValue
Dim perfStep As DateTime = DateTime.MinValue
Dim gridUpdateStarted As Boolean = False
Dim viewUpdateStarted As Boolean = False
If LOG_HOTSPOTS Then
perfStart = DateTime.Now
perfStep = perfStart
LOGGER.Info($"[PERF LoadOverviewData] START - pFormLoad:[{pFormLoad}] pForceReload:[{pForceReload}]")
End If
Try
GridControlWorkflows_Visible()
' ========== GRID UPDATES VORBEREITEN ==========
If GridControlWorkflows.Visible Then
GridControlWorkflows.BeginUpdate()
gridUpdateStarted = True
GridViewWorkflows.BeginUpdate()
viewUpdateStarted = True
End If
' ========== PROFILE VALIDIEREN ==========
If BASEDATA_DT_VW_PROFILE_USER.Rows.Count = 0 Then
LOGGER.Info("Attention: No profiles for user: '" & USER_USERNAME & "' configured!", False)
NO_WORKFLOW_ITEMS = True
bsiMessage.Caption = "NO PROFILES FOR USER"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
GridControlWorkflows.Visible = False
Return False
End If
If LOG_HOTSPOTS Then
LOGGER.Debug($"[PERF LoadOverviewData] Load_Profiles_for_User wird aufgerufen...")
End If
Load_Profiles_for_User()
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ Load_Profiles_for_User LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LoadOverviewData] Load_Profiles_for_User: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== SQL VORBEREITEN ==========
Dim oSQLOverview As String
Dim isCustomSQL As Boolean = False
If Not String.IsNullOrWhiteSpace(CUSTOM_OVERVIEW_SQL) Then
LOGGER.Debug($"[LoadOverviewData] Using CUSTOM_OVERVIEW_SQL from TreeList node [{CUSTOM_OVERVIEW_SQL}]")
oSQLOverview = CUSTOM_OVERVIEW_SQL
isCustomSQL = True
ElseIf Not String.IsNullOrWhiteSpace(_lastUsedOverviewSQL) Then
LOGGER.Debug($"[LoadOverviewData] CUSTOM_OVERVIEW_SQL is empty - using _lastUsedOverviewSQL (e.g. after ValidatorClosed)")
oSQLOverview = _lastUsedOverviewSQL
isCustomSQL = True
Else
oSQLOverview = BASEDATA_DT_CONFIG.Rows(0).Item("SQL_PROFILE_MAIN_VIEW")
End If
If IsDBNull(oSQLOverview) Then
LOGGER.Warn("Overview SQL is Null - cannot load overview data")
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Return False
End If
' GROUP_TEXT-Prüfung nur für Standard-SQL (nicht für Custom/TreeList-SQL)
If Not isCustomSQL AndAlso Not oSQLOverview.ToString.Contains("GROUP_TEXT") Then
LOGGER.Warn("Overview SQL is not properly configured - missing GROUP_TEXT column - might not load overview data")
LOGGER.Warn($"Overview SQL so far: {oSQLOverview}")
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Return False
End If
' SQL-Platzhalter ersetzen
oSQLOverview = PrepareSQLWithReplacements(oSQLOverview, 0)
If LOG_HOTSPOTS Then
Dim rowCount = If(DT_CURR_WF_ITEMS IsNot Nothing, DT_CURR_WF_ITEMS.Rows.Count, 0)
LOGGER.Info($"[PERF LoadOverviewData] SQL-Abfrage für Workflows startet (aktuelle Rows: {rowCount})...")
End If
' ========== DATEN ABRUFEN ==========
DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQLOverview)
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
Dim rowCount = If(DT_CURR_WF_ITEMS IsNot Nothing, DT_CURR_WF_ITEMS.Rows.Count, 0)
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ Datenbank-Abfrage für Workflows LANGSAM: {elapsed}ms ({rowCount} Zeilen) (Schwellwert: 4000ms) - SQL prüfen!")
Else
LOGGER.Info($"[PERF LoadOverviewData] Datenbank-Abfrage für Workflows: {elapsed}ms ({rowCount} Zeilen)")
End If
perfStep = DateTime.Now
End If
If IsNothing(DT_CURR_WF_ITEMS) Then
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
Return False
End If
LOGGER.Debug($"Datatable CURR_DT_OVERVIEW loaded: {DT_CURR_WF_ITEMS.Rows.Count} rows")
' ========== DATEN VERARBEITEN ==========
NO_WORKFLOW_ITEMS = (DT_CURR_WF_ITEMS.Rows.Count = 0)
UpdateGridCaption()
If NO_WORKFLOW_ITEMS Then
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Return False
End If
' ========== ICON-SPALTE VORBEREITEN ==========
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF LoadOverviewData] Icon-Verarbeitung startet ({DT_CURR_WF_ITEMS.Rows.Count} Zeilen)...")
End If
Await Task.Run(Sub() PrepareIconColumn())
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ Icon-Verarbeitung LANGSAM: {elapsed}ms ({DT_CURR_WF_ITEMS.Rows.Count} Zeilen) (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LoadOverviewData] Icon-Verarbeitung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== GRID MIT DATEN FÜLLEN ==========
bindsourcegrid.DataSource = DT_CURR_WF_ITEMS
GridControlWorkflows.DataSource = bindsourcegrid
GridControlWorkflows.ForceInitialize()
Create_View_Caption()
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ Grid-DataSource-Zuweisung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LoadOverviewData] Grid-DataSource-Zuweisung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== LAYOUT ANWENDEN ==========
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF LoadOverviewData] Layout-Anwendung startet...")
End If
Await ApplyGridLayout(pForceReload)
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ Layout-Wiederherstellung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LoadOverviewData] Layout-Wiederherstellung: {elapsed}ms")
End If
End If
Return True
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("LoadOverviewData - Fehler: " & ex.Message)
Return False
Finally
' ========== AUFRÄUMEN ==========
If viewUpdateStarted Then
GridViewWorkflows.EndUpdate()
End If
If gridUpdateStarted Then
GridControlWorkflows.EndUpdate()
End If
If LOG_HOTSPOTS Then
Dim totalElapsed = (DateTime.Now - perfStart).TotalMilliseconds
If totalElapsed > 4000 Then
LOGGER.Warn($"[PERF LoadOverviewData] ⚠️ GESAMT LANGSAM: {totalElapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LoadOverviewData] GESAMT: {totalElapsed}ms")
End If
End If
End Try
End Function
' ========================================
' PROFILE DATEN LADEN - Spezialisiert auf einzelnes Profil
' ========================================
Private Async Function LoadProfileData(ForceReload As Boolean) As Task(Of Boolean)
Dim gridUpdateStarted As Boolean = False
Dim viewUpdateStarted As Boolean = False
Try
Load_Profiles_for_User()
Dim expression As String = "GUID = " & CURRENT_CLICKED_PROFILE_ID
Dim foundRow As DataRow = CURRENT_DT_PROFILES.Select(expression).FirstOrDefault()
If foundRow Is Nothing Then
LOGGER.Warn($"LoadProfileData for Profile-ID [{CURRENT_CLICKED_PROFILE_ID}] - Title [{CURRENT_CLICKED_PROFILE_TITLE}] not found - exiting")
Return False
End If
If GridControlWorkflows.Visible Then
GridControlWorkflows.BeginUpdate()
gridUpdateStarted = True
GridViewWorkflows.BeginUpdate()
viewUpdateStarted = True
End If
' ===== PRIORISIERUNG: TreeList-SQL (COCKPIT_PROFILE_SQL) VOR Datenbank-SQL (SQL_VIEW) =====
Dim oSQL As String = String.Empty
' 1⃣ ERSTE PRIORITÄT: SQL aus TreeList-Knoten
If Not String.IsNullOrWhiteSpace(COCKPIT_PROFILE_SQL) Then
oSQL = COCKPIT_PROFILE_SQL
LOGGER.Debug($"LoadProfileData: Using COCKPIT_PROFILE_SQL from TreeList node")
' 2⃣ FALLBACK: SQL aus Datenbank-Tabelle (nur wenn TreeList-SQL fehlt)
Else
oSQL = foundRow.Item("SQL_VIEW")?.ToString()
LOGGER.Debug($"LoadProfileData: SQL_VIEW from foundRow = [{oSQL}]")
' Prüfen ob SQL leer oder "select 'NONE'" ist
If String.IsNullOrWhiteSpace(oSQL) OrElse oSQL.Trim().ToUpper() = "SELECT 'NONE'" Then
LOGGER.Warn($"⚠️ LoadProfileData: Both COCKPIT_PROFILE_SQL and SQL_VIEW are empty/invalid for Profile-ID [{CURRENT_CLICKED_PROFILE_ID}]")
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Return False
End If
LOGGER.Debug($"LoadProfileData: COCKPIT_PROFILE_SQL empty - using SQL_VIEW from database as fallback")
End If
' ===== SQL NACH allen Ersetzungen loggen =====
LOGGER.Debug($"LoadProfileData: Final SQL BEFORE PrepareSQLWithReplacements: [{oSQL}]")
oSQL = PrepareSQLWithReplacements(oSQL, CURRENT_CLICKED_PROFILE_ID)
LOGGER.Debug($"LoadProfileData: Final SQL AFTER PrepareSQLWithReplacements: [{oSQL}]")
' ===== DATEN ABRUFEN =====
DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQL)
If IsNothing(DT_CURR_WF_ITEMS) Then
LOGGER.Warn($"LoadProfileData for Profile-ID [{CURRENT_CLICKED_PROFILE_ID}] - Title [{CURRENT_CLICKED_PROFILE_TITLE}] failed - exiting")
Return False
End If
' ===== DATEN VERARBEITEN =====
NO_WORKFLOW_ITEMS = (DT_CURR_WF_ITEMS.Rows.Count = 0)
UpdateGridCaption()
If NO_WORKFLOW_ITEMS Then
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
LOGGER.Info("Keine Workflow-Items für Profil: " & CURRENT_CLICKED_PROFILE_TITLE)
Return False
End If
GridControlWorkflows_Visible()
' ===== BASIC VIEW ERSTELLEN =====
Await CreateBasicViewForProfile()
LOGGER.Debug("Basic View für Profil erstellt: " & CURRENT_CLICKED_PROFILE_TITLE)
Return True
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("LoadProfileData - Error: " & ex.Message)
Return False
Finally
If viewUpdateStarted Then
GridViewWorkflows.EndUpdate()
End If
If gridUpdateStarted Then
GridControlWorkflows.EndUpdate()
End If
End Try
End Function
' ========================================
' HILFSMETHODEN - Extrahierte Logik für Wiederverwendung
' ========================================
Private Function PrepareSQLWithReplacements(oSQL As String, oProfileID As Integer) As String
oSQL = clsPatterns.ReplaceInternalValues(oSQL)
oSQL = clsPatterns.ReplaceUserValues(oSQL)
LOGGER.Debug("PrepareSQLWithReplacements - Original SQL: " & oSQL)
oSQL = oSQL.Replace("@USERNAME", USER_USERNAME)
oSQL = oSQL.Replace("@MACHINE_NAME", System.Environment.MachineName)
oSQL = oSQL.Replace("@DATE", Now.ToShortDateString)
' ===== ZUSÄTZLICHE PLATZHALTER-FORMATE FÜR USER_ID =====
oSQL = oSQL.Replace("{#USER#USER_ID}", USER_ID)
oSQL = oSQL.Replace("#USER#USER_ID", USER_ID)
oSQL = oSQL.Replace("@USER_ID", USER_ID)
LOGGER.Debug("PrepareSQLWithReplacements - SQL after replacements: " & oSQL)
If oProfileID = 0 Then
If GRID_LOAD_TYPE = "OVERVIEW" Then
LOGGER.Debug("PrepareSQLWithReplacements called with oProfileID = 0 in OVERVIEW context")
Else
LOGGER.Warn("PrepareSQLWithReplacements called with oProfileID = 0, using CURRENT_CLICKED_PROFILE_ID instead")
End If
oProfileID = CURRENT_CLICKED_PROFILE_ID
Else
LOGGER.Debug($"PrepareSQLWithReplacements called with oProfileID = {oProfileID}")
End If
oSQL = oSQL.Replace("@PROFILE_ID", oProfileID)
oSQL = oSQL.Replace("@PROFIL_ID", oProfileID)
Return oSQL
End Function
Private Sub PrepareIconColumn()
' Prüfen, ob TL_STATE-Spalte vorhanden ist
Dim hasTLStateColumn As Boolean = False
If DT_CURR_WF_ITEMS IsNot Nothing Then
hasTLStateColumn = DT_CURR_WF_ITEMS.Columns.Contains("TL_STATE")
End If
If TL_ICON = True AndAlso DT_CURR_WF_ITEMS IsNot Nothing AndAlso DT_CURR_WF_ITEMS.Columns.Contains("ICON") = False Then
Dim columnStateIcon As New DataColumn() With {
.DataType = GetType(Image),
.ColumnName = "ICON",
.Caption = ""
}
DT_CURR_WF_ITEMS.Columns.Add(columnStateIcon)
End If
RedDocuments = 0
YellowDocuments = 0
GreenDocuments = 0
If TL_ICON = True AndAlso hasTLStateColumn AndAlso DT_CURR_WF_ITEMS IsNot Nothing Then
For Each row As DataRow In DT_CURR_WF_ITEMS.Rows
Try
Dim State As Integer = CInt(row.Item("TL_STATE"))
Select Case State
Case 1
RedDocuments += 1
row.Item("ICON") = My.Resources.bullet_red
Case 2
YellowDocuments += 1
row.Item("ICON") = My.Resources.bullet_orange
Case 3
GreenDocuments += 1
row.Item("ICON") = My.Resources.bullet_green
End Select
Catch ex As Exception
LOGGER.Warn($"Could not set ICON value: {ex.Message}")
End Try
Next
ElseIf TL_ICON = True AndAlso Not hasTLStateColumn Then
LOGGER.Warn("⚠️ TL_ICON is enabled but TL_STATE column is missing in DT_CURR_WF_ITEMS")
End If
End Sub
Private Async Function ApplyGridLayout(pForceReload As Boolean) As Tasks.Task
Dim oColNotPartofLayout As Boolean = False
If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then
LOGGER.Debug("Now GridLayout_Reset..")
Await GridLayout_Reset(False)
Else
RestoreLayout()
End If
If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then
Create_GroupBy_Parts()
End If
' Icon-Spalte konfigurieren
If TL_ICON = True Then
Try
GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24
GridViewWorkflows.Columns.Item("ICON").MinWidth = 24
GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White
GridViewWorkflows.Columns.Item("ICON").Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left
Catch ex As Exception
End Try
End If
If GridViewWorkflows.Columns.Count <= 5 Then
LOGGER.Info("GridViewWorkflows.Columns.Count <= 5 - Reset_Gridlayout will be forced...", False)
Await Reset_GridLayout(False)
Else
RestoreLayout()
End If
COLUMNS_INVISIBLE()
' Spaltenformatierung anwenden
ApplyColumnFormatting()
End Function
Private Sub ApplyColumnFormatting()
Try
For Each oColumn As DevExpress.XtraGrid.Columns.GridColumn In GridViewWorkflows.Columns
For Each oRow As DataRow In BASEDATA_TBDD_COLUMNS_FORMAT.Rows
Dim colName = oRow("COLUMN_TITLE").ToString()
If oColumn.FieldName = colName Then
Dim oSollFormatType = oRow("TYPE2FORMAT").ToString()
If oSollFormatType = "DateTime" Then
If oColumn.ColumnType <> GetType(DateTime) Then
oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
End If
If oColumn.ColumnType = GetType(DateTime) And oColumn.DisplayFormat.FormatString <> "dd.MM.yyyy HH:mm:ss" Then
oColumn.DisplayFormat.FormatString = "dd.MM.yyyy HH:mm:ss"
End If
ElseIf oSollFormatType = "Numeric" Then
If oColumn.ColumnType <> GetType(Int32) Then
oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric
End If
End If
End If
Next
Next
Catch ex As Exception
LOGGER.Warn("⚠️ Fehler beim Anwenden der Formatierung aus TBDD_COLUMNS_FORMAT: " & ex.Message)
End Try
End Sub
Private Async Function CreateBasicViewForProfile() As Task
' ===== GRID DATASOURCE ZURÜCKSETZEN =====
GridControlWorkflows.DataSource = Nothing
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Warn("⚠️ Could not clear GridViewWorkflows.Columns")
End Try
' ===== ICON-SPALTE VORBEREITEN =====
Await Task.Run(Sub() PrepareIconColumn())
' ===== DATASOURCE ZUWEISEN =====
bindsourcegrid.DataSource = DT_CURR_WF_ITEMS
GridControlWorkflows.DataSource = bindsourcegrid
' ✅ KRITISCH: Grid zwingen, Columns zu erstellen BEVOR RestoreLayout
GridControlWorkflows.ForceInitialize()
' ✅ Wenn kein gespeichertes Layout existiert → Columns manuell populieren
Dim oXmlPath As String = GetLayoutName_GridMain()
If Not System.IO.File.Exists(oXmlPath) Then
LOGGER.Debug($"CreateBasicViewForProfile: No layout file found at [{oXmlPath}] - populating columns")
GridViewWorkflows.PopulateColumns()
End If
' ===== LAYOUT WIEDERHERSTELLEN =====
RestoreLayout()
COLUMNS_INVISIBLE()
' ===== GRUPPIERUNG FÜR PROFIL-ANSICHT ENTFERNEN =====
If GridViewWorkflows.GroupCount > 0 Then
LOGGER.Debug($"CreateBasicViewForProfile: Clearing [{GridViewWorkflows.GroupCount}] group(s) from restored layout for profile view")
GridViewWorkflows.ClearGrouping()
End If
' ===== ICON-SPALTE KONFIGURIEREN =====
If TL_ICON = True Then
Try
If GridViewWorkflows.Columns.ColumnByFieldName("ICON") IsNot Nothing Then
GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24
GridViewWorkflows.Columns.Item("ICON").MinWidth = 24
GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White
GridViewWorkflows.Columns.Item("ICON").Fixed = FixedStyle.Left
GridViewWorkflows.Columns.Item("ICON").VisibleIndex = 0 ' ✅ Ganz links
End If
Catch ex As Exception
LOGGER.Warn($"Could not configure ICON column: {ex.Message}")
End Try
End If
' ✅ DEBUG: Spalten-Info loggen
LOGGER.Debug($"CreateBasicViewForProfile: Grid has [{GridViewWorkflows.Columns.Count}] columns, DataSource has [{DT_CURR_WF_ITEMS.Rows.Count}] rows")
End Function
Private Sub ApplyPostLoadSettings()
If SHOW_MASS_VALIDATOR = False Then
GridViewWorkflows.OptionsSelection.MultiSelect = False
GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect
BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
Else
BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
GridViewWorkflows.OptionsSelection.MultiSelect = True
GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect
End If
If GridViewWorkflows.OptionsView.ShowAutoFilterRow = True Then
BarCheckItemAutofilter.Checked = True
End If
If GridViewWorkflows.OptionsFind.AlwaysVisible Then
BarCheckItemShowSearch.Checked = True
End If
COLUMNS_INVISIBLE()
End Sub
Private Sub ToolStripButton2_Click_2(sender As Object, e As EventArgs)
frmAdminPasswort.ShowDialog()
End Sub
Public Sub New()
Dim splash As New frmSplash()
Try
splash.ShowDialog()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info($"Error in Splash: {ex.Message}")
End Try
' LookAndFeel ZUERST global setzen
ConfigureGlobalLookAndFeel()
Try
If USER_LANGUAGE <> "" Then
Dim cultureInfo As New System.Globalization.CultureInfo(USER_LANGUAGE)
cultureInfo.DateTimeFormat.ShortDatePattern = USER_DATE_FORMAT
Thread.CurrentThread.CurrentCulture = cultureInfo
Thread.CurrentThread.CurrentUICulture = cultureInfo
CultureInfo.DefaultThreadCurrentCulture = cultureInfo
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
Try
InitializeComponent()
FormHelper = New FormHelper(LOGCONFIG, Me)
' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info($"Error in InitializeComponent: {ex.Message}")
End Try
End Sub
Private Sub TimerReminder_Tick(sender As Object, e As EventArgs) Handles TimerReminder.Tick
Try
If Application.OpenForms().OfType(Of frmValidator).Any Then
Exit Sub
End If
If DT_CURR_WF_ITEMS.Rows.Count > 0 And POPUP_REMINDER_ACTIVE = True Then
Dim oMessage As String = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("App.ReminderPipeline")
NotifyIcon1.ShowBalloonTip(30000, $"Reminder {ADDITIONAL_TITLE}", oMessage, ToolTipIcon.Info)
End If
Catch ex As Exception
LOGGER.Warn($"Unexpected error in TimerReminderTick: {ex.Message}")
End Try
End Sub
Public Function GetEnvironment() As Environment
Return New Environment With {
.Database = DatabaseECM,
.DatabaseIDB = DatabaseIDB,
.Service = EDMIService,
.User = User
}
End Function
Sub Load_Profil_from_Grid(pProfilID As Integer)
Dim perfStart As DateTime = DateTime.MinValue
Dim useWaitCursorApplied As Boolean = False
Dim previousMessage As String = bsiMessage.Caption
Dim messageApplied As Boolean = False
Dim oHandle As Object = Nothing
Dim overlayStartedHere As Boolean = False
If LOG_HOTSPOTS Then
perfStart = DateTime.Now
LOGGER.Info($"[PERF Load_Profil_from_Grid START - pProfilID:[{pProfilID}]")
End If
Try
CURRENT_ProfilGUID = pProfilID
WM_AHWF_docPath = String.Empty
' ========== OVERLAY ANZEIGEN ==========
If Not _overlayActive Then
oHandle = SplashScreenManager.ShowOverlayForm(Me)
_overlayActive = True
overlayStartedHere = True
End If
' ========== UI-VORBEREITUNG ==========
Me.UseWaitCursor = True
useWaitCursorApplied = True
bsiMessage.Caption = "Loading profile..."
messageApplied = True
If Not Application.OpenForms().OfType(Of frmValidator).Any Then
' ========== TIMER MANAGEMENT ==========
If TimerRefresh.Enabled Then
TimerRefresh.Enabled = False
End If
' ========== FORM DESIGN CHECK ==========
If CHANGES_FORM_DESIGN = True Then
LoadCURRENT_DT_PROFILES()
LoadVWPM_CONTROL_INDEX()
CHANGES_FORM_DESIGN = False
End If
' ========== PROFILE DATA PREPARATION ==========
Dim oExpression = $"GUID = {CURRENT_ProfilGUID}"
CURRENT_DT_PROFILE = Nothing
CURRENT_DT_PROFILE = CURRENT_DT_PROFILES.Clone
CURRENT_DT_PROFILES.Select(oExpression).CopyToDataTable(CURRENT_DT_PROFILE, LoadOption.PreserveChanges)
If CURRENT_DT_PROFILE.Rows.Count = 1 Then
CURRENT_ProfilName = CURRENT_DT_PROFILE.Rows(0).Item("NAME")
CURRENT_WMObjecttype = CURRENT_DT_PROFILE.Rows(0).Item("WD_OBJECTTYPE")
PROFILE_SHOW_DOCUMENT = Convert.ToBoolean(CURRENT_DT_PROFILE.Rows(0).Item("SHOW_DOCUMENT"))
ActiveWorkflowType = 1
Else
MsgBox("Could not get a Profile - Check Your log!", MsgBoxStyle.Exclamation, ADDITIONAL_TITLE)
Exit Sub
End If
LOGGER.Debug($"Load_Profil_from_Grid: Loaded profile [{CURRENT_ProfilName}] with GUID [{CURRENT_ProfilGUID}]")
LOGGER.Debug($"Load_Profil_from_Grid: PROFILE_SHOW_DOCUMENT = [{PROFILE_SHOW_DOCUMENT}]")
' ========== SEARCH DOCUMENTS PREPARATION ==========
oExpression = $"PROFILE_ID = {CURRENT_ProfilGUID} "
DT_FILTERED_PROFILE_SEARCHES_DOC = Nothing
Dim rows = BASEDATA_DT_PROFILES_SEARCHES_DOC.Select(oExpression, "TAB_INDEX")
If rows.Length > 0 Then
DT_FILTERED_PROFILE_SEARCHES_DOC = rows.CopyToDataTable()
Else
DT_FILTERED_PROFILE_SEARCHES_DOC = BASEDATA_DT_PROFILES_SEARCHES_DOC.Clone()
End If
' ========== SEARCH SQL PREPARATION ==========
DT_FILTERED_PROFILE_SEARCHES_DATA = Nothing
rows = BASEDATA_DT_PROFILES_SEARCHES_DATA.Select(oExpression, "TAB_INDEX")
If rows.Length > 0 Then
DT_FILTERED_PROFILE_SEARCHES_DATA = rows.CopyToDataTable()
Else
DT_FILTERED_PROFILE_SEARCHES_DATA = BASEDATA_DT_PROFILES_SEARCHES_DATA.Clone()
End If
' ========== VALIDATOR-FORM ÖFFNEN ==========
Try
If LOG_HOTSPOTS Then
LOGGER.Info("[PERF Load_Profil_from_Grid öffnet frmValidator...")
End If
Dim oEnvironment = GetEnvironment()
_FormValidator = New frmValidator(oEnvironment)
AddHandler _FormValidator.FormClosed, AddressOf ValidatorClosed
_FormValidator.Show()
Catch ex As Exception
LOGGER.Warn($"Error opening Form frmValidator [{ex.Message}]")
If Not IsNothing(ex.InnerException) Then
LOGGER.Warn($"ex.InnerException.Message [{ex.InnerException.Message}]")
LOGGER.Warn($"ex.InnerException.Source [{ex.InnerException.Source}]")
LOGGER.Error(ex.InnerException)
End If
MsgBox(ex.Message, MsgBoxStyle.Critical, ADDITIONAL_TITLE)
End Try
' ========== ROW AUS ÜBERSICHT ENTFERNEN ==========
Try
Dim iterateIndex As Integer = 0
Dim oNewDataTable As DataTable = DT_CURR_WF_ITEMS.Copy
For Each row As DataRow In oNewDataTable.Rows
If row("GUID") = CURRENT_DOC_GUID Then
DT_CURR_WF_ITEMS.Rows.RemoveAt(iterateIndex)
Exit For
Else
iterateIndex += 1
End If
Next
Catch ex As Exception
LOGGER.Warn("⚠️ Unexpected Error In Removing Row after Loading Record from Grid: " & ex.Message)
End Try
' ========== TIMER RE-ENABLE ==========
TimerRefresh.Enabled = True
Else
LOGGER.Debug("Validator is already open...")
FormHelper.ShowInfoMessage(S.Es_existiert_bereits_ein_aktiver_Workflow_, omsgTitleAttention)
End If
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Unexpected error in Load_Profil_from_Grid: " & ex.Message & vbNewLine & ADDITIONAL_TITLE & " will try to reload the overview - Please try again!", MsgBoxStyle.Information, ADDITIONAL_TITLE)
Dim task = Decide_Load(False, True)
Finally
' ========== OVERLAY SCHLIESSEN (FALLBACK) ==========
If overlayStartedHere AndAlso _overlayActive Then
SplashScreenManager.CloseOverlayForm(oHandle)
LOGGER.Debug("Overlay closed in Load_Profil_from_Grid")
_overlayActive = False
End If
' ========== UI AUFRÄUMEN ==========
If useWaitCursorApplied Then
Me.UseWaitCursor = False
End If
If messageApplied AndAlso bsiMessage.Caption = "Loading profile..." Then
bsiMessage.Caption = previousMessage
End If
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF Load_Profil_from_Grid GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms")
End If
End Try
End Sub
Private Sub Reset_Current()
CURRENT_JUMP_DOC_GUID = 0
CURRENT_DOC_GUID = 0
CURRENT_DOC_ID = 0
CURRENT_ProfilGUID = 0
CURRENT_CLICKED_PROFILE_ID = 0
DT_CURR_WF_ITEMS.Clear()
End Sub
Private Async Function Item_Scope(startedFrom As String) As Task
' ========== FRÜHE VALIDIERUNGEN (VOR UI-ÄNDERUNGEN) ==========
If Application.OpenForms().OfType(Of frmValidator).Any Then
bsiMessage.Caption = S.Es_existiert_bereits_ein_aktiver_Workflow_
LOGGER.Info("Item Scope - Workflow open! - Exit")
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Exit Function
End If
Dim perfStart As DateTime = DateTime.MinValue
Dim useWaitCursorApplied As Boolean = False
Dim previousMessage As String = bsiMessage.Caption
Dim messageApplied As Boolean = False
If LOG_HOTSPOTS Then
perfStart = DateTime.Now
LOGGER.Info($"[PERF Item_Scope] START - startedFrom:[{startedFrom}]")
End If
Try
LOGGER.Info("Starting Profile Loading")
Reset_Current()
' ========== UI-VORBEREITUNG ==========
Me.UseWaitCursor = True
useWaitCursorApplied = True
bsiMessage.Caption = "Processing selection..."
messageApplied = True
' ========== HITINFO NUR EINMAL BERECHNEN ==========
Dim hitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(GridCursorLocation)
' ===== EFFEKTIVEN ROWHANDLE ERMITTELN (MIT FALLBACK) =====
' hitInfo basiert auf der zwischengespeicherten Klick-Position (GridCursorLocation).
' Diese kann zwischen Klick und Verarbeitung ungültig werden - z.B. wenn eine Gruppe
' zwischenzeitlich auf-/zugeklappt wurde (automatisch durch den DoubleClick-Handler
' oder manuell durch den User) und sich dadurch die RowHandle-Nummerierung verschoben hat.
' In diesem Fall auf FocusedRowHandle ausweichen, das vom Grid selbst nachgeführt wird
' und i.d.R. weiterhin die angeklickte Zeile referenziert.
Dim effectiveRowHandle As Integer = hitInfo.RowHandle
If effectiveRowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
Dim focusedRowHandle = GridViewWorkflows.FocusedRowHandle
If focusedRowHandle <> DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
LOGGER.Debug($"Item_Scope: CalcHitInfo(GridCursorLocation) invalid - falling back to FocusedRowHandle [{focusedRowHandle}]")
effectiveRowHandle = focusedRowHandle
Else
LOGGER.Warn($"⚠️ Item_Scope: InvalidRowHandle detected (click on empty grid area?) - exiting")
Exit Function
End If
End If
' ===== GROUP-/DATAROW DIREKT AM ROWHANDLE PRÜFEN =====
' Robuster als hitInfo.InGroupRow/InDataRow: funktioniert unverändert für den
' FocusedRowHandle-Fallback und umgeht einen bekannten DevExpress-Bug, bei dem
' diese hitInfo-Flags trotz gültigem RowHandle falsch gesetzt sein können.
Dim isGroupRow As Boolean = GridViewWorkflows.IsGroupRow(effectiveRowHandle)
Dim isDataRow As Boolean = GridViewWorkflows.IsDataRow(effectiveRowHandle)
If Not isGroupRow AndAlso Not isDataRow Then
LOGGER.Warn($"⚠️ Item_Scope: RowHandle [{effectiveRowHandle}] ist weder Group- noch DataRow - exiting")
Exit Function
End If
' ===== STARTEDROM NORMALISIEREN =====
If startedFrom = "DOUBLECLICK" Then
startedFrom = If(isGroupRow, "CMGROUP", "CMROW")
LOGGER.Debug($"User clicked {If(isGroupRow, "group", "normal")} row.")
End If
' ========== PROFIL-ID ERMITTELN ==========
Dim oHitProfilID As Object = Nothing
If isGroupRow Then
' ✅ Gruppenkopf: Profil-ID aus erster Datenzeile der Gruppe
oHitProfilID = GridViewWorkflows.GetRowCellValue(
GridViewWorkflows.GetDataRowHandleByGroupRowHandle(effectiveRowHandle),
GridViewWorkflows.Columns("PROFILE_ID"))
LOGGER.Debug("Clicked on Group Row")
ElseIf isDataRow Then
' ✅ Normale Datenzeile: Profil-ID direkt aus dieser Zeile
oHitProfilID = GridViewWorkflows.GetRowCellValue(
effectiveRowHandle,
GridViewWorkflows.Columns("PROFILE_ID"))
LOGGER.Debug("Clicked on Data Row")
End If
LOGGER.Debug("Clicked ProfileId: [{0}], Started From: [{1}]", oHitProfilID, startedFrom)
' ========== PROFIL-ID VALIDIERUNG ==========
If oHitProfilID Is Nothing OrElse Not IsNumeric(oHitProfilID) OrElse CInt(oHitProfilID) = 0 Then
LOGGER.Warn("⚠️ Item_Scope: Could not determine valid PROFILE_ID from clicked row!")
FormHelper.ShowInfoMessage("Konnte keine gültige Profil-ID ermitteln!", omsgTitleWarning)
Exit Function
End If
' ========== PROFIL-ID UPDATE ==========
If oHitProfilID IsNot Nothing AndAlso IsNumeric(oHitProfilID) AndAlso CInt(oHitProfilID) > 0 Then
If oHitProfilID <> CURRENT_CLICKED_PROFILE_ID Then
LOGGER.Debug($"Item_Scope: oHitProfilID {oHitProfilID} <> CURRENT_CLICKED_PROFILE_ID {CURRENT_CLICKED_PROFILE_ID}")
CURRENT_CLICKED_PROFILE_ID = oHitProfilID
End If
End If
' ========== GRUPPE VERARBEITEN (MIT KORREKTER GRUPPEN-ERMITTLUNG) ==========
If startedFrom = "CMGROUP" Then
LOGGER.Debug("Loading Child DocIds from focused expanded group..")
Dim oIds As New List(Of Integer)
Dim oGroupRowHandle As Integer
' KRITISCH: Den RICHTIGEN Gruppen-Handle ermitteln
If isGroupRow Then
' User hat direkt auf die Gruppen-Zeile geklickt
oGroupRowHandle = effectiveRowHandle
LOGGER.Debug($"User clicked directly on group row, handle: {oGroupRowHandle}")
Else
' User hat auf eine Daten-Zeile INNERHALB einer Gruppe geklickt
' → Parent-Gruppe ermitteln
oGroupRowHandle = GridViewWorkflows.GetParentRowHandle(effectiveRowHandle)
LOGGER.Debug($"User clicked on data row {effectiveRowHandle}, parent group handle: {oGroupRowHandle}")
If Not GridViewWorkflows.IsGroupRow(oGroupRowHandle) Then
LOGGER.Warn($"⚠️ Parent handle {oGroupRowHandle} is not a group row!")
FormHelper.ShowWarningMessage("Bitte klicken Sie direkt auf die Gruppenzeile!", omsgTitleAttention)
Exit Function
End If
End If
' Spalten-Objekt VOR der Schleife holen
Dim docIdColumn As GridColumn = GridViewWorkflows.Columns.ColumnByFieldName("DocID")
If docIdColumn Is Nothing Then
docIdColumn = GridViewWorkflows.Columns.ColumnByFieldName("DOCID")
End If
If docIdColumn Is Nothing Then
LOGGER.Error("⚠️ Column 'DocID' not found in GridView!")
' DEBUG: Alle verfügbaren Spalten ausgeben
LOGGER.Debug("=== Available Columns ===")
For Each col As GridColumn In GridViewWorkflows.Columns
LOGGER.Debug($" {col.FieldName} (Caption: {col.Caption})")
Next
LOGGER.Debug("=== END Available Columns ===")
FormHelper.ShowInfoMessage("Column 'DocID' not found!", omsgTitleWarning)
Exit Function
End If
' JETZT GetChildRowCount auf der RICHTIGEN Gruppe
Dim oChildRowCount = GridViewWorkflows.GetChildRowCount(oGroupRowHandle)
LOGGER.Debug($"Group handle {oGroupRowHandle} has {oChildRowCount} total child rows")
' WICHTIG: Wenn 0 Kinder → Gruppe ist zugeklappt oder leer
If oChildRowCount = 0 Then
' Versuche die Gruppe aufzuklappen
LOGGER.Debug($"Expanding group at handle {oGroupRowHandle}...")
GridViewWorkflows.ExpandGroupRow(oGroupRowHandle)
' UI-Thread Zeit geben
Application.DoEvents()
' Erneut prüfen
oChildRowCount = GridViewWorkflows.GetChildRowCount(oGroupRowHandle)
LOGGER.Debug($"After expanding: {oChildRowCount} child rows")
If oChildRowCount = 0 Then
LOGGER.Warn($"⚠️ Group has 0 children even after expanding")
Dim omsg = "Die Gruppe ist leer!"
FormHelper.ShowWarningMessage(omsg, omsgTitleAttention)
Exit Function
End If
End If
' JETZT sollten Kinder vorhanden sein
For childIndex = 0 To oChildRowCount - 1
Dim oChildRowHandle = GridViewWorkflows.GetChildRowHandle(oGroupRowHandle, childIndex)
' WICHTIG: Nur Daten-Rows verarbeiten, KEINE Gruppen
If Not GridViewWorkflows.IsDataRow(oChildRowHandle) Then
LOGGER.Debug($"Skipping non-data row at child index {childIndex} (Handle: {oChildRowHandle})")
Continue For
End If
' DocId auslesen - MIT COLUMN-OBJEKT
Try
Dim oDocId = GridViewWorkflows.GetRowCellValue(oChildRowHandle, docIdColumn)
If oDocId IsNot Nothing AndAlso IsNumeric(oDocId) Then
oIds.Add(CInt(oDocId))
LOGGER.Debug($"Added DocId: {oDocId} from child index {childIndex} (Handle: {oChildRowHandle})")
Else
LOGGER.Warn($"⚠️ DocId is Nothing/Invalid at child index {childIndex}, Handle: {oChildRowHandle}")
End If
Catch ex As Exception
LOGGER.Error($"Error reading DocId at child index {childIndex}: {ex.Message}")
End Try
Next
LOGGER.Debug($"[{oIds.Count}] DocIds collected from focused group")
If oIds.Count = 0 Then
Dim omsg = String.Format(S.System_konnte_die_Profilworkflows_nicht_auswerten_, vbNewLine)
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
Exit Function
End If
If oIds.Count > 1000 Then
Dim omsg = String.Format("You chose more than 1000 Workflows. Please select fewer items.", vbNewLine)
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
Exit Function
End If
' ========== DB-OPERATIONEN ==========
LOGGER.Debug("Cleaning up queued DocIds..")
Dim oDelete = $"DELETE FROM TBPM_VALIDATION_PROFILE_GROUP_USER WHERE UserID = {USER_ID}"
If DatabaseFallback.ExecuteNonQueryECM(oDelete) = True Then
LOGGER.Debug("Adding {0} queued DocIds..", oIds.Count)
Dim oInsertBatch As New System.Text.StringBuilder()
oInsertBatch.AppendLine("INSERT INTO TBPM_VALIDATION_PROFILE_GROUP_USER ([PROFIL_ID],[DocID],[UserID],[ADDED_WHO]) VALUES")
For i As Integer = 0 To oIds.Count - 1
If i > 0 Then oInsertBatch.Append(",")
oInsertBatch.AppendLine($"({CURRENT_CLICKED_PROFILE_ID},{oIds(i)},{USER_ID},'{USER_USERNAME}')")
Next
' WICHTIG: Debug-Logging des Batch-Inserts
LOGGER.Debug(String.Format("Batch-Insert {0}", oInsertBatch.ToString))
DatabaseFallback.ExecuteNonQueryECM(oInsertBatch.ToString())
End If
End If
CURRENT_JUMP_DOC_GUID = 0
' ========== HITINFO VALIDIERUNG ==========
If hitInfo Is Nothing Then
bsiMessage.Caption = "Could not specify hitinfo via click event (CalcHitInfo)"
LOGGER.Info("Could not specify hitinfo via click event (CalcHitInfo)")
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Exit Function
End If
' ========== PROFIL-TITEL ERMITTELN ==========
Dim PROFIL_TITLE As String = String.Empty
If isGroupRow Then
GridViewItem_Clicked = "GROUP"
startedFrom = "CMGROUP"
LOGGER.Debug($"Item_Scope: InGroupRow")
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(effectiveRowHandle)
LOGGER.Debug($"Item_Scope: groupRowText {groupRowText}")
If GRID_LOAD_TYPE = "OVERVIEW" Then
groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim()
Dim splitIndex = groupRowText.IndexOf("|")
PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText)
End If
ElseIf isDataRow Then
GridViewItem_Clicked = "ROW"
LOGGER.Debug($"Item_Scope: InDataRow")
If GRID_LOAD_TYPE = "OVERVIEW" Then
LOGGER.Debug($"Item_Scope: GRID_LOAD_TYPE = OVERVIEW")
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(
GridViewWorkflows.GetParentRowHandle(effectiveRowHandle))
LOGGER.Debug($"Item_Scope: OVERVIEWgroupRowText {groupRowText}")
groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim()
Dim splitIndex = groupRowText.IndexOf("|")
PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText)
Else
LOGGER.Debug($"Item_Scope: NOT GRID_LOAD_TYPE = OVERVIEW")
If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso CURRENT_CLICKED_PROFILE_ID <> 0 Then
LOGGER.Debug($"Item_Scope: CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]")
oHitProfilID = CURRENT_CLICKED_PROFILE_ID
Else
LOGGER.Warn("⚠️ ItemScope: CURRENT_CLICKED_PROFILE_ID is nothing or 0!!!")
Exit Function
End If
End If
Else
Exit Function
End If
' ========== PROFIL-TITEL SETZEN ==========
If Not String.IsNullOrEmpty(PROFIL_TITLE) Then
CURRENT_CLICKED_PROFILE_TITLE = PROFIL_TITLE.Replace("GROUP_TEXT:", "")
End If
' ========== PROFIL LADEN ==========
If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then
LOGGER.Debug($"Item_Scope: Valid PROFIL_ID")
If isGroupRow OrElse (startedFrom = "CMGROUP" AndAlso isDataRow) Then
' GRUPPE: Workflow ohne spezifisches Dokument
Reset_Current()
CURRENT_ProfilGUID = CURRENT_CLICKED_PROFILE_ID
LOGGER.Debug($"Item_Scope: isGroupRow...CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]")
Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID)
ElseIf isDataRow Then
' EINZELNE ZEILE: Mit spezifischem Dokument
LOGGER.Debug($"Item_Scope: isDataRow...")
' ========== DOKUMENT-DATEN ABRUFEN ==========
Dim oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID"))
Dim oFocusedDocID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("DocID"))
' Validierungen
If oFocusedDocID Is Nothing Then
LOGGER.Warn("⚠️ In isDataRow: DocID is nothing!!!")
bsiMessage.Caption = "Error getting DocID!"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Exit Function
End If
If oFocusedDocGUID Is Nothing Then
LOGGER.Warn("⚠️ In isDataRow: oFocusedDocGUID is nothing!!!")
bsiMessage.Caption = "Error getting DocGUID!"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Exit Function
End If
LOGGER.Debug($"Item_Scope: GotDocID {oFocusedDocID} and DocGUID {oFocusedDocGUID}")
' ========== DATEIPFAD (OPTIONAL) ==========
If GridViewWorkflows.Columns(FullFilepatColName) IsNot Nothing Then
Dim DOC_PATH = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns(FullFilepatColName))
If DOC_PATH IsNot Nothing Then
DOC_PATH = DOC_PATH.Replace("W:\", "\\windream\objects\").Replace("K:\", "\\windream\objects\")
End If
End If
' ========== DOKUMENT-DATEN SETZEN ==========
CURRENT_DOC_ID = oFocusedDocID
CURRENT_JUMP_DOC_GUID = oFocusedDocGUID
CURRENT_DOC_GUID = CURRENT_JUMP_DOC_GUID
' ========== DOKUMENT-VALIDIERUNG (OPTIMIERT) ==========
Dim oSQL = $"SELECT [dbo].[FNPM_CHECK_DocGUID_Valid] ({CURRENT_DOC_GUID})"
Dim oResult = DatabaseFallback.GetScalarValueECM(oSQL)
If CBool(oResult) = True Then
Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID)
Else
Dim omsg = S.Der_gewählte_Beleg_ist_durch_einen_anderen_Benutzer_bereits_in_Bearbeitung_oder_anderweitig_gesperrt_
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
End If
End If
Else
FormHelper.ShowInfoMessage("Could not get the ProfileID of file! - Check Your configuration of MainView!", omsgTitleWarning)
End If
Catch ex As Exception
LOGGER.Error(ex)
bsiMessage.Caption = "Warning in Item_Scope: " & ex.Message
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Finally
' ========== UI AUFRÄUMEN ==========
If useWaitCursorApplied Then
Me.UseWaitCursor = False
End If
bsiMessage.Caption = ""
bsiMessage.ItemAppearance.Normal.BackColor = Color.Transparent
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF Item_Scope] GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms")
End If
End Try
End Function
Private Async Sub ValidatorClosed(sender As Object, e As FormClosedEventArgs)
Try
' LoadingPanel-Verwaltung erfolgt in Decide_Load
Await Decide_Load(False, True)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.LoadViewInfo()
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Function Init_IDB()
Try
IDBData = New ClassIDBData()
Return True
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Error Init_IDB:" & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Attention:")
LOGGER.Info("Unexpected error in Init_IDB: " & ex.Message, True)
Return False
End Try
End Function
Private Function Init_windream()
Try
WINDREAM = New ClassPMWindream()
WINDREAM_MOD = New Windream(LOGCONFIG, False, WMDRIVE_LETTER, WMSUFFIX, True, "", "", "", "")
WINDREAM.Create_Session()
WINDREAM_ALLG = New ClassWindream_allgemein
Return WINDREAM.IsLoggedIn
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Error Init_windream:" & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Attention:")
LOGGER.Info("Unexpected error in Init_windream: " & ex.Message, True)
Return False
End Try
End Function
Private Sub Create_GroupBy_Parts()
Try
LOGGER.Debug("Now Create_GroupBy_Parts ...")
GridViewWorkflows.OptionsView.ShowGroupPanel = False
Dim oindex As Integer = 0
If Not IsNothing(BASEDATA_DTGRID_GROUPS) Then
For Each oGridGroup As DataRow In BASEDATA_DTGRID_GROUPS.Rows
Dim oGroupName = oGridGroup.Item("GROUPNAME")
LOGGER.Debug($"Adding group [{oGroupName}] for Grid...")
Try
Dim oGroupColumn As GridColumn = GridViewWorkflows.Columns.Item(oGroupName)
If oGroupColumn IsNot Nothing Then
oGroupColumn.GroupIndex = oindex
oGroupColumn.Group()
oGroupColumn.OptionsColumn.AllowGroup = DefaultBoolean.False
oGroupColumn.OptionsColumn.AllowMove = False
oGroupColumn.OptionsColumn.AllowShowHide = False
oGroupColumn.Caption = "Profile (Fixed)"
End If
Catch ex As Exception
End Try
oindex += 1
Next
End If
Try
GridViewWorkflows.Columns.Item("GROUP_TEXT").Visible = False
GridViewWorkflows.Columns.Item("GROUP_COLOR").Visible = False
Catch ex As Exception
End Try
For index = 0 To GridViewWorkflows.GroupCount - 1
'Dim v = GridViewWorkflows.GroupedColumns(index).ToString
LOGGER.Debug($"Adding tag [{GridViewWorkflows.Columns.Item("PROFILE_ID")}] for group...")
Dim sd = GridViewWorkflows.GroupedColumns(index).GetTextCaption
GridViewWorkflows.GroupedColumns(index).Tag = GridViewWorkflows.Columns.Item("PROFILE_ID")
Next
GridViewWorkflows.CollapseAllGroups()
LOGGER.Debug("finished Grouping!")
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Async Function Load_Grid_Overview(pFormLoad As Boolean, pForceReload As Boolean, pNavbarClick As Boolean) As Tasks.Task
Dim perfStart As DateTime = DateTime.MinValue
Dim perfStep As DateTime = DateTime.MinValue
Dim gridUpdateStarted As Boolean = False
Dim viewUpdateStarted As Boolean = False
Dim layoutRestored As Boolean = False
Dim resetLayoutTriggered As Boolean = False
Dim useWaitCursorApplied As Boolean = False
Dim previousMessage As String = bsiMessage.Caption
Dim loadingMessageApplied As Boolean = False
If LOG_HOTSPOTS Then
perfStart = DateTime.Now
perfStep = perfStart
LOGGER.Info($"[PERF Load_Grid_Overview] START - pFormLoad:[{pFormLoad}] pForceReload:[{pForceReload}] pNavbarClick:[{pNavbarClick}]")
End If
' ========== LOADING PANEL UND UI-VORBEREITUNG ==========
' SCHRITT 1: Grid sichtbar machen
If GridControlWorkflows.Visible = False Then
GridControlWorkflows.Visible = True
End If
GRID_LOAD_TYPE = "OVERVIEW"
CURRENT_CLICKED_PROFILE_ID = 0
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ UI-Vorbereitung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] UI-Vorbereitung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' WaitCursor setzen
If Me.UseWaitCursor = False Then
Me.UseWaitCursor = True
useWaitCursorApplied = True
End If
' Statusmeldung aktualisieren
bsiMessage.Caption = "Overviewdata loading..."
loadingMessageApplied = True
Try
' ========== GRID UPDATES VORBEREITEN ==========
If GridControlWorkflows.Visible Then
GridControlWorkflows.BeginUpdate()
gridUpdateStarted = True
GridViewWorkflows.BeginUpdate()
viewUpdateStarted = True
End If
' ========== DATEN VALIDIEREN ==========
If BASEDATA_DT_VW_PROFILE_USER.Rows.Count = 0 Then
LOGGER.Info("Attention: No profiles for user: '" & USER_USERNAME & "' configured!", False)
NO_WORKFLOW_ITEMS = True
bsiMessage.Caption = "NO PROFILES FOR USER"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
GridControlWorkflows.Visible = False
Exit Try
End If
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF LGO] Load_Profiles_for_User wird aufgerufen...")
End If
Load_Profiles_for_User()
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Load_Profiles_for_User LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] Load_Profiles_for_User: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== SQL UND DATEN LADEN ==========
Dim oSQLOverview = BASEDATA_DT_CONFIG.Rows(0).Item("SQL_PROFILE_MAIN_VIEW")
If IsDBNull(oSQLOverview) Then
bsiMessage.Caption = "No SQL_PROFILE_MAIN_VIEW in Baseconfig"
Exit Try
End If
If oSQLOverview.ToString.Contains("GROUP_TEXT") = False Then
LOGGER.Info($"SQL SO FAR: {oSQLOverview} ")
FormHelper.ShowInfoMessage("Incomplete Overview-Source (No Group-Columns). Column", omsgTitleWarning)
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
LOGGER.Error(ex)
End Try
Exit Try
End If
' SQL-Platzhalter ersetzen
oSQLOverview = clsPatterns.ReplaceInternalValues(oSQLOverview)
oSQLOverview = clsPatterns.ReplaceUserValues(oSQLOverview)
oSQLOverview = oSQLOverview.Replace("@USER_ID", USER_ID)
oSQLOverview = oSQLOverview.Replace("@USERNAME", USER_USERNAME)
oSQLOverview = oSQLOverview.Replace("@MACHINE_NAME", System.Environment.MachineName)
oSQLOverview = oSQLOverview.Replace("@DATE", Now.ToShortDateString)
oSQLOverview = oSQLOverview.Replace("@PROFILE_ID", CURRENT_CLICKED_PROFILE_ID)
If LOG_HOTSPOTS Then
LOGGER.Info($"[PERF LGO] SQL-Abfrage startet (Rows erwartet: {If(DT_CURR_WF_ITEMS IsNot Nothing, DT_CURR_WF_ITEMS.Rows.Count.ToString(), "N/A")})...")
End If
DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQLOverview)
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
Dim rowCount = If(DT_CURR_WF_ITEMS IsNot Nothing, DT_CURR_WF_ITEMS.Rows.Count, 0)
If elapsed > 4500 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Datenbank-Abfrage Overview LANGSAM: {elapsed}ms ({rowCount} Zeilen) (Schwellwert: 4500ms) - SQL prüfen!")
Else
LOGGER.Info($"[PERF LGO] Datenbank-Abfrage Overview: {elapsed}ms ({rowCount} Zeilen)")
End If
perfStep = DateTime.Now
End If
If IsNothing(DT_CURR_WF_ITEMS) Then
NO_WORKFLOW_ITEMS = True
GridControlWorkflows.Visible = False
GridControlWorkflows.DataSource = Nothing
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
LOGGER.Error(ex)
End Try
Exit Try
End If
LOGGER.Debug($"Datatable CURR_DT_OVERVIEW loaded: {DT_CURR_WF_ITEMS.Rows.Count} rows")
' ========== DATEN ANALYSIEREN ==========
Dim oADDED = GET_LAST_ADDED(DT_CURR_WF_ITEMS)
Dim oChanged = GET_LAST_CHANGED(DT_CURR_WF_ITEMS)
Dim oCOUNT = DT_CURR_WF_ITEMS.Rows.Count
NO_WORKFLOW_ITEMS = (oCOUNT = 0)
UpdateGridCaption()
If NO_WORKFLOW_ITEMS Then
GridControlWorkflows.Visible = False
bindsourcegrid.DataSource = Nothing
GridControlWorkflows.DataSource = Nothing
Try
GridViewWorkflows.Columns.Clear()
Catch ex As Exception
LOGGER.Error(ex)
End Try
Exit Try
End If
' ========== ICON-SPALTE VORBEREITEN ==========
If TL_ICON = True AndAlso DT_CURR_WF_ITEMS.Columns.Contains("ICON") = False Then
Dim columnStateIcon As New DataColumn() With {
.DataType = GetType(Image),
.ColumnName = "ICON",
.Caption = ""
}
DT_CURR_WF_ITEMS.Columns.Add(columnStateIcon)
End If
RedDocuments = 0
YellowDocuments = 0
GreenDocuments = 0
If TL_ICON = True Then
For Each row As DataRow In DT_CURR_WF_ITEMS.Rows
Dim State As Integer = row.Item("TL_STATE")
Select Case State
Case 1
RedDocuments += 1
row.Item("ICON") = My.Resources.bullet_red
Case 2
YellowDocuments += 1
row.Item("ICON") = My.Resources.bullet_orange
Case 3
GreenDocuments += 1
row.Item("ICON") = My.Resources.bullet_green
End Select
Next
End If
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Icon-Verarbeitung LANGSAM: {elapsed}ms ({DT_CURR_WF_ITEMS.Rows.Count} Zeilen) (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] Icon-Verarbeitung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== GRID MIT DATEN FÜLLEN ==========
bindsourcegrid.DataSource = DT_CURR_WF_ITEMS
GridControlWorkflows.DataSource = bindsourcegrid
GridControlWorkflows.ForceInitialize()
Create_View_Caption()
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Grid-DataSource-Zuweisung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] Grid-DataSource-Zuweisung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== LAYOUT WIEDERHERSTELLEN ODER ZURÜCKSETZEN ==========
Dim oColNotPartofLayout As Boolean = False
If pNavbarClick = False Then
If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then
LOGGER.Debug("Now GridLayout_Reset..")
Await GridLayout_Reset(False)
resetLayoutTriggered = True
ElseIf oColNotPartofLayout = False Then
RestoreLayout()
layoutRestored = True
End If
Else
RestoreLayout()
layoutRestored = True
End If
If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then
Create_GroupBy_Parts()
End If
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Layout-Wiederherstellung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] Layout-Wiederherstellung: {elapsed}ms")
End If
perfStep = DateTime.Now
End If
' ========== ICON-SPALTE KONFIGURIEREN ==========
If TL_ICON = True Then
Try
GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24
GridViewWorkflows.Columns.Item("ICON").MinWidth = 24
GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White
GridViewWorkflows.Columns.Item("ICON").Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left
Catch ex As Exception
End Try
End If
If GridViewWorkflows.Columns.Count <= 5 Then
LOGGER.Info("GridViewWorkflows.Columns.Count <= 5 - Reset_Gridlayout will be forced...", False)
Await Reset_GridLayout(pFormLoad)
resetLayoutTriggered = True
End If
If Not layoutRestored And Not resetLayoutTriggered Then
RestoreLayout()
End If
COLUMNS_INVISIBLE()
' ========== SPALTENFORMATIERUNG ANWENDEN ==========
Try
For Each oColumn As DevExpress.XtraGrid.Columns.GridColumn In GridViewWorkflows.Columns
For Each oRow As DataRow In BASEDATA_TBDD_COLUMNS_FORMAT.Rows
Dim colName = oRow("COLUMN_TITLE").ToString()
If oColumn.FieldName = colName Then
Dim oSollFormatType = oRow("TYPE2FORMAT").ToString()
If oSollFormatType = "DateTime" Then
If oColumn.ColumnType <> GetType(DateTime) Then
oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
End If
If oColumn.ColumnType = GetType(DateTime) And oColumn.DisplayFormat.FormatString <> "dd.MM.yyyy HH:mm:ss" Then
oColumn.DisplayFormat.FormatString = "dd.MM.yyyy HH:mm:ss"
End If
ElseIf oSollFormatType = "Numeric" Then
If oColumn.ColumnType <> GetType(Int32) Then
oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric
End If
End If
End If
Next
Next
Catch ex As Exception
LOGGER.Warn("⚠️ Fehler beim Anwenden der Formatierung aus TBDD_COLUMNS_FORMAT: " & ex.Message)
End Try
If LOG_HOTSPOTS Then
Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds
If elapsed > 4000 Then
LOGGER.Warn($"[PERF LGO] ⚠️ Spaltenformatierung LANGSAM: {elapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF LGO] Spaltenformatierung: {elapsed}ms")
End If
End If
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Info("Load_Grid_Overview - Fehler: " & ex.Message)
Finally
' ========== AUFRÄUMEN ==========
If viewUpdateStarted Then
GridViewWorkflows.EndUpdate()
End If
If gridUpdateStarted Then
GridControlWorkflows.EndUpdate()
End If
' WaitCursor entfernen
If useWaitCursorApplied Then
Me.UseWaitCursor = False
End If
' Statusmeldung zurücksetzen
If loadingMessageApplied AndAlso bsiMessage.Caption = "Overviewdata loading..." Then
bsiMessage.Caption = previousMessage
End If
If LOG_HOTSPOTS Then
Dim totalElapsed = (DateTime.Now - perfStart).TotalMilliseconds
If totalElapsed > 4000 Then
LOGGER.Warn($"[PERF Load_Grid_Overview] ⚠️ GESAMT LANGSAM: {totalElapsed}ms (Schwellwert: 4000ms)")
Else
LOGGER.Info($"[PERF Load_Grid_Overview] GESAMT: {totalElapsed}ms")
End If
End If
End Try
End Function
Private Sub tsmiValidationProfil_Click(sender As Object, e As EventArgs) Handles tsmiValidationProfil.Click
If CURRENT_CLICKED_PROFILE_ID <> 0 Then
Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID)
Else
FormHelper.ShowInfoMessage(S.Bitte_wählen_Sie_ein_Profil_aus_, omsgTitleWarning)
End If
End Sub
Private Async Function GridLayout_Reset(Also_decideload As Boolean) As Tasks.Task
FRONTEND_ACTION = "RESET_LAYOUT"
Await Reset_GridLayout(False)
If Also_decideload Then
Await Decide_Load(False, True)
End If
GridViewWorkflows.OptionsView.ShowViewCaption = False
SaveGridLayout()
' ===== GRUPPIERUNG NUR FÜR OVERVIEW ERSTELLEN =====
' Bei Profil-Ansichten (GRID_LOAD_TYPE = PROFILE#xxx) darf nicht gruppiert werden
If GRID_LOAD_TYPE = "OVERVIEW" Then
If GridViewWorkflows.GroupCount = 0 AndAlso Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then
LOGGER.Info("NO GROUPS AFTER GridLayout_Reset Load...")
Create_GroupBy_Parts()
End If
Else
LOGGER.Debug($"GridLayout_Reset: Skipping Create_GroupBy_Parts for non-OVERVIEW mode [{GRID_LOAD_TYPE}]")
End If
GridBuilder.WithFontSizeDelta(CONFIG.Config.GridFontSizeDelta)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo()
FRONTEND_ACTION = FA_NONE
End Function
Async Function Reset_GridLayout(FormLoad As Boolean) As Tasks.Task
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.SaveViewInfo()
End If
InResetlayout = True
' Layout zurücksetzen
ResetLayout()
' Ansicht neu laden
'LoadNavBar()
Await Decide_Load(FormLoad)
InResetlayout = False
End Function
Private Async Sub GridViewWorkflows_DoubleClick(sender As Object, e As EventArgs) Handles GridViewWorkflows.DoubleClick
Try
' ===== KRITISCH: HitInfo MIT AKTUELLEM Mauszeiger-Position berechnen =====
Dim oCurrentMousePosition As System.Drawing.Point = GridControlWorkflows.PointToClient(Cursor.Position)
Dim hitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(oCurrentMousePosition)
' ===== FRÜHE VALIDIERUNG =====
If hitInfo.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
Dim focused = GridViewWorkflows.FocusedRowHandle
If focused <> DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
LOGGER.Debug($"Item_Scope: hitInfo invalid, falling back to FocusedRowHandle [{focused}]")
' hitInfo/rowHandle entsprechend neu aufbauen
CURRENT_CLICKED_PROFILE_ID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(focused), GridViewWorkflows.Columns("PROFILE_ID"))
LOGGER.Debug($"Item_Scope: Fallback PROFILE_ID = [{CURRENT_CLICKED_PROFILE_ID}]")
Else
LOGGER.Warn("⚠️ Item_Scope: InvalidRowHandle detected...")
Exit Sub
End If
End If
If Not hitInfo.InRow Then
LOGGER.Warn("⚠️ DoubleClick: Not in row - ignoring")
Exit Sub
End If
' ===== AKTUALISIERTE GridCursorLocation SETZEN =====
GridCursorLocation = oCurrentMousePosition
LOGGER.Debug($"DoubleClick: RowHandle=[{hitInfo.RowHandle}], InGroupRow=[{hitInfo.InGroupRow}], InDataRow=[{hitInfo.InDataRow}]")
Me.Cursor = Cursors.WaitCursor
Try
Await Item_Scope("DOUBLECLICK")
Finally
Me.Cursor = Cursors.Default
End Try
Catch ex As Exception
LOGGER.Error(ex)
Me.Cursor = Cursors.Default
End Try
End Sub
'Private Sub GridViewWorkflows_CustomDrawGroupRow(sender As Object, e As Views.Base.RowObjectCustomDrawEventArgs) Handles GridViewWorkflows.CustomDrawGroupRow
' Try
' ' Added
' If FormOpenClose = True And GridIsLoaded = False Then
' Exit Sub
' End If
' Dim info As GridGroupRowInfo = TryCast(e.Info, GridGroupRowInfo)
' Dim view As GridView = sender
' If info.Column.FieldName = "GROUP_TEXT" Then
' info.GroupText = info.GroupValueText
' Dim oColorString As String = "LightGray"
' Dim oFontColorString As String = "Black"
' Dim oFoundConfig As Boolean = False
' Dim oGROUP_TEXT_COL As String
' If USER_LANGUAGE = "de-DE" Then
' oGROUP_TEXT_COL = "GROUP_TEXT"
' Else
' oGROUP_TEXT_COL = "GROUP_TEXT_LANG"
' End If
' For Each oProfileRow As DataRow In CURR_DT_VWPM_PROFILE_ACTIVE.Rows
' If oProfileRow.Item(oGROUP_TEXT_COL) = info.GroupValueText Then
' oFoundConfig = True
' oColorString = oProfileRow.Item("GROUP_COLOR")
' oFontColorString = oProfileRow.Item("GROUP_FONT_COLOR")
' ' Added
' Exit For
' End If
' Next
' If oFoundConfig = False Then
' LOGGER.Info($"CustomDrawGroupRow: Could not find a ColorConfig for ProfileGroupValueText [{info.GroupValueText}]...")
' ' Added
' Exit Sub
' End If
' Dim oColor As Color = ParseColorString(oColorString, Color.LightGray, "Background Color")
' Dim oFontColor As Color = ParseColorString(oFontColorString, Color.Black, "Font Color")
' info.Appearance.BackColor = oColor
' info.Appearance.ForeColor = oFontColor
' End If
' Catch ex As Exception
' LOGGER.Error(ex)
' End Try
'End Sub
Private Sub GridViewWorkflows_CustomDrawGroupRow(sender As Object, e As Views.Base.RowObjectCustomDrawEventArgs) Handles GridViewWorkflows.CustomDrawGroupRow
Try
If FormOpenClose = True And GridIsLoaded = False Then
Exit Sub
End If
Dim oInfo As GridGroupRowInfo = TryCast(e.Info, GridGroupRowInfo)
If oInfo Is Nothing OrElse oInfo.Column Is Nothing Then
Exit Sub
End If
Dim oView As GridView = sender
If oInfo.Column.FieldName = "GROUP_TEXT" Then
oInfo.GroupText = oInfo.GroupValueText
' ===== PRÜFUNG AUF KINDERZEILEN HINZUFÜGEN =====
Dim oChildCount As Integer = oView.GetChildRowCount(oInfo.RowHandle)
' Wenn keine Kinder vorhanden sind, Standard-Farben verwenden
If oChildCount = 0 Then
LOGGER.Debug($"CustomDrawGroupRow: Group [{oInfo.GroupValueText}] has no children - using default colors")
oInfo.Appearance.BackColor = Color.LightGray
oInfo.Appearance.ForeColor = Color.Black
Exit Sub
End If
' ===== NUR BEI VORHANDENEN KINDERN FARBE AUSLESEN =====
Dim oColorString As String = "LightGray"
Dim oFontColorString As String = "Black"
Dim oChildRowHandle As Integer = oView.GetChildRowHandle(oInfo.RowHandle, 0)
' GetRowCellValue kann Nothing zurückgeben, daher absichern
Dim oCellValue As Object = oView.GetRowCellValue(oChildRowHandle, "GROUP_COLOR")
If oCellValue IsNot Nothing AndAlso Not IsDBNull(oCellValue) Then
oColorString = oCellValue.ToString()
End If
Dim oColor As Color = ParseColorString(oColorString, Color.LightGray, "Background Color")
Dim oFontColor As Color = ParseColorString(oFontColorString, Color.Black, "Font Color")
oInfo.Appearance.BackColor = oColor
oInfo.Appearance.ForeColor = oFontColor
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Function ParseColorString(ColorString As String, DefaultColor As Color, ColorDescription As String) As Color
' ===== NULL-CHECK HINZUFÜGEN =====
If String.IsNullOrWhiteSpace(ColorString) Then
LOGGER.Debug($"ParseColorString: ColorString is null/empty for {ColorDescription} - using default color")
Return DefaultColor
End If
Dim oResultColor As Color
If ColorString.Contains(";") Or ColorString.Contains(".") Then
Dim oSplitColorString As String()
If ColorString.Contains(";") Then
oSplitColorString = ColorString.Split(";")
Else
oSplitColorString = ColorString.Split(".")
End If
Try
oResultColor = Color.FromArgb(oSplitColorString(0), oSplitColorString(1), oSplitColorString(2))
Catch ex As Exception
oResultColor = DefaultColor
LOGGER.Info("ParseColorString: Could not get Color.FromArgb [{0}] for {1}", ColorString, ColorDescription)
End Try
Else
Try
oResultColor = Color.FromName(ColorString)
Catch ex As Exception
LOGGER.Info("ParseColorString: Could not get Color.FromArgb [{0}] for {1}", ColorString, ColorDescription)
oResultColor = DefaultColor
End Try
End If
Return oResultColor
End Function
Private Sub GridViewWorkflows_MouseDown(sender As Object, e As MouseEventArgs) Handles GridViewWorkflows.MouseDown
Dim view As GridView = sender
Dim hi As GridHitInfo = view.CalcHitInfo(e.Location)
Dim groupRowButtonClicked = (hi.HitTest = GridHitTest.RowGroupButton)
' ===== UNGÜLTIGE CLICKS ABFANGEN =====
' Anders als in Item_Scope ist hier KEIN FocusedRowHandle-Fallback sinnvoll:
' e.Location ist immer aktuell (kein Caching-Problem), und InvalidRowHandle ist
' hier der normale Fall für legitime Nicht-Zeilen-Klicks (Spaltenkopf, leerer
' Bereich, FilterPanelCloseButton). Ein Fallback würde solche Klicks fälschlich
' der aktuell fokussierten Zeile zuordnen.
If hi.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
LOGGER.Debug("MouseDown: InvalidRowHandle - ignoring click")
Exit Sub
End If
If Not hi.InRow Then
LOGGER.Debug($"MouseDown: Click not in row (HitTest:[{hi.HitTest}]) - ignoring")
Exit Sub
End If
GridCursorLocation = e.Location
'If e.Button = MouseButtons.Left Then
' wenn in eine Group Row Doppelt geklickt wurde..
If hi.InGroupRow And Not groupRowButtonClicked Then
' Ein/Ausklappen verhindern
DXMouseEventArgs.GetMouseArgs(e).Handled = True
GridViewItem_Clicked = "GROUP"
If Not Application.OpenForms().OfType(Of frmValidator).Any Then
CURRENT_CLICKED_PROFILE_ID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hi.RowHandle), GridViewWorkflows.Columns("PROFILE_ID"))
LOGGER.Debug($"MouseDown: PROFILE_ID for GroupRow [{hi.RowHandle}] is [{CURRENT_CLICKED_PROFILE_ID}]")
End If
ElseIf hi.InDataRow Then
GridViewItem_Clicked = "ROW"
If Not Application.OpenForms().OfType(Of frmValidator).Any Then
CURRENT_CLICKED_PROFILE_ID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hi.RowHandle), GridViewWorkflows.Columns("PROFILE_ID"))
LOGGER.Debug($"MouseDown: PROFILE_ID for DataRow [{hi.RowHandle}] is [{CURRENT_CLICKED_PROFILE_ID}]")
End If
Else
GridViewItem_Clicked = Nothing
If hi.HitTest = GridHitTest.FilterPanelCloseButton Then
Ev_Filter_Panel_Closed = True
LOGGER.Debug("MouseDown: FilterPanelCloseButton clicked - Ev_Filter_Panel_Closed set to True")
Grid_Reset_Filter()
Ev_Filter_Panel_Closed = False
End If
End If
If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) Then
If IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then
If CURRENT_CLICKED_PROFILE_ID > 0 Then
For Each orow As DataRow In CURRENT_DT_PROFILES.Rows
If orow.Item("GUID") = CURRENT_CLICKED_PROFILE_ID Then
If Not Application.OpenForms().OfType(Of frmValidator).Any Then
LOGGER.Debug($"MouseDown: PROFILE_TITLE for PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}] is [{orow.Item("TITLE")}]")
CURRENT_CLICKED_PROFILE_TITLE = orow.Item("TITLE")
End If
Exit For
End If
Next
End If
End If
End If
End Sub
Private Sub GridViewWorkflows_ColumnWidthChanged(sender As Object, e As Views.Base.ColumnEventArgs) Handles GridViewWorkflows.ColumnWidthChanged
GridLayout_Changed("ColumnWidthChanged")
End Sub
Private Sub GridViewWorkflows_EndSorting(sender As Object, e As EventArgs) Handles GridViewWorkflows.EndSorting
GridLayout_Changed("EndSorting")
End Sub
Private Sub GridViewWorkflows_LostFocus(sender As Object, e As EventArgs) Handles GridViewWorkflows.LostFocus
' Save expanded GroupRows
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.SaveViewInfo()
End If
End Sub
Sub LoadCURRENT_DT_PROFILES()
Dim oSQL = $"select * from TBPM_PROFILE WITH (NOLOCK) where ACTIVE = 1"
CURRENT_DT_PROFILES = DatabaseFallback.GetDatatable("TBPM_PROFILE", New GetDatatableOptions(oSQL, DatabaseType.ECM))
oSQL = $"select * from TBDD_GUI_LANGUAGE_PHRASE WITH (NOLOCK) where LANGUAGE = '{USER_LANGUAGE}' AND MODULE = 'PM' AND TITLE LIKE 'PROFILE_%'"
CURRENT_DT_PROFILE_LANGUAGE = DatabaseFallback.GetDatatable("TBPMPROFILE_LANGUAGE_TERMS", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = $"LANGUAGE = '{USER_LANGUAGE}'"
})
End Sub
Sub LoadVWPM_CONTROL_INDEX()
Dim oSQL = $"SELECT * FROM VWPM_CONTROL_INDEX ORDER BY PROFIL_ID,Y_LOC, X_LOC"
'DTVWCONTROLS_INDEX = DataASorDB.GetDatatable("DD_ECM", oSQL, "VWPM_CONTROL_INDEX", "")
DTVWCONTROLS_INDEX = DatabaseFallback.GetDatatable("VWPM_CONTROL_INDEX", New GetDatatableOptions(oSQL, DatabaseType.ECM))
End Sub
Sub GetBaseData(pMode As String)
Dim oStopWatch As New RefreshHelper.SW("GetBaseData")
Try
Dim oSQL = String.Format("SELECT * FROM [dbo].[FNDD_LOGIN_USER_MODULE] ('{0}','PM',{1})", USER_USERNAME, CLIENT_SELECTED)
Dim DT_CHECKUSER_MODULE As DataTable
DT_CHECKUSER_MODULE = DatabaseFallback.GetDatatable("TBDD_USER_MODULE", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = $"USERNAME = '{USER_USERNAME.ToLower}' AND MODULE_SHORT = 'PM'"
})
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(10)
If pMode <> "Load" Then
ClassParamRefresh.Refresh_Params(DT_CHECKUSER_MODULE, pMode)
End If
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(20)
If SQL_PROFILES_USER <> "" Then
oSQL = SQL_PROFILES_USER.Replace("@USER_ID", USER_ID)
LOGGER.Debug($"VWPM_PROFILE_ACTIVE-SELECT used from DD-SQL-Config..")
Else
oSQL = $"SELECT [dbo].[FNDD_LANGUAGE_PHRASE] ('PROFILE_TITLE' + CONVERT(VARCHAR(4),T.GUID),'{USER_LANGUAGE}','PM') as GROUP_TEXT_LANG, T.*
FROM VWPM_PROFILE_ACTIVE T WHERE T.GUID IN (SELECT PROFILE_ID FROM [dbo].[FNPM_GET_ACTIVE_PROFILES_USER] ({USER_ID}))"
End If
LOGGER.Debug($"VWPM_PROFILE_ACTIVE-SELECT: {oSQL}")
CURR_DT_VWPM_PROFILE_ACTIVE = DatabaseFallback.GetDatatableECM(oSQL)
CURR_DT_VWPM_PROFILE_AH_WORKFLOW = CURR_DT_VWPM_PROFILE_ACTIVE.Copy
CURR_DT_VWPM_PROFILE_AH_WORKFLOW.Clear()
Dim AHWFRows As DataRow() = CURR_DT_VWPM_PROFILE_ACTIVE.Select($"TYPE = {ConstAHWorkflow_BlindFile}", "PRIORITY")
If AHWFRows.Length > 0 Then
LOGGER.Info($"...NUMBER OF ADHOC-WORKFLOW PROFILES ({AHWFRows.Length})")
CURR_DT_VWPM_PROFILE_AH_WORKFLOW = AHWFRows.CopyToDataTable()
Else
LOGGER.Debug($"...NO ADHOC-WORKFLOW PROFILES!")
End If
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(30)
LoadCURRENT_DT_PROFILES()
If pMode = "Load" Then
CURRENT_DT_PROFILE = CURRENT_DT_PROFILES.Clone()
End If
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(40)
oSQL = "select * from TBPM_PROFILE_SEARCH WITH (NOLOCK) where TYPE = 'DOC' AND ACTIVE = 1 ORDER BY PROFILE_ID,TAB_INDEX"
If SQL_VALIDATOR_SEARCHES <> String.Empty Then
SQL_VALIDATOR_SEARCHES = SQL_VALIDATOR_SEARCHES.Replace("@USR_LANG_CODE", User.Language)
oSQL = SQL_VALIDATOR_SEARCHES
End If
BASEDATA_DT_PROFILES_SEARCHES_DOC = DatabaseECM.GetDatatable(oSQL)
EnsureProfileSearchType(BASEDATA_DT_PROFILES_SEARCHES_DOC, "DOC", NameOf(BASEDATA_DT_PROFILES_SEARCHES_DOC))
If pMode = "Load" Then
DT_FILTERED_PROFILE_SEARCHES_DOC = BASEDATA_DT_PROFILES_SEARCHES_DOC.Clone()
End If
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(50)
oSQL = "select * from TBPM_PROFILE_SEARCH WITH (NOLOCK) where TYPE = 'SQL' AND ACTIVE = 1 ORDER BY PROFILE_ID,TAB_INDEX"
BASEDATA_DT_PROFILES_SEARCHES_DATA = DatabaseFallback.GetDatatable("TBPM_PROFILE_SEARCH", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = "TYPE = 'SQL'",
.SortByColumn = "PROFILE_ID,TAB_INDEX"
})
EnsureProfileSearchType(BASEDATA_DT_PROFILES_SEARCHES_DATA, "SQL", NameOf(BASEDATA_DT_PROFILES_SEARCHES_DATA))
oSQL = String.Format("SELECT [dbo].[FNPM_LANGUAGE_CONTROL_TEXT] (NAME,'{0}',CTRL_TYPE,CTRL_TEXT) CTRL_CAPTION_LANG, '{0}' as LANGUAGE, * FROM TBPM_PROFILE_CONTROLS WITH (NOLOCK) WHERE CONTROL_ACTIVE = 1", {USER_LANGUAGE})
BASEDATA_TBPM_PROFILE_CONTROLS = DatabaseFallback.GetDatatable("TBPM_PROFILE_CONTROLS_LANGUAGE", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = String.Format("LANGUAGE = '{0}'", {USER_LANGUAGE})
})
If pMode = "Load" Then
DT_FILTERED_PROFILE_SEARCHES_DATA = BASEDATA_DT_PROFILES_SEARCHES_DATA.Clone()
End If
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(60)
LoadVWPM_CONTROL_INDEX()
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(80)
If pMode = "Load" Then
DTVWCONTROL_INDEX = DTVWCONTROLS_INDEX.Clone()
End If
oSQL = $"SELECT * FROM TBPM_PROFILE_CONTROLS WITH (NOLOCK) WHERE CONTROL_ACTIVE = 1 AND LEN(ISNULL(SQL_UEBERPRUEFUNG,'')) > 0 AND CTRL_TYPE <> 'BUTTON'"
DTCONTROLS_WITH_SQL = DatabaseFallback.GetDatatable("DTCONTROLS_WITH_SQL", New GetDatatableOptions(oSQL, DatabaseType.ECM))
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(85)
oSQL = "SELECT * FROM TBPM_PROFILE_FINAL_INDEXING with (NOLOCK) WHERE ACTIVE = 1"
DTTBPM_PROFILE_FINAL_INDEXING = DatabaseFallback.GetDatatable("TBPM_PROFILE_FINAL_INDEXING", New GetDatatableOptions(oSQL, DatabaseType.ECM))
If pMode = "bwBasicData" Then bwBasicData.ReportProgress(100)
Catch ex As Exception
LOGGER.Warn($"Error in GetBaseData - Error: [{ex.Message}]")
End Try
oStopWatch.Done()
End Sub
Private Sub EnsureProfileSearchType(ByRef pTable As DataTable, expectedType As String, tableName As String)
Try
If pTable Is Nothing Then
LOGGER.Warn($"{tableName} is Nothing - type guard skipped")
Exit Sub
End If
If pTable.Columns.Contains("TYPE") = False Then
LOGGER.Warn($"{tableName} has no TYPE column - type guard skipped")
Exit Sub
End If
Dim cleanedTable As DataTable = pTable.Clone()
Dim removedCount As Integer = 0
Dim sampleInvalidSql As String = String.Empty
For Each row As DataRow In pTable.Rows
Dim rowType As String = String.Empty
If row("TYPE") IsNot DBNull.Value Then
rowType = row("TYPE").ToString().Trim().ToUpperInvariant()
End If
If rowType = expectedType.ToUpperInvariant() Then
cleanedTable.ImportRow(row)
Else
removedCount += 1
If sampleInvalidSql = String.Empty AndAlso pTable.Columns.Contains("SQL_COMMAND") Then
If row("SQL_COMMAND") IsNot DBNull.Value Then
sampleInvalidSql = row("SQL_COMMAND").ToString()
End If
End If
End If
Next
If removedCount > 0 Then
LOGGER.Warn($"{tableName}: removed {removedCount} row(s) with unexpected TYPE. Expected TYPE='{expectedType}'.")
If sampleInvalidSql <> String.Empty Then
LOGGER.Warn($"{tableName}: sample unexpected SQL_COMMAND => {sampleInvalidSql}")
End If
End If
LOGGER.Debug($"{tableName}: {cleanedTable.Rows.Count} rows with TYPE='{expectedType}' after type guard.")
pTable = cleanedTable
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Warn($"EnsureProfileSearchType failed for {tableName}")
End Try
End Sub
Private Sub ConfigureGlobalLookAndFeel()
If RIBBON_COLOR_SCHEME <> "" Then
UserLookAndFeel.Default.UseDefaultLookAndFeel = False
If RIBBON_COLOR_SCHEME = "Blue".ToUpper Then
LookAndFeel.SetSkinStyle(SkinStyle.Office2019White, SkinSvgPalette.Office2019White.Yale)
ElseIf RIBBON_COLOR_SCHEME = "Green".ToUpper Then
LookAndFeel.SetSkinStyle(SkinStyle.Office2019White, SkinSvgPalette.Office2019White.Pine)
ElseIf RIBBON_COLOR_SCHEME = "Purple".ToUpper Then
LookAndFeel.SetSkinStyle(SkinStyle.Office2019White, SkinSvgPalette.Office2019White.Plum)
ElseIf RIBBON_COLOR_SCHEME = "Red".ToUpper Then
LookAndFeel.SetSkinStyle(SkinStyle.Office2019White, SkinSvgPalette.Office2019White.FireBrick)
Else
RibbonControl1.ColorScheme = DevExpress.XtraBars.Ribbon.RibbonControlColorScheme.Default
End If
LOGGER.Debug($" RibbonControl1.ColorScheme [{RIBBON_COLOR_SCHEME}]")
End If
End Sub
Private Async Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Text = ADDITIONAL_TITLE
FormShown = True
Try
If CONFIG.Config.MainTreeList_Width > 0 Then
TreeList_Cockpit.Width = CONFIG.Config.MainTreeList_Width
End If
Catch ex As Exception
End Try
Timer_Inactivity_Reset_Disable("Decide_Load")
Dim oFirstNode As DevExpress.XtraTreeList.Nodes.TreeListNode = TreeList_Cockpit.Nodes.FirstOrDefault()
If oFirstNode IsNot Nothing Then
LOGGER.Debug($"Selecting first TreeList node: [{oFirstNode.GetValue("NAME")}]")
TreeList_Cockpit.FocusedNode = oFirstNode
Await ProcessTreeListNodeAsync(oFirstNode)
Else
LOGGER.Debug("No TreeList nodes found - falling back to Decide_Load")
Await Decide_Load(True)
End If
If GridViewWorkflows.GroupCount = 0 And Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then
LOGGER.Info("NO GROUPS AFTER SHOWN_Decide Load...")
Create_GroupBy_Parts()
End If
' ===== SICHTBARKEIT NACH LADEVORGANG NOCHMALS ANWENDEN =====
' AppendCountsToTreeAsync könnte bereits vor frmMain_Shown abgeschlossen sein (Race Condition),
' daher hier sicherstellen, dass die korrekte Sichtbarkeit gesetzt ist
If _treeNodeCounts.Count > 0 Then
LOGGER.Debug($"frmMain_Shown: Applying node visibility after load (Hide_Empty_Workflows=[{CONFIG.Config.Hide_Empty_Workflows}])")
Decide_Show_Empty_Workflows(Not CONFIG.Config.Hide_Empty_Workflows)
End If
Handling_DEBUG_USER()
Dim oSQL = $"SELECT * FROM TBDD_NOTIFICATIONS_SYSTEM NOTE WITH (NOLOCK)
INNER JOIN (SELECT * FROM TBDD_NOTIFICATIONS_SYSTEM WITH (NOLOCK) WHERE LANG_CODE = '{USER_LANGUAGE}' OR LANG_CODE = 'ALL') LANG ON NOTE.GUID = LANG.GUID
where (CONVERT(DATE,GETDATE()) <= NOTE.DISPLAY_UNTIL or NOTE.DISPLAY_UNTIL IS NULL) AND NOTE.MODULE = 'PM'
AND NOTE.GUID NOT IN (SELECT NOTIFY_ID FROM TBDD_NOTIFICATIONS_USER_HISTORY WITH (NOLOCK) WHERE USR_ID = {USER_ID})"
Dim oDT As DataTable = DatabaseFallback.GetDatatable("TBDD_NOTIFICATIONS_SYSTEM", New GetDatatableOptions(oSQL, DatabaseType.ECM))
If Not IsNothing(oDT) Then
If oDT.Rows.Count > 0 Then
NOTIFICATIONS_DT = oDT
BBtnItmNotfications.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Open_Notifications_Form()
End If
End If
End Sub
Sub Open_Notifications_Form()
Try
Dim oEnvironment = GetEnvironment()
Dim oNForm As New frmNotification_Startup(NOTIFICATIONS_DT, LOGCONFIG, GDPICTURE_LICENSE, TITLE_NOTIFICATIONS, oEnvironment)
oNForm.ShowDialog()
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Sub Handling_DEBUG_USER()
If DEBUG = True Then
'bsiDebug.Caption = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("DebugModeActive")
bsiDebug.Caption = S.HINWEIS__Debug_Modus_ist_eingeschaltet_
bsiDebug.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Else
bsiDebug.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If
End Sub
Sub DebuglogBackgroundthread()
Dim oSQL As String = FA_NONE
Try
For Each oSLogstring As String In LOGCONFIG.Logs
Dim oLogSplit As String() = oSLogstring.Split("|")
Dim oMessage = PrepareLogMessage(oSLogstring)
Dim oDateTime As Date = CDate(oLogSplit(0))
oSQL = $"INSERT INTO [dbo].[TBPM_LOG_DEBUG] ([USERID] , [LOGMSG], [ADDED_WHEN],DATE_STR) VALUES({USER_ID},'{oMessage}',GetDate(),'{oDateTime}')"
DatabaseFallback.ExecuteNonQueryECM(oSQL)
Next
LOGCONFIG.ClearLogs()
Catch ex As Exception
LOGGER.Error(ex)
LOGGER.Warn($"oSQL so far [{oSQL}]")
End Try
End Sub
Private Sub tsslblDEBUG_LOG_MouseHover(sender As Object, e As EventArgs)
MsgBox("UserDebugMode is activated remotely. Debugdata will be transferred to database and will be deleted after 10 days!!", MsgBoxStyle.Information, ADDITIONAL_TITLE)
End Sub
Private Sub frmMain_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
If Application.OpenForms().OfType(Of frmValidator).Any Then
_FormValidator.Close()
End If
If Not IsNothing(WINDREAM_MOD) And IDB_ACTIVE = False Then
LOGGER.Debug("Closing frmMain - Now logging out...")
Try
WINDREAM_MOD.Session.Logout()
LOGGER.Debug("WINDREAM_MOD Session logged out successfully.")
Catch ex As Exception
LOGGER.Warn("Error while logging out WINDREAM_MOD Session: {0}", ex.Message)
LOGGER.Error(ex)
End Try
End If
End Sub
Sub Grid_Reset_Filter()
Timer_Inactivity_Reset_Disable("LöscheAlleFilterToolStripMenuItem")
Try
GridViewWorkflows.ClearFindFilter()
GridViewWorkflows.ClearColumnsFilter()
SaveGridLayout()
Catch ex As Exception
End Try
End Sub
Private Sub ContextMenuNotifyIcon_Opening(sender As Object, e As CancelEventArgs) Handles ContextMenuNotifyIcon.Opening
If CONFIG.Config.ReminderTimer <> 0 Then
PopupErinnerungInaktivierenToolStripMenuItem.Text = "Popup Erinnerung inaktivieren"
Else
PopupErinnerungInaktivierenToolStripMenuItem.Text = $"Popup Erinnerung aktivieren ({CONFIG.Config.ReminderTimer} min)"
End If
End Sub
Private Sub PopupErinnerungInaktivierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PopupErinnerungInaktivierenToolStripMenuItem.Click
If CONFIG.Config.ReminderTimer <> 0 Then
TimerReminder.Stop()
TimerReminder.Enabled = False
Else
CONFIG.Config.ReminderTimer = 5
CONFIG.Save()
Check_Timer_Notification()
End If
End Sub
Private Sub AnzeigenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AnzeigenToolStripMenuItem.Click
BringMonitor2Front()
End Sub
Private Sub frmMain_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Try
If FormShown = False Then
Exit Sub
End If
If WindowState = FormWindowState.Maximized Then
My.Settings.frmMainWindowState = "Maximized"
ElseIf WindowState = FormWindowState.Normal Then
My.Settings.frmMainWindowState = "Normal"
End If
My.Settings.Save()
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Sub BarButtonItem3_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniGrundeinstellung.ItemClick
Try
frmKonfig.ShowDialog()
' Load_Profil()
Check_Timer_Notification()
Catch ex As Exception
LOGGER.Error(ex)
MsgBox(ex.Message, MsgBoxStyle.Critical, "Fehler beim Laden Grundeinstellungen:")
End Try
End Sub
Private Async Sub bbtniRefresh_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniRefresh.ItemClick
If Application.OpenForms().OfType(Of frmValidator).Any Then
'FormHelper.ShowInfoMessage(omsgOpenWorkflow, omsgTitleWarning)
FormHelper.ShowInfoMessage(S.Bitte_schließen_Sie_den_offenen_Workflow_, omsgTitleWarning)
Exit Sub
End If
Timer_Inactivity_Reset_Disable("OverviewRefreshClick")
'If GridControlWorkflows.Visible = True And FormOpenClose = False Then
' RefreshHelper.SaveViewInfo()
' SaveGridLayout()
'End If
Await Decide_Load(False, True)
'LoadNavBar()
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.LoadViewInfo()
End If
End Sub
Private Sub bbtniMonitor_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs)
' Prüfen ob bereits ein Monitor mit der aktuellen COCKPIT_MONITOR_ID geöffnet ist
If COCKPIT_MONITOR_ID > 0 Then
Dim existingMonitor = Application.OpenForms().OfType(Of frmMonitor)().FirstOrDefault(Function(f) f.MonitorID = COCKPIT_MONITOR_ID)
If existingMonitor IsNot Nothing Then
LOGGER.Debug($"bbtniMonitor_ItemClick: Monitor with ID [{COCKPIT_MONITOR_ID}] is already open - bringing to front")
existingMonitor.Activate()
existingMonitor.BringToFront()
Exit Sub
End If
End If
Dim newMonitor As New frmMonitor(COCKPIT_MONITOR_ID)
newMonitor.Show()
End Sub
Private Sub bbiProfilverwaltung_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbiProfilverwaltung.ItemClick
'Dim AdminSecurity As Boolean = False
'AdminSecurity = TBPM_KONFIGURATIONTableAdapter.cmdGetAdminSecurity()
'If AdminSecurity = True Then
' frmLoginAdmin.ShowDialog()
'Else
frmAdministration.Show()
' End If
End Sub
Private Sub bbiKonfiguration_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbiKonfiguration.ItemClick
frmAdmin2.ShowDialog()
End Sub
Private Sub bbtniMetadataFile_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniMetadataFile.ItemClick
frmDesignerLayout.Show()
End Sub
Private Sub bwSync_DoWork(sender As Object, e As DoWorkEventArgs) Handles bwSync.DoWork
End Sub
Private Sub bwSync_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bwSync.ProgressChanged
BarEditItem1.EditValue = e.ProgressPercentage
End Sub
Private Sub Timer5Mins_Tick(sender As Object, e As EventArgs) Handles Timer5Mins.Tick
Try
Timer5Mins_running = True
If Not bwBasicData.IsBusy Then
BarEditItem1.Caption = "Get BasicData"
BarEditItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
bwBasicData.RunWorkerAsync()
End If
If DEBUG = True Then
' 'Jetzt der insert der Inhalte
If Not IsNothing(LOGCONFIG.Logs) Then
If LOGCONFIG.Logs.Count > 0 Then
Dim thread As New Thread(AddressOf DebuglogBackgroundthread)
thread.Start()
End If
End If
End If
Catch ex As Exception
LOGGER.Warn($"Timer5Mins Error: {ex.Message}")
End Try
Timer5Mins_running = False
End Sub
Private Sub bwBasicData_DoWork(sender As Object, e As DoWorkEventArgs) Handles bwBasicData.DoWork
GetBaseData("bwBasicData")
End Sub
Private Sub bwBasicData_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bwBasicData.RunWorkerCompleted
Try
If e.Error IsNot Nothing Then
LOGGER.Error(e.Error)
LOGGER.Warn($"bwBasicData completed with error: {e.Error.Message}")
End If
If USER_IS_ADMIN Then
bsiDebug.Caption = String.Format(S.Anzahl_Lizenzen___0_, USERCOUNT_LOGGED_IN)
End If
Catch ex As Exception
LOGGER.Error(ex)
Finally
BarEditItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
' Caption zurücksetzen, falls sie noch auf "busy" steht
If bsiMessage.Caption = "bwBasicData is busy - no Refreshing" Then
bsiMessage.Caption = ""
bsiMessage.ItemAppearance.Normal.BackColor = Color.Transparent
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Empty
End If
End Try
End Sub
Private Sub bwBasicData_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bwBasicData.ProgressChanged
BarEditItem1.EditValue = e.ProgressPercentage
End Sub
Private Sub BarButtonItem2_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs)
If Application.OpenForms().OfType(Of frmInvDashboard).Any Then
Exit Sub
End If
frmInvDashboard.Show()
End Sub
Private Sub OutOfRangePMFixierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OutOfRangePMFixierenToolStripMenuItem.Click
Dim myPoint As System.Drawing.Point = New System.Drawing.Point(50, 50)
Me.Location = Screen.AllScreens(UBound(Screen.AllScreens)).Bounds.Location + myPoint
BringMonitor2Front()
End Sub
Private Sub GridViewWorkflows_RowStyle(sender As Object, e As RowStyleEventArgs) Handles GridViewWorkflows.RowStyle
If FormShown = False Then
Exit Sub
End If
If e.RowHandle = -1 Then
IsFilterMode = True
Exit Sub
End If
If e.RowHandle = DevExpress.XtraGrid.GridControl.AutoFilterRowHandle Then
IsFilterMode = True
' e.Appearance.BackColor = Color.Yellow
Else
IsFilterMode = False
Try
Dim oRowColorCellValue = GridViewWorkflows.GetRowCellValue(e.RowHandle, "ROW_COLOR")
If Not IsNothing(oRowColorCellValue) Then
Dim oColor As Color
Try
If oRowColorCellValue.ToString.Contains(";") Or oRowColorCellValue.ToString.Contains(".") Then
Dim oColorSplit As String()
If oRowColorCellValue.Contains(";") Then
oColorSplit = oRowColorCellValue.Split(";")
ElseIf oRowColorCellValue.Contains(".") Then
oColorSplit = oRowColorCellValue.Split(".")
End If
Try
oColor = Color.FromArgb(oColorSplit(0), oColorSplit(1), oColorSplit(2))
Catch ex As Exception
LOGGER.Info($"RowColorHandler: Could not get Color.FromArgb [{oRowColorCellValue}]")
oColor = Color.LightGray
End Try
Else
Try
oColor = Color.FromName(oRowColorCellValue)
Catch ex As Exception
LOGGER.Info($"RowColorHandler: Could not get Color.FromName [{oRowColorCellValue}]")
End Try
End If
Catch ex As Exception
LOGGER.Info("RowBackColor: " & ex.Message, False)
Exit Sub
End Try
e.Appearance.BackColor = oColor
e.HighPriority = True
End If
Catch ex As Exception
LOGGER.Info("Unexpected Error in RowStyle: " & ex.Message, False)
End Try
End If
End Sub
Private Async Sub BarButtonItem2_ItemClick_1(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnitmGhostMode.ItemClick
frmGhostMode.ShowDialog()
If USER_GHOST_MODE_ACTIVE = True And USER_GHOST_MODE_USRNAME <> String.Empty Then
LOGGER.Info($"GHOST MODE for User {USER_GHOST_MODE_USRNAME} will now be initialized!")
Dim oUserLanguage = User.Language
USER_USERNAME_ORG = USER_USERNAME
BarButtonItemGhostMode.Caption = String.Format(S.Ghost_Modus___0___deaktivieren, USER_GHOST_MODE_USRNAME)
BarButtonItemGhostMode.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
_Init.InitBasics()
_Init.InitUserLogin()
_Init.InitBasics2()
Dim onewUserLanguage = User.Language
GetBaseData("Load")
'LoadNavBar()
If oUserLanguage <> onewUserLanguage Then
MsgBox($"Layout will be reset as language changed from {oUserLanguage} to {onewUserLanguage}", MsgBoxStyle.Exclamation, ADDITIONAL_TITLE)
Await GridLayout_Reset(True)
Else
Await Decide_Load(False)
End If
If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo()
End If
End Sub
Private Async Sub BarButtonItem2_ItemClick_2(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemGhostMode.ItemClick
USER_GHOST_MODE_ACTIVE = False
USER_GHOST_MODE_USRNAME = String.Empty
USER_ID = 0
USER_USERNAME = USER_USERNAME_ORG
BarButtonItemGhostMode.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
_Init.InitUserLogin()
GetBaseData("InactivateGM")
'LoadNavBar()
Await Decide_Load(False)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo()
End Sub
Private Sub GridViewWorkflows_ColumnFilterChanged(sender As Object, e As EventArgs) Handles GridViewWorkflows.ColumnFilterChanged
Try
If FormShown = False Or FRONTEND_ACTION <> FA_NONE Then
Exit Sub
End If
Timer_Inactivity_Reset_Disable("GridViewWorkflows.ColumnFilterChanged")
If DetailLinkActive = False Then
Create_View_Caption()
End If
If GridViewWorkflows.ActiveFilterEnabled Then
End If
If Ev_Filter_Panel_Closed = False Then
Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.DataRowCount)
If GridViewWorkflows.ActiveFilterString <> String.Empty Then
If lblCaptionMainGrid.Text.Contains(oTermFilterActive) Then
Ev_Filter_Panel_Closed = False
End If
' Caption korrekt setzen: Profil-Titel oder Gesamtübersicht
If GRID_LOAD_TYPE.StartsWith("PROFILE#") AndAlso Not String.IsNullOrEmpty(CURRENT_CLICKED_PROFILE_TITLE) Then
LOGGER.Debug($"Setting Grid Caption with Profile Title [{CURRENT_CLICKED_PROFILE_TITLE}] and Filter Active Term [{oTermFilterActive}]")
lblCaptionMainGrid.Text = String.Format("{0} - {1}", CURRENT_CLICKED_PROFILE_TITLE, oTermFilterActive)
Else
LOGGER.Debug($"Setting Grid Caption with Gesamtübersicht and Filter Active Term [{oTermFilterActive}]")
lblCaptionMainGrid.Text = String.Format("{0} - {1}", S.Gesamtübersicht, oTermFilterActive)
End If
bsitmCount.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
bsitmCount.Caption = oTermFilterActive
Else
bsitmCount.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
LOGGER.Debug("No active filter - resetting caption to default")
End If
End If
GridLayout_Changed("ColumnFilterChanged")
Catch ex As Exception
LOGGER.Error(ex.Message)
End Try
End Sub
Private Sub UpdateGridCaption()
Try
LOGGER.Debug($"UpdateGridCaption called - GRID_LOAD_TYPE: [{GRID_LOAD_TYPE}], CURRENT_CLICKED_PROFILE_TITLE: [{CURRENT_CLICKED_PROFILE_TITLE}], NO_WORKFLOWITEMS: [{NO_WORKFLOW_ITEMS}]")
If GRID_LOAD_TYPE = "OVERVIEW" Then
' Übersicht-Caption
lblCaptionMainGrid.Text = S.Gesamtübersicht
' Filter-Info hinzufügen, falls aktiv
If GridViewWorkflows.ActiveFilterString <> String.Empty Then
Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.DataRowCount)
lblCaptionMainGrid.Text = String.Format("{0} - {1}", S.Gesamtübersicht, oTermFilterActive)
End If
ElseIf GRID_LOAD_TYPE.StartsWith("PROFILE#") Then
' Profil-Caption
If Not String.IsNullOrEmpty(CURRENT_CLICKED_PROFILE_TITLE) Then
If NO_WORKFLOW_ITEMS Then
lblCaptionMainGrid.Text = String.Format(S.Aktuell_keine_Workflowdaten_vorhanden___0_, CURRENT_CLICKED_PROFILE_TITLE)
Else
lblCaptionMainGrid.Text = CURRENT_CLICKED_PROFILE_TITLE
End If
End If
End If
LOGGER.Debug($"Grid Caption updated: [{lblCaptionMainGrid.Text}]")
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Sub Create_View_Caption()
UpdateGridCaption()
End Sub
Sub Grid_Export()
XtraSaveFileDialog1.FileName = "Overview.xlsx"
XtraSaveFileDialog1.DefaultExt = ".xlsx"
If XtraSaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim oOptions As New XlsxExportOptions() With {
.ExportMode = XlsxExportMode.SingleFile
}
GridViewWorkflows.ExportToXlsx(XtraSaveFileDialog1.FileName, oOptions)
End If
End Sub
Private Sub TimerInactivity_Tick(sender As Object, e As EventArgs) Handles TimerInactivity.Tick
Try
If Application.OpenForms().OfType(Of frmValidator).Any Then
bsiMessage.Caption = "Validation Active - no Inactivity-Logout"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Timer_Inactivity_Reset_Disable("frmValidator")
Exit Sub
End If
If Application.OpenForms().OfType(Of frmAdministration).Any Then
bsiMessage.Caption = "Administration Active - no Inactivity-Logout"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Timer_Inactivity_Reset_Disable("frmAdministration")
Exit Sub
End If
If Application.OpenForms().OfType(Of frmAdmin2).Any Then
bsiMessage.Caption = "Administration2 Active - no Inactivity-Logout"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Timer_Inactivity_Reset_Disable("frmAdmin2")
Exit Sub
End If
If Application.OpenForms().OfType(Of frmMonitor).Any Then
bsiMessage.Caption = "Monitoring open - no Inactivity-Logout"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Timer_Inactivity_Reset_Disable("frmMonitor")
Exit Sub
End If
If GHOSTMODE_ACTIVE And USER_GHOST_MODE_ACTIVE Then
bsiMessage.Caption = "GhostMode Active - no Inactivity-Logout"
bsiMessage.ItemAppearance.Normal.BackColor = Color.Yellow
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
Timer_Inactivity_Reset_Disable("USER_GHOST_MODE_ACTIVE")
Exit Sub
End If
INACTIVITYRecognized = True
'Dim omsg As String = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("INACTIVITYRecognized")
Dim omsg As String = S.Sie_wurden_aufgrund_von_Inaktivität_automatisch_abgemeldet_
Timer5Mins.Stop()
TimerRefresh.Stop()
TimerReminder.Stop()
LOGGER.Info("Inactivity recognized. Automatic Logout In process!")
Hide()
ClassAllgemeineFunktionen.LoginOut("LOGOUT")
TimerInactivity.Stop()
MsgBox(omsg, MsgBoxStyle.Information, ADDITIONAL_TITLE)
Application.Exit()
Catch ex As Exception
LOGGER.Error(ex.Message)
End Try
End Sub
Private Sub BarButtonItem3_ItemClick_1(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles SearchItem1.ItemClick
Try
Dim oTag = SearchItem1.Tag
Dim _SPLIT As String()
_SPLIT = oTag.Split("%")
Dim oPath = LTrim(RTrim(_SPLIT(0).ToString))
Dim MyProcess As New Process()
MyProcess.StartInfo.FileName = oPath
MyProcess.StartInfo.Arguments = LTrim(RTrim(_SPLIT(1).ToString))
MyProcess.Start() 'Startet den Prozess
Catch ex As Exception
LOGGER.Error(ex.Message)
End Try
End Sub
Private Sub bbtniCW_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniCW.ItemClick
Try
If File.Exists(bbtniCW.Tag) Then
Dim MyProcess As New Process()
MyProcess.StartInfo.FileName = bbtniCW.Tag
MyProcess.Start()
Else
LOGGER.Warn($"easyFLOW-Exe Not found [{bbtniCW.Tag}]")
FormHelper.ShowInfoMessage("Clipboard Watcher could Not be started!", omsgTitleWarning)
End If
Catch ex As Exception
LOGGER.Error(ex.Message)
End Try
End Sub
Private Sub GridViewWorkflows_ColumnPositionChanged(sender As Object, e As EventArgs) Handles GridViewWorkflows.ColumnPositionChanged
GridLayout_Changed("ColumnPositionChanged")
End Sub
Private Sub GridLayout_Changed(oEvent As String)
If FormShown = False Or Ev_Filter_Panel_Closed Then
Exit Sub
End If
If FRONTEND_ACTION <> FA_NONE Then
Exit Sub
End If
SaveGridLayout()
End Sub
Private Sub GridViewWorkflows_EndGrouping(sender As Object, e As EventArgs) Handles GridViewWorkflows.EndGrouping
GridLayout_Changed("EndGrouping")
End Sub
Private Sub bsilastsync_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bsilastsync.ItemClick
End Sub
Private Sub GridViewWorkflows_KeyDown(sender As Object, e As KeyEventArgs) Handles GridViewWorkflows.KeyDown
Dim view As GridView = CType(sender, GridView)
If e.Control AndAlso e.KeyCode = Keys.C Then
If view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn) IsNot Nothing AndAlso view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn).ToString() <> [String].Empty Then
Clipboard.SetText(view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn).ToString())
End If
e.Handled = True
End If
End Sub
Private Sub BarCheckItem1_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarCheckItemAutofilter.CheckedChanged
If GridIsLoaded = True Then
GridViewWorkflows.OptionsView.ShowAutoFilterRow = BarCheckItemAutofilter.Checked
End If
End Sub
Private Sub BarCheckItem1_CheckedChanged_1(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarCheckItemShowSearch.CheckedChanged
If GridIsLoaded = True Then
GridViewWorkflows.OptionsFind.AlwaysVisible = BarCheckItemShowSearch.Checked
End If
End Sub
Private Sub BarButtonItem4_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem4.ItemClick
Grid_Layout_Save()
End Sub
Sub Grid_Layout_Save()
FRONTEND_ACTION = "SAVE GRID LAYOUT"
GridViewWorkflows.OptionsView.ShowViewCaption = False
GridLayout_Changed("Grid_Layout_Save")
FRONTEND_ACTION = FA_NONE
End Sub
Private Sub BarButtonItem5_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemExportExcel.ItemClick
Grid_Export()
End Sub
Private Sub BarButtonItem6_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem6.ItemClick
Grid_Reset_Filter()
End Sub
Private Sub BarButtonItem7_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem7.ItemClick
GridViewWorkflows.ShowCustomization()
End Sub
Private Async Sub BarButtonItem8_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemWFSingle.ItemClick
Me.Cursor = Cursors.WaitCursor
Await Item_Scope("CMROW")
Me.Cursor = Cursors.Default
End Sub
Private Async Sub BarButtonItemWFGroup_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemWFGroup.ItemClick
Me.Cursor = Cursors.WaitCursor
Await Item_Scope("CMGROUP")
Me.Cursor = Cursors.Default
End Sub
Private Sub BarButtonItemFileLink_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemFileLink.ItemClick
Dim oReceipiant = ""
Dim oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID"))
Dim oSQL = $"Select [dbo].[FNPM_GET_FILEPATH] ({oFocusedDocGUID}, 1)"
Dim oFilePath = DatabaseFallback.GetScalarValueECM(oSQL)
If File.Exists(oFilePath) Then
Dim oLink = "<HTML><body><p><a href=" + "file:///" + oFilePath + ">Link zur Datei</a></p></body></HTML>"
Dim oLink2 = "<a href=" + "file:///" + oFilePath + ">Link zur Datei</a>"
If Not IsNothing(oFilePath) Then
Process.Start($"mailto:{oReceipiant}?subject=Link aus taskFLOW Manager&body={oLink}")
End If
End If
End Sub
Private Async Sub BarButtonItemMassValidation_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemMassValidation.ItemClick
Try
Dim oSelectedRows As Integer() = GridViewWorkflows.GetSelectedRows()
Dim oHitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(GridCursorLocation)
Dim oSelectedRowHandle As Integer = oHitInfo.RowHandle
Dim oWorkedFiles As Integer = 0
Dim oProfileId = 0
If oSelectedRows.Count = 0 Then
'Dim omsg = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("MASS_NO_WF_SELECTED")
Dim omsg = S.Bitte_wählen_Sie_ein_Profil_aus_
FormHelper.ShowInfoMessage(omsg, omsgTitleWarning)
Exit Sub
End If
oProfileId = GridViewWorkflows.GetRowCellValue(oSelectedRows.Last(), GridViewWorkflows.Columns("PROFILE_ID"))
If oProfileId = 0 Then
FormHelper.ShowInfoMessage("Could not select a profile!", omsgTitleWarning)
Exit Sub
End If
If SOURCE_INIT = True Then
CURRENT_ProfilGUID = oProfileId
Dim oSQL = $"select * from TBPM_PROFILE_FINAL_INDEXING WITH (NOLOCK) where PROFIL_ID = {CURRENT_ProfilGUID} ORDER BY [SEQUENCE]"
'CURRENT_DT_FINAL_INDEXING = DataASorDB.GetDatatable("DD_ECM", oSQL, "TBPM_PROFILE_FINAL_INDEXING", $"PROFIL_ID = {CURRENT_ProfilGUID}", "SEQUENCE")
CURRENT_DT_FINAL_INDEXING = DatabaseFallback.GetDatatable("TBPM_PROFILE_FINAL_INDEXING", New GetDatatableOptions(oSQL, DatabaseType.ECM) With {
.FilterExpression = $"PROFIL_ID = {CURRENT_ProfilGUID}",
.SortByColumn = "SEQUENCE"
})
CURRENT_DT_PROFILE = Nothing '.Clear
CURRENT_DT_PROFILE = CURRENT_DT_PROFILES.Clone
Dim oExpression = $"GUID = {CURRENT_ProfilGUID}"
CURRENT_DT_PROFILES.Select(oExpression).CopyToDataTable(CURRENT_DT_PROFILE, LoadOption.PreserveChanges)
If CURRENT_DT_PROFILE.Rows.Count = 1 Then
CURRENT_ProfilName = CURRENT_DT_PROFILE.Rows(0).Item("NAME")
PROFILE_SHOW_DOCUMENT = CURRENT_DT_PROFILE.Rows(0).Item("SHOW_DOCUMENT")
PROFILE_NOT_RESP_COMMENT = CURRENT_DT_PROFILE.Rows(0).Item("NOT_RESP_COMMENT")
ActiveWorkflowType = 1
Else
Exit Sub
End If
CURRENT_PROFILE_LOG_INDEX = CURRENT_DT_PROFILE.Rows(0).Item("PM_VEKTOR_INDEX")
If CURRENT_PROFILE_LOG_INDEX = "" Then
CURRENT_PROFILE_LOG_INDEX = CURRENT_DT_PROFILE.Rows(0).Item("LOG_INDEX")
End If
Dim NewDatatable As New DataTable
NewDatatable.Columns.Add("DocID")
NewDatatable.Columns.Add("DOC_GUID")
NewDatatable.Columns.Add("FULL_PATH")
For Each oRowHandle As Integer In oSelectedRows
Dim oDocID = GridViewWorkflows.GetRowCellValue(oRowHandle, "DocID")
If IsNothing(oDocID) Then
Continue For
End If
Dim R As DataRow = NewDatatable.NewRow
CURRENT_DOC_ID = oDocID
Dim DOC_PATH = GridViewWorkflows.GetRowCellValue(oRowHandle, FullFilepatColName)
' CURRENT_DOC_PATH = DOC_PATH
CURRENT_DOC_GUID = GridViewWorkflows.GetRowCellValue(oRowHandle, "GUID")
R("DocID") = CURRENT_DOC_ID
R("FULL_PATH") = DOC_PATH
R("DOC_GUID") = GridViewWorkflows.GetRowCellValue(oRowHandle, "GUID")
NewDatatable.Rows.Add(R)
Next
CURRENT_DT_MASS_CHANGE_DOCS = Nothing
CURRENT_DT_MASS_CHANGE_DOCS = NewDatatable
TimerRefresh.Enabled = False
frmMassValidator.ShowDialog()
'LoadNavBar()
Await Decide_Load(False)
Else
'Dim oMSG = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("MASS_ERROR_WINDREAM")
Dim oMSG = S.Massenabschluss_konnte_nicht_ausgeführt_werden__weil_windream_nicht_initialisiert_werden_konnte_
MsgBox(oMSG, MsgBoxStyle.Critical, "Unexpected Error Massvalidation")
End If
Catch ex As Exception
LOGGER.Error(ex)
MsgBox("Unhandled Error in tsmiMarkedFilesFinish_Click: " & ex.Message)
End Try
End Sub
Private Sub RibbonControl1_SelectedPageChanged(sender As Object, e As EventArgs) Handles RibbonControl1.SelectedPageChanged
Dim ribbon As RibbonControl = TryCast(sender, RibbonControl)
Timer_Inactivity_Reset_Disable("RibbonControl1_SelectedPageChanged")
If ribbon.SelectedPage Is RibbonPageAktionen Then
If USER_GHOST_MODE_ACTIVE = True And USER_GHOST_MODE_USRNAME <> String.Empty Then
LOGGER.Debug("Ghostmode is active...")
bbtnitmLanguage_Change.Enabled = False
Else
bbtnitmLanguage_Change.Enabled = True
End If
Select Case GridViewItem_Clicked
Case "GROUP"
If SHOW_MASS_VALIDATOR = True Then
BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
End If
Case "ROW"
' If selectedRows.Count > 1 Then
' CMFileStart.Enabled = False
' Else
' CMFileStart.Enabled = True
' End If
' If CURRENT_CLICKED_PROFILE_ID > 0 Then
' CMGroupStart.Enabled = True
' End If
End Select
End If
End Sub
Private Sub barItemGridFontSize_EditValueChanged(sender As Object, e As EventArgs) Handles barItemGridFontSize.EditValueChanged
Try
Dim fontDelta As Integer = DirectCast(barItemGridFontSize.EditValue, FontSetting).Value
' Schriftgröße im Grid anpassen
CONFIG.Config.GridFontSizeDelta = fontDelta
CONFIG.Save()
GridBuilder.WithFontSizeDelta(fontDelta)
' Schriftgröße im TreeList anpassen
Dim baseFont As Font = TreeList_Cockpit.Appearance.Row.Font
If baseFont Is Nothing Then
baseFont = New Font("Segoe UI", 12, FontStyle.Regular)
End If
Dim newSize As Single = 12 + fontDelta ' Basis-Größe 12pt
If newSize < 8 Then newSize = 8 ' Mindestgröße
If newSize > 20 Then newSize = 20 ' Maximalgröße
TreeList_Cockpit.Appearance.Row.Font = New Font(baseFont.FontFamily, newSize, FontStyle.Regular)
TreeList_Cockpit.Appearance.FocusedRow.Font = New Font(baseFont.FontFamily, newSize, FontStyle.Bold)
TreeList_Cockpit.Appearance.HideSelectionRow.Font = New Font(baseFont.FontFamily, newSize, FontStyle.Regular)
' TreeList neu zeichnen
TreeList_Cockpit.Refresh()
Catch ex As Exception
End Try
End Sub
Private Sub GridViewWFItems_SelectionChanged(sender As Object, e As DevExpress.Data.SelectionChangedEventArgs) Handles GridViewWorkflows.SelectionChanged
Timer_Inactivity_Reset_Disable("GridViewWFItems_SelectionChanged")
End Sub
Private Sub GridViewWFItems_Click(sender As Object, e As MouseEventArgs) Handles GridViewWorkflows.Click
Try
If e.Button = Windows.Forms.MouseButtons.Right Then
RibbonControl1.SelectedPage = RibbonPageTabelle
Else
RibbonControl1.SelectedPage = RibbonPageStart
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Sub frmMain_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
Try
'System.Diagnostics.Process.GetCurrentProcess().Kill()
Catch ex As Exception
End Try
End Sub
Private Sub GridViewWFItems_SubstituteFilter(sender As Object, e As DevExpress.Data.SubstituteFilterEventArgs) Handles GridViewWorkflows.SubstituteFilter
GridLayout_Changed("GridViewWFItems_SubstituteFilter")
End Sub
Private Sub BbtnitmAHWF1_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BbtnitmAHWF1.ItemClick, BbtnitmAHWF2.ItemClick, BbtnitmAHWF3.ItemClick, BbtnitmAHWF4.ItemClick
Dim obutton As DevExpress.XtraBars.BarButtonItem = TryCast(e.Item, DevExpress.XtraBars.BarButtonItem)
AdHocWorkflow_BlindFile(obutton.Tag)
End Sub
Private Sub AdHocWorkflow_BlindFile(pProfileID As Int16)
Try
If Not Application.OpenForms().OfType(Of frmValidator).Any Then
Dim oExpression = $"GUID = {pProfileID}"
LOGGER.Debug($"Starting AHWFNoFile for ProfileID: {pProfileID}...")
CURRENT_DT_PROFILE = Nothing
CURRENT_DT_PROFILE = CURRENT_DT_PROFILES.Clone
CURRENT_DT_PROFILES.Select(oExpression).CopyToDataTable(CURRENT_DT_PROFILE, LoadOption.PreserveChanges)
If CURRENT_DT_PROFILE.Rows.Count = 1 Then
CURRENT_ProfilGUID = pProfileID
Dim sGUID As String
sGUID = System.Guid.NewGuid.ToString()
Dim oTargetPath = CURRENT_DT_PROFILE.Rows(0).Item("TARGET_PATH_BLIND_FILE")
Dim oSourcePath = CURRENT_DT_PROFILE.Rows(0).Item("WD_SEARCH")
Dim oWMObjecttype = CURRENT_DT_PROFILE.Rows(0).Item("WD_OBJECTTYPE")
LOGGER.Debug($"oTargetPath: {oTargetPath}")
LOGGER.Debug($"oSourcePath: {oSourcePath}")
If oTargetPath = String.Empty Or oSourcePath = String.Empty Then
LOGGER.Warn($"oTargetPath is nothing - PRofile can not be startet . Check TARGET_PATH_BLIND_FILE Column in Profile")
Exit Sub
End If
oTargetPath = $"{oTargetPath}\{Now.Year}\{Now.Month}\{Now.Day}"
oTargetPath = oTargetPath & "\" & sGUID & ".pdf"
LOGGER.Debug($"oTargetPath with NowParams: {oTargetPath}")
Dim oResult = WINDREAM_MOD.NewFileStream(oSourcePath, oTargetPath, oWMObjecttype)
If oResult = True Then
WM_AHWF_docPath = oTargetPath
Dim oDocID = WINDREAM_MOD.NewDocumentID
CURRENT_CLICKED_PROFILE_ID = pProfileID
PROFILE_SHOW_DOCUMENT = CURRENT_DT_PROFILE.Rows(0).Item("SHOW_DOCUMENT")
CURRENT_CLICKED_PROFILE_TITLE = CURRENT_DT_PROFILE.Rows(0).Item("TITLE")
CURRENT_WMObjecttype = CURRENT_DT_PROFILE.Rows(0).Item("WD_OBJECTTYPE")
CURRENT_DOC_ID = oDocID
CURRENT_DOC_GUID = 99123456789
ActiveWorkflowType = ConstAHWorkflow_BlindFile
CURRENT_JUMP_DOC_GUID = CURRENT_DOC_GUID
DT_FILTERED_PROFILE_SEARCHES_DOC = Nothing
DT_FILTERED_PROFILE_SEARCHES_DOC = BASEDATA_DT_PROFILES_SEARCHES_DOC.Copy
DT_FILTERED_PROFILE_SEARCHES_DOC.Clear()
oExpression = $"PROFILE_ID = {CURRENT_ProfilGUID}"
BASEDATA_DT_PROFILES_SEARCHES_DOC.Select(oExpression, "TAB_INDEX").CopyToDataTable(DT_FILTERED_PROFILE_SEARCHES_DOC, LoadOption.PreserveChanges)
DT_FILTERED_PROFILE_SEARCHES_DATA = Nothing
DT_FILTERED_PROFILE_SEARCHES_DATA = BASEDATA_DT_PROFILES_SEARCHES_DATA.Copy
DT_FILTERED_PROFILE_SEARCHES_DATA.Clear()
BASEDATA_DT_PROFILES_SEARCHES_DATA.Select(oExpression, "TAB_INDEX").CopyToDataTable(DT_FILTERED_PROFILE_SEARCHES_DATA, LoadOption.PreserveChanges)
Try
Dim oEnvironment = GetEnvironment()
_FormValidator = New frmValidator(oEnvironment)
AddHandler _FormValidator.FormClosed, AddressOf ValidatorClosed
_FormValidator.Show()
Catch ex As Exception
LOGGER.Warn($"Error opening Form frmValidator [{ex.Message}]")
LOGGER.Warn($"ex.InnerException.Message [{ex.InnerException.Message}]")
LOGGER.Warn($"ex.InnerException.Source [{ex.InnerException.Source}]")
LOGGER.Error(ex.InnerException)
MsgBox(ex.Message, MsgBoxStyle.Critical, ADDITIONAL_TITLE)
End Try
End If
Else
LOGGER.Info("Attention: CURRENT_DT_PROFILE.Rows.Count <> 1")
End If
Else
FormHelper.ShowInfoMessage(S.Bitte_schließen_Sie_den_offenen_Workflow_, omsgTitleWarning)
Exit Sub
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Sub bbtnitmLanguage_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnitmLanguage_Change.ItemClick
Dim oNForm As New frmLanguage_Select(LOGCONFIG, CONNECTION_STRING_ECM, USER_USERNAME, BASEDATA_DT_LANGUAGE, "TF")
oNForm.ShowDialog()
If oNForm.pChanged = True Then
MsgBox("For the changes to take effect, the program must now be closed. Restart it afterwards.", MsgBoxStyle.Exclamation, "Restart:")
Me.Close()
End If
End Sub
Private Sub BBtnItmNotfications_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BBtnItmNotfications.ItemClick
Open_Notifications_Form()
End Sub
Private Sub GridViewWFItems_Click(sender As Object, e As EventArgs) Handles GridViewWorkflows.Click
End Sub
Private Async Sub BarButtonItem3_ItemClick_2(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemResetLayout.ItemClick
LOGGER.Info("User clicked reset layout")
Await GridLayout_Reset(True)
End Sub
Private Sub barbtnitmsaveLogfiles_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles barbtnitmsaveLogfiles.ItemClick
ClassAllgemeineFunktionen.Save_Logfiles()
End Sub
Private Async Function ProcessTreeListNodeAsync(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode) As Task
Try
Dim oTypeId As Object = oNode.GetValue("TYPE_ID")
Dim oCockpitConfigID As Object = oNode.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
Dim oFkProfileId As Object = oNode.GetValue("FK_PROFILE_ID")
Dim oSqlQuery As Object = oNode.GetValue("SQL_QUERY")
Dim oProfileTitle As Object = oNode.GetValue("NAME")
LOGGER.Debug($"TreeList_Cockpit Node selected - PK_CFG_COCKPIT_DEFINITION_ID:[{oCockpitConfigID}] NAME:[{oProfileTitle}] TYPE_ID:[{oTypeId}] FK_PROFILE_ID:[{oFkProfileId}]")
If oTypeId Is Nothing OrElse IsDBNull(oTypeId) Then
LOGGER.Debug("ProcessTreeListNodeAsync: TYPE_ID is Nothing/DBNull - Folder node, skipping")
Exit Function
End If
RibbonPageGroup7.Visible = False
FRONTEND_ACTION = NAVBAR_CLICKED
Timer_Inactivity_Reset_Disable("TreeList1_FocusedNodeChanged")
COCKPIT_CONFIG_ID = oCockpitConfigID
COCKPIT_PROFILE_SQL = String.Empty
Dim oTypeIdInt As Integer = CInt(oTypeId)
If oTypeIdInt = 0 Or oTypeId = 1 Then
If Application.OpenForms().OfType(Of frmValidator).Any Then
FormHelper.ShowInfoMessage(S.Bitte_schließen_Sie_den_offenen_Workflow_, omsgTitleWarning)
Exit Function
End If
End If
Select Case oTypeIdInt
Case 0
LOGGER.Debug("TreeList_Cockpit: Loading overview")
OverviewOrDEtail = "OVERVIEW"
GRID_LOAD_TYPE = "OVERVIEW"
Dim oForce As Boolean = False
If DetailLinkActive = True Then
oForce = True
DetailLinkActive = False
OVERVIEW_ADDED_WHEN = ""
End If
If IsDBNull(oSqlQuery) OrElse String.IsNullOrWhiteSpace(oSqlQuery?.ToString()) Then
LOGGER.Warn($"TreeList_Cockpit: SQL_QUERY for ProfileID {oFkProfileId} is DBNull or empty for overview node - this should not happen, check data integrity of TreeList's DataSource")
Exit Function
Else
LOGGER.Debug($"TreeList_Cockpit: Overview SQL query to be used: [{oSqlQuery}]")
End If
' ✅ NEU: Verifizieren Sie die Zuweisung
LOGGER.Debug($"TreeList_Cockpit: COCKPIT_PROFILE_SQL after assignment: [{COCKPIT_PROFILE_SQL}]")
LOGGER.Debug($"TreeList_Cockpit: COCKPIT_PROFILE_SQL.Length = [{COCKPIT_PROFILE_SQL.Length}]")
CURRENT_CLICKED_PROFILE_ID = 0
CUSTOM_OVERVIEW_SQL = oSqlQuery.ToString()
_lastUsedOverviewSQL = CUSTOM_OVERVIEW_SQL ' ← SQL merken BEVOR es gelöscht wird
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.SaveViewInfo()
End If
Me.Cursor = Cursors.WaitCursor
Try
Await Decide_Load(False, oForce)
Finally
Me.Cursor = Cursors.Default
End Try
' ✅ CUSTOM_OVERVIEW_SQL erst HIER leeren nach dem kompletten Lade-Zyklus inkl. internem GridLayout_Reset
LOGGER.Debug("TreeList_Cockpit: Clearing CUSTOM_OVERVIEW_SQL after loading overview")
CUSTOM_OVERVIEW_SQL = String.Empty
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.LoadViewInfo()
End If
If GridViewWorkflows.GroupCount = 0 AndAlso Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then
LOGGER.Info("TreeList_Cockpit: NO GROUPS AFTER CLICK OVERVIEW - creating groups...")
Await Decide_Load(False, True)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.LoadViewInfo()
End If
End If
RibbonPageGroup7.Visible = True
Case 1
If oFkProfileId Is Nothing OrElse IsDBNull(oFkProfileId) Then
LOGGER.Warn("TreeList_Cockpit: TYPE_ID=1 but FK_PROFILE_ID is Nothing/DBNull")
Exit Function
End If
Dim oProfileId As Integer = CInt(oFkProfileId)
LOGGER.Debug($"TreeList_Cockpit: Profile node clicked - FK_PROFILE_ID:[{oProfileId}]")
If CURRENT_CLICKED_PROFILE_ID = oProfileId Then
LOGGER.Debug($"TreeList_Cockpit: Profile [{oProfileId}] is already active - ignoring click")
Exit Function
End If
LOGGER.Debug($"TreeList_Cockpit: Loading profile with ID [{oProfileId}]...")
If IsDBNull(oSqlQuery) OrElse String.IsNullOrWhiteSpace(oSqlQuery?.ToString()) Then
LOGGER.Warn($"TreeList_Cockpit: SQL_QUERY for ProfileID {oFkProfileId} is DBNull or empty for Profile-Node - this should not happen, check data integrity of TreeList's DataSource")
Exit Function
Else
LOGGER.Debug($"TreeList_Cockpit: Profile-SQL query to be used: [{oSqlQuery}]")
End If
COCKPIT_PROFILE_SQL = oSqlQuery.ToString()
' ===== ANZAHL-SUFFIX ENTFERNEN (von AppendCountsToTreeAsync angehängt: "Titel (42)" → "Titel") =====
Dim oCleanProfileTitle As String = oProfileTitle?.ToString()
Dim oSuffixMatch = System.Text.RegularExpressions.Regex.Match(oCleanProfileTitle, "^(.*)\s+\(\d+\)$")
If oSuffixMatch.Success Then
oCleanProfileTitle = oSuffixMatch.Groups(1).Value.Trim()
LOGGER.Debug($"TreeList_Cockpit: Stripped count suffix from title [{oProfileTitle}] → [{oCleanProfileTitle}]")
End If
OverviewOrDEtail = "DETAIL"
CURRENT_CLICKED_PROFILE_ID = oProfileId
CURRENT_CLICKED_PROFILE_TITLE = oCleanProfileTitle
GRID_LOAD_TYPE = $"PROFILE#{oProfileId}"
DetailLinkActive = True
If GridControlWorkflows.Visible = True And FormOpenClose = False Then
RefreshHelper.SaveViewInfo()
End If
Me.Cursor = Cursors.WaitCursor
Try
Await Decide_Load(False, True)
Finally
Me.Cursor = Cursors.Default
End Try
Case 2
Dim oMONITOR_ID As Object = oNode.GetValue("FK_MONITOR_ID")
If oMONITOR_ID Is Nothing OrElse IsDBNull(oMONITOR_ID) Then
LOGGER.Warn($"TreeList_Cockpit: TYPE_ID=2 but FK_MONITOR_ID is Nothing/DBNull - PK_CFG_COCKPIT_DEFINITION_ID:[{oCockpitConfigID}]")
Exit Function
End If
Dim oMonitorIdInt As Integer = CInt(oMONITOR_ID)
' Prüfen ob bereits ein Monitor mit dieser ID geöffnet ist
Dim existingMonitor = Application.OpenForms().OfType(Of frmMonitor)().FirstOrDefault(Function(f) f.MonitorID = oMonitorIdInt)
If existingMonitor IsNot Nothing Then
LOGGER.Debug($"TreeList_Cockpit: Monitor with ID [{oMonitorIdInt}] is already open - bringing to front")
existingMonitor.Activate()
existingMonitor.BringToFront()
Exit Function
End If
COCKPIT_MONITOR_ID = oMonitorIdInt
COCKPIT_MONITOR_CAPTION = oNode.GetValue("NAME")
' ✅ KEIN Overlay bei Monitor-Öffnung
' Overlay nur bei Datenlade-Operationen (Case 0, 1)
Me.Cursor = Cursors.WaitCursor
Try
Dim newMonitor As New frmMonitor(oMonitorIdInt)
newMonitor.Show()
newMonitor.Activate()
newMonitor.BringToFront()
Finally
Me.Cursor = Cursors.Default
End Try
Case 3
Dim oCHART_ID As Object = oNode.GetValue("FK_CHART_ID")
If oCHART_ID Is Nothing OrElse IsDBNull(oCHART_ID) Then
LOGGER.Warn($"TreeList_Cockpit: TYPE_ID=3 but FK_CHART_ID is Nothing/DBNull - PK_CFG_COCKPIT_DEFINITION_ID:[{oCockpitConfigID}]")
Exit Function
End If
COCKPIT_CHART_ID = oCHART_ID
' ✅ KEIN Overlay bei Dashboard (verhindert Fokus-Raub)
Me.Cursor = Cursors.WaitCursor
Try
' ===== SCHRITT 1: Dashboard öffnen/referenzieren =====
Dim dashboardForm As frmInvDashboard
If Application.OpenForms().OfType(Of frmInvDashboard).Any Then
' Dashboard ist bereits offen
dashboardForm = Application.OpenForms().OfType(Of frmInvDashboard).First()
LOGGER.Debug("TreeList_Cockpit: Dashboard already open - reusing existing instance")
Else
' Dashboard neu öffnen
dashboardForm = New frmInvDashboard()
dashboardForm.Show()
LOGGER.Debug("TreeList_Cockpit: Dashboard opened new instance")
End If
' ===== SCHRITT 2: Garantierte Vordergrund-Aktivierung =====
' TopMost temporär setzen (wird sofort wieder entfernt)
dashboardForm.TopMost = True
dashboardForm.TopMost = False
' Aktivieren und Fokus setzen
dashboardForm.Activate()
dashboardForm.BringToFront()
dashboardForm.Focus()
' ===== SCHRITT 3: Windows-API als Fallback (optional) =====
' Falls DevExpress hartnäckig ist
NativeMethods.SetForegroundWindow(dashboardForm.Handle)
Finally
Me.Cursor = Cursors.Default
End Try
Case Else
LOGGER.Warn($"ProcessTreeListNodeAsync: Unhandled TYPE_ID [{oTypeIdInt}] - PK_CFG_COCKPIT_DEFINITION_ID:[{oCockpitConfigID}]")
End Select
Catch ex As Exception
LOGGER.Error(ex)
Finally
FRONTEND_ACTION = FA_NONE
End Try
End Function
Private Async Sub TreeList1_FocusedNodeChanged(sender As Object, e As DevExpress.XtraTreeList.FocusedNodeChangedEventArgs) Handles TreeList_Cockpit.FocusedNodeChanged
Try
If e.Node Is Nothing Then
LOGGER.Debug("TreeList1_FocusedNodeChanged: Node is Nothing - skipping")
Exit Sub
End If
If FormShown = False Then
LOGGER.Debug("TreeList1_FocusedNodeChanged: Form not shown - skipping")
Exit Sub
End If
LOGGER.Debug("TreeList1_FocusedNodeChanged: Node changed - processing")
Await ProcessTreeListNodeAsync(e.Node)
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Async Sub TreeList_Cockpit_Click(sender As Object, e As EventArgs) Handles TreeList_Cockpit.Click
Try
Dim oFocusedNode As DevExpress.XtraTreeList.Nodes.TreeListNode = TreeList_Cockpit.FocusedNode
If oFocusedNode Is Nothing Then Exit Sub
Dim oTypeId As Object = oFocusedNode.GetValue("TYPE_ID")
If oTypeId Is Nothing OrElse IsDBNull(oTypeId) OrElse CInt(oTypeId) <> 2 Then
Exit Sub
End If
' ===== PRÜFEN OB MONITOR BEREITS GEÖFFNET IST =====
Dim oMonitorId As Object = oFocusedNode.GetValue("FK_MONITOR_ID")
If oMonitorId Is Nothing OrElse IsDBNull(oMonitorId) Then
Exit Sub
End If
Dim oMonitorIdInt As Integer = CInt(oMonitorId)
Dim existingMonitor = Application.OpenForms().OfType(Of frmMonitor)().FirstOrDefault(Function(f) f.MonitorID = oMonitorIdInt)
If existingMonitor IsNot Nothing Then
' ✅ Monitor ist offen → Nach vorne bringen
LOGGER.Debug($"TreeList_Cockpit_NodeCellClick: Monitor [{oMonitorIdInt}] already open - bringing to front")
existingMonitor.Activate()
existingMonitor.BringToFront()
Else
' ✅ Monitor ist geschlossen → Neu öffnen via ProcessTreeListNodeAsync
LOGGER.Debug($"TreeList_Cockpit_NodeCellClick: Monitor [{oMonitorIdInt}] closed - reopening")
Await ProcessTreeListNodeAsync(oFocusedNode)
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Sub BarButtonItemCock_refresh_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemCock_refresh.ItemClick
Load_Treeview()
End Sub
Private Sub Bchkitm_load_empty_wf_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles Bchkitm_load_empty_wf.CheckedChanged
If FormShown = False Then
Exit Sub
End If
CONFIG.Config.Hide_Empty_Workflows = Bchkitm_load_empty_wf.Checked
CONFIG.Save()
End Sub
Private Sub Bchkitm_load_empty_wf_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles Bchkitm_load_empty_wf.ItemClick
Decide_Show_Empty_Workflows(Not Bchkitm_load_empty_wf.Checked)
End Sub
Sub Decide_Show_Empty_Workflows(pShow As Boolean)
Try
LOGGER.Debug($"Decide_Show_Empty_Workflows: pShow=[{pShow}], cached node counts: [{_treeNodeCounts.Count}]")
TreeList_Cockpit.BeginUpdate()
Try
TreeList_Cockpit.NodesIterator.DoOperation(
Sub(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode)
Dim oPk As Object = oNode.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk Is Nothing OrElse IsDBNull(oPk) Then
oNode.Visible = True
LOGGER.Debug($"Decide_Show_Empty_Workflows: oPk is Nothing/DBNull - Node visible set to True")
Exit Sub
End If
Dim oPkInt As Integer = CInt(oPk)
If Not _treeNodeCounts.ContainsKey(oPkInt) Then
oNode.Visible = True
LOGGER.Debug($"Decide_Show_Empty_Workflows: oPkInt [{oPkInt}] not found in _treeNodeCounts - Node visible set to True")
Exit Sub
End If
oNode.Visible = pShow OrElse (_treeNodeCounts(oPkInt) > 0)
End Sub)
Finally
TreeList_Cockpit.EndUpdate()
End Try
TreeList_Cockpit.Refresh()
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Async Sub TreeList_Cockpit_DoubleClick(sender As Object, e As EventArgs) Handles TreeList_Cockpit.DoubleClick
Try
Dim oFocusedNode As DevExpress.XtraTreeList.Nodes.TreeListNode = TreeList_Cockpit.FocusedNode
If oFocusedNode Is Nothing Then
LOGGER.Debug("TreeList_Cockpit_DoubleClick: No focused node")
Exit Sub
End If
Dim oTypeId As Object = oFocusedNode.GetValue("TYPE_ID")
If oTypeId Is Nothing OrElse IsDBNull(oTypeId) Then
LOGGER.Debug("TreeList_Cockpit_DoubleClick: TYPE_ID is Nothing/DBNull - skipping")
Exit Sub
End If
Dim oTypeIdInt As Integer = CInt(oTypeId)
' Nur bei Profil-Knoten (TYPE_ID = 1) Validator öffnen
If oTypeIdInt = 1 Then
Dim oFkProfileId As Object = oFocusedNode.GetValue("FK_PROFILE_ID")
If oFkProfileId Is Nothing OrElse IsDBNull(oFkProfileId) Then
LOGGER.Warn("TreeList_Cockpit_DoubleClick: TYPE_ID=1 but FK_PROFILE_ID is Nothing/DBNull")
Exit Sub
End If
Dim oProfileId As Integer = CInt(oFkProfileId)
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Opening validator for profile ID [{oProfileId}]")
Reset_Current()
' ===== PROFIL-DATEN INS GRID LADEN (FALLS NOCH NICHT GELADEN) =====
' Wenn das Grid aktuell leer ist oder ein anderes Profil zeigt, müssen wir erst laden
If DT_CURR_WF_ITEMS Is Nothing OrElse DT_CURR_WF_ITEMS.Rows.Count = 0 Then
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Grid does not show profile [{oProfileId}] - loading it first")
CURRENT_CLICKED_PROFILE_ID = oProfileId
' Profil-Titel setzen (ohne Count-Suffix)
Dim oProfileTitle As Object = oFocusedNode.GetValue("NAME")
Dim oCleanProfileTitle As String = oProfileTitle?.ToString()
Dim oSuffixMatch = System.Text.RegularExpressions.Regex.Match(oCleanProfileTitle, "^(.*)\s+\(\d+\)$")
If oSuffixMatch.Success Then
oCleanProfileTitle = oSuffixMatch.Groups(1).Value.Trim()
End If
CURRENT_CLICKED_PROFILE_TITLE = oCleanProfileTitle
GRID_LOAD_TYPE = $"PROFILE#{oProfileId}"
' Profil-Daten laden
Await Decide_Load(False, True)
' Warten bis DT_CURR_WF_ITEMS gefüllt ist
If DT_CURR_WF_ITEMS Is Nothing OrElse DT_CURR_WF_ITEMS.Rows.Count = 0 Then
LOGGER.Warn($"TreeList_Cockpit_DoubleClick: No workflow items found for profile [{oProfileId}]")
Dim omsg = String.Format(S.Aktuell_keine_Workflowdaten_vorhanden___0_, oCleanProfileTitle)
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
Exit Sub
End If
Else
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Grid already shows profile [{CURRENT_CLICKED_PROFILE_ID}] with [{DT_CURR_WF_ITEMS.Rows.Count}] items")
End If
' ===== DOCIDS AUS DT_CURR_WF_ITEMS SAMMELN =====
Dim oIds As New List(Of Integer)
If DT_CURR_WF_ITEMS IsNot Nothing AndAlso DT_CURR_WF_ITEMS.Columns.Contains("DocID") Then
For Each oRow As DataRow In DT_CURR_WF_ITEMS.Rows
Dim oDocId As Object = oRow("DocID")
If oDocId IsNot Nothing AndAlso IsNumeric(oDocId) Then
oIds.Add(CInt(oDocId))
End If
Next
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Collected [{oIds.Count}] DocIDs from DT_CURR_WF_ITEMS")
Else
LOGGER.Warn("TreeList_Cockpit_DoubleClick: DT_CURR_WF_ITEMS is Nothing or has no DocID column")
Exit Sub
End If
' ===== VALIDIERUNG: MINDESTENS 1 WORKFLOW =====
If oIds.Count = 0 Then
Dim omsg = String.Format(S.System_konnte_die_Profilworkflows_nicht_auswerten_, vbNewLine)
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
Exit Sub
End If
' ===== VALIDIERUNG: MAXIMUM 1000 WORKFLOWS =====
If oIds.Count > 1000 Then
Dim omsg = "You chose more than 1000 Workflows. Please select fewer items."
FormHelper.ShowInfoMessage(omsg, omsgTitleAttention)
Exit Sub
End If
' ===== DB-OPERATIONEN: TABELLE LEEREN UND NEU BEFÜLLEN =====
LOGGER.Debug("TreeList_Cockpit_DoubleClick: Cleaning up queued DocIds...")
Dim oDelete = $"DELETE FROM TBPM_VALIDATION_PROFILE_GROUP_USER WHERE UserID = {USER_ID}"
If DatabaseFallback.ExecuteNonQueryECM(oDelete) = True Then
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Adding [{oIds.Count}] queued DocIds...")
Dim oInsertBatch As New System.Text.StringBuilder()
oInsertBatch.AppendLine("INSERT INTO TBPM_VALIDATION_PROFILE_GROUP_USER ([PROFIL_ID],[DocID],[UserID],[ADDED_WHO]) VALUES")
For i As Integer = 0 To oIds.Count - 1
If i > 0 Then oInsertBatch.Append(",")
oInsertBatch.AppendLine($"({oProfileId},{oIds(i)},{USER_ID},'{USER_USERNAME}')")
Next
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: Batch-Insert SQL: {oInsertBatch.ToString()}")
DatabaseFallback.ExecuteNonQueryECM(oInsertBatch.ToString())
End If
' ===== VALIDATOR IM GRUPPEN-MODUS ÖFFNEN =====
CURRENT_ProfilGUID = oProfileId
CURRENT_CLICKED_PROFILE_ID = oProfileId
' Profil-Titel setzen (ohne Count-Suffix)
Dim oProfileTitle2 As Object = oFocusedNode.GetValue("NAME")
Dim oCleanProfileTitle2 As String = oProfileTitle2?.ToString()
Dim oSuffixMatch2 = System.Text.RegularExpressions.Regex.Match(oCleanProfileTitle2, "^(.*)\s+\(\d+\)$")
If oSuffixMatch2.Success Then
oCleanProfileTitle2 = oSuffixMatch2.Groups(1).Value.Trim()
End If
CURRENT_CLICKED_PROFILE_TITLE = oCleanProfileTitle2
' ===== WICHTIG: KEIN spezifisches Dokument laden (wie bei CMGROUP) =====
CURRENT_JUMP_DOC_GUID = 0
CURRENT_DOC_GUID = 0
' Cursor setzen
Me.Cursor = Cursors.WaitCursor
Try
' ===== DIREKTER AUFRUF OHNE GRID-KONTEXT =====
' Load_Profil_from_Grid öffnet den Validator im Gruppen-Modus
Load_Profil_from_Grid(oProfileId)
Finally
Me.Cursor = Cursors.Default
End Try
Else
LOGGER.Debug($"TreeList_Cockpit_DoubleClick: TYPE_ID=[{oTypeIdInt}] - no action for double-click")
End If
Catch ex As Exception
LOGGER.Error(ex)
Me.Cursor = Cursors.Default
End Try
End Sub
' ===== AM ENDE DER DATEI (vor "End Class") =====
Friend NotInheritable Class NativeMethods
<DllImport("user32.dll")>
Public Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Boolean
End Function
Public Const SW_RESTORE As Integer = 9
End Class
End Class