Bladeren bron

wpf: MainWindow module setup now moved to code instead of XAML

Kenric Nugteren 1 maand geleden
bovenliggende
commit
e7111eb3d0

+ 0 - 538
prs.desktop/MainWindow.xaml

@@ -213,544 +213,6 @@
                     </fluent:BackstageTabControl>
                 </fluent:Backstage>
             </fluent:Ribbon.Menu>
-            
-            <fluent:RibbonTabItem x:Name="ProjectsTab" Header="Projects" IsSelected="False" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="ProjectsActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="ProjectsDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="ProjectMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="ProjectTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="ProjectAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="ProjectsMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="ProjectDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="ProjectTaskSeparator" />
-                    
-                    <fluent:Button x:Name="QuotesButton" Header="Quotes"
-                                   LargeIcon="pack://application:,,,/Resources/quotation.png"
-                                    />
-                    
-                    <fluent:Button x:Name="ProjectsButton" Header="Projects"
-                                   LargeIcon="pack://application:,,,/Resources/project.png"
-                                    />
-                    
-                    <fluent:Button x:Name="ProjectPlannerButton" Header="Project Planner"
-                                   LargeIcon="pack://application:,,,/Resources/calendar.png"
-                                    />
-                    
-                </fluent:RibbonGroupBox>
-                
-                <fluent:RibbonGroupBox x:Name="ProjectsSetup" Width="Auto"  Header="Setup" Visibility="Collapsed">
-                    
-                    <fluent:Button x:Name="KitsMasterList" Header="Product Kits"
-                                   LargeIcon="pack://application:,,,/Resources/kit.png" />
-                    
-                    <fluent:Button x:Name="CostSheetsMasterList" Header="Cost Sheets"
-                                   LargeIcon="pack://application:,,,/Resources/costsheet.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="ProjectReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="ManufacturingTab" Header="Manufacturing" IsSelected="False"
-                                  Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="ManufacturingActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-
-                    <syncfusion:RibbonSeparator x:Name="ManufacturingTaskSeparator" />
-                    
-                    <fluent:Button x:Name="ManufacturingDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="ManufacturingMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="ManufacturingTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="ManufacturingAttendanceButton"
-                                   Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="ManufacturingMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="ManufacturingDailyReportButton"
-                                   Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="ManufacturingDesignSeparator" />
-                    
-                    <fluent:Button x:Name="DesignManagementButton" Header="Design Management"
-                                   LargeIcon="pack://application:,,,/Resources/design.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="ManufacturingActionSeparator" />
-                    
-                    <fluent:Button x:Name="FactoryStatusButton" Header="Manufacturing Status"
-                                   LargeIcon="pack://application:,,,/Resources/factory.png" />
-                    
-                    <fluent:Button x:Name="FactoryAllocationButton"
-                                   Header="Factory Allocation"
-                                   LargeIcon="pack://application:,,,/Resources/assignments.png" />
-                    
-                    <fluent:Button x:Name="FactoryFloorButton" Header="Factory Floor"
-                                   LargeIcon="pack://application:,,,/Resources/wrench.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="ManufacturingAnalysisSeparator" />
-                    
-                    <fluent:Button x:Name="FactoryProductivityButton" Header="Factory KPIs"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="TemplateAnalysisButton" Header="Template Analysis"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="FactoryAnalysisButton" Header="Factory Analysis"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="ManufacturingReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="ProductTab" Header="Products" IsSelected="False"
-                                  Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="ProductActions" Width="Auto" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="ProductsDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="ProductsMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="ProductsTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="ProductsAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="ProductsMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="ProductsDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="ProductsTaskSeparator" />
-                    
-                    <fluent:Button x:Name="ProductsMasterList" Header="Product List"
-                                   LargeIcon="pack://application:,,,/Resources/product.png" />
-                    
-                    <fluent:Button x:Name="StockLocationList" Header="Stock Locations"
-                                   LargeIcon="pack://application:,,,/Resources/parcel.png" />
-                    
-                    <fluent:Button x:Name="StockMovementList" Header="Stock Movements"
-                                   LargeIcon="pack://application:,,,/Resources/forklift.png" />
-                    
-                    <fluent:Button x:Name="StockForecastButton" Header="Stock Forecast"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="ReservationManagementButton" Header="Reservation Management"
-                                   LargeIcon="pack://application:,,,/Resources/requisition.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="ProductReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="LogisticsTab" Header="Logistics" IsSelected="False" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="LogisticsActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click"  />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="LogisticsDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="LogisticsMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="LogisticsTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="LogisticsAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="LogisticsMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="LogisticsDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="LogisticsTaskSeparator1" />
-                    
-                    <fluent:Button x:Name="ReadyToGoItemsButton" Header="Ready To Go"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/truck.svg}" />
-                    
-                    <fluent:Button x:Name="DispatchButton" Header="Rack List"
-                                   LargeIcon="pack://application:,,,/Resources/barcode.png" />
-                    
-                    <fluent:Button x:Name="RequisitionsButton" Header="Picking Lists"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/box.svg}" />
-                    
-                    <fluent:Button x:Name="DeliveriesButton" Header="Deliveries"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/truck.svg}" />
-                    
-                    <fluent:Button x:Name="DeliveredItemsButton" Header="Delivered On Site"
-                                   LargeIcon="pack://application:,,,/Resources/lifter.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="LogisticsTaskSeparator2" />
-                    
-                    <fluent:Button x:Name="ConsignmentButton" Header="Incoming Consignments"
-                                   LargeIcon="pack://application:,,,/Resources/consignment.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="LogisticsReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="HumanResourcesTab" Header="Human Resources" IsSelected="False"
-                                  Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="HumanResourcesActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click"  />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="HumanResourcesDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="HumanResourcesMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="HumanResourcesTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="HumanResourcesAttendanceButton"
-                                   Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="HumanResourcesMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="HumanResourcesDailyReportButton"
-                                   Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="HumanResourcesTaskSeparator" />
-                    
-                    <fluent:Button x:Name="CalendarButton" Header="Calendar"
-                                   LargeIcon="pack://application:,,,/Resources/assignments.png" />
-                    
-                    <fluent:Button x:Name="EmployeePlannerButton" Header="Employee Planner"
-                                   LargeIcon="pack://application:,,,/Resources/calendar.png" />
-                    
-                    <fluent:Button x:Name="TimesheetsButton" Header="Staff TimeSheets"
-                                   LargeIcon="pack://application:,,,/Resources/clock.png" />
-                    
-                    <fluent:Button x:Name="LeaveRequestsButton" Header="Leave Requests"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/beach.svg}" />
-                    
-                    <fluent:Button x:Name="MeetingsButton" Header="Meetings"
-                                   LargeIcon="pack://application:,,,/Resources/employees.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="HumanResourcesSetupSeparator1" />
-                    
-                    <fluent:Button x:Name="UsersButton" Header="User Accounts"
-                                   LargeIcon="pack://application:,,,/Resources/user.png" />
-                    
-                    <fluent:Button x:Name="EmployeesButton" Header="Employee List"
-                                   LargeIcon="pack://application:,,,/Resources/employee.png" />
-                    
-                    <fluent:Button x:Name="OrgChartButton" Header="Org Chart"
-                                   LargeIcon="pack://application:,,,/Resources/orgchart.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="HumanResourcesReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-                
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="AccountsReceivableTab" Header="Accounts Receivable" IsSelected="False" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="AccountsReceivableActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="AccountsReceivableDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="AccountsReceivableMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="AccountsReceivableTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="AccountsReceivableAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="AccountsReceivableMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="AccountsReceivableDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="AccountsReceivableTaskSeparator1" />
-                    
-                    <fluent:Button x:Name="CustomerList" Header="Customers"
-                                   LargeIcon="pack://application:,,,/Resources/customer.png" />
-                    
-                    <fluent:Button x:Name="InvoiceList" Header="Invoices"
-                                   LargeIcon="pack://application:,,,/Resources/invoice.png" />
-                    
-                    <fluent:Button x:Name="ReceiptList" Header="Receipts"
-                                   LargeIcon="pack://application:,,,/Resources/receipt.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="AccountsReceivableReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-                
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="AccountsPayableTab" Header="Accounts Payable" IsSelected="False" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="AccountsPayableActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="AccountsPayableDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="AccountsPayableMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="AccountsPayableTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="AccountsPayableAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="AccountsPayableMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="AccountsPayableDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="AccountsPayableTaskSeparator1" />
-                    
-                    <fluent:Button x:Name="SupplierList" Header="Suppliers"
-                                   LargeIcon="pack://application:,,,/Resources/supplier.png" />
-                    
-                    <fluent:Button x:Name="AccountsDataButton" Header="Data Entry"
-                                   LargeIcon="pack://application:,,,/Resources/pencil.png" />
-                    
-                    <fluent:Button x:Name="PurchasesList" Header="Purchase Orders"
-                                   LargeIcon="pack://application:,,,/Resources/purchase.png" />
-                    
-                    <fluent:Button x:Name="BillsList" Header="Bills"
-                                   LargeIcon="pack://application:,,,/Resources/bill.png" />
-                    
-                    <fluent:Button x:Name="PaymentsList" Header="Payments"
-                                   LargeIcon="pack://application:,,,/Resources/payment.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="AccountsPayableReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-                
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="EquipmentTab" Header="Equipment" IsSelected="True" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="EquipmentActions" Width="Auto" Header="Actions">
-
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="EquipmentDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="EquipmentMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="EquipmentTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="EquipmentAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="EquipmentMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="EquipmentDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="EquipmentTaskSeparator" />
-                    
-                    <fluent:Button x:Name="EquipmentButton" Header="Equipment List"
-                                   LargeIcon="pack://application:,,,/Resources/specifications.png"/>
-                    
-                    <fluent:Button x:Name="EquipmentMaintenanceButton" Header="Planned Maintenance"
-                                   LargeIcon="pack://application:,,,/Resources/service.png" />
-                    
-                    <fluent:Button x:Name="EquipmentPlannerButton" Header="Equipment Planner"
-                                   LargeIcon="pack://application:,,,/Resources/calendar.png" />
-                    
-                    <fluent:Button x:Name="TrackersMasterList" Header="GPS Trackers"
-                                   LargeIcon="pack://application:,,,/Resources/milestone.png" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="EquipmentReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="DigitalFormsTab" Header="Digital Forms" IsSelected="False" Visibility="Collapsed">
-                <fluent:RibbonGroupBox x:Name="DigitalFormsActions" Width="Auto" Header="Actions">
-
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="DigitalFormsDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="DigitalFormsMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="DigitalFormsTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="DigitalFormsAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="DigitalFormsMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="DigitalFormsDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="DigitalFormsTaskSeparator" />
-                    
-                    <fluent:Button x:Name="DigitalFormsFormsLibraryButton" Header="Forms Library"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/formslibrary.svg}" />
-                    
-                    <fluent:Button x:Name="DigitalFormsCompletedFormsButton" Header="Forms Dashboard"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/formsinstance.svg}" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="DigitalFormReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-            </fluent:RibbonTabItem>
-
-            <fluent:RibbonTabItem x:Name="DashboardsTab" Header="Dashboards" IsSelected="False" Visibility="Collapsed">
-
-                <fluent:RibbonGroupBox x:Name="DashboardsActions" Header="Actions">
-                    
-                    <fluent:Button Header="Refresh"
-                                   LargeIcon="pack://application:,,,/Resources/refresh.png"
-                                   Click="RefreshMenu_Click" />
-                    
-                    <syncfusion:RibbonSeparator />
-                    
-                    <fluent:Button x:Name="DashboardsDashboardButton" Header="Dashboards"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="DashboardMessagesButton"
-                                   Header="Notification Centre"
-                                   LargeIcon="pack://application:,,,/Resources/email.png" />
-                    
-                    <fluent:Button x:Name="DashboardsTaskButton" Header="Task List"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kanban.svg}" />
-                    
-                    <fluent:Button x:Name="DashboardsAttendanceButton" Header="In/Out Board"
-                                   LargeIcon="pack://application:,,,/Resources/attendance.png" />
-                    
-                    <fluent:Button x:Name="DashboardsMapButton" Header="Live Maps"
-                                   LargeIcon="pack://application:,,,/Resources/map.png" />
-                    
-                    <fluent:Button x:Name="DashboardsDailyReportButton" Header="Daily Report"
-                                   LargeIcon="pack://application:,,,/Resources/report.png" />
-                    
-                    <syncfusion:RibbonSeparator x:Name="DashboardsTaskSeparator" />
-                    
-                    <!--This is where the static dashboards need to go-->
-                    <fluent:Button x:Name="DatabaseActivityButton" Header="Database Activity"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="UserActivityButton" Header="User Activity"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                    <fluent:Button x:Name="QuickStatusButton" Header="Quick Status"
-                                   LargeIcon="{svgc:SvgImage Source=/Resources/kpi.svg}" />
-                    
-                </fluent:RibbonGroupBox>
-
-                <fluent:RibbonGroupBox x:Name="DashboardsReports" Width="Auto"  Header="Print" Visibility="Collapsed"/>
-
-            </fluent:RibbonTabItem>
-
         </fluent:Ribbon>
 
         <Grid Grid.Row="0" Grid.Column="1">

+ 437 - 494
prs.desktop/MainWindow.xaml.cs

@@ -63,6 +63,10 @@ using InABox.Formatters;
 using PRSDesktop.Forms.Issues;
 using Brushes = System.Windows.Media.Brushes;
 using System.Windows.Media.Imaging;
+using Button = System.Windows.Controls.Button;
+using Visibility = System.Windows.Visibility;
+using SharpVectors.Converters;
+using SVGImage.SVG;
 
 namespace PRSDesktop;
 
@@ -671,26 +675,44 @@ public partial class MainWindow : IPanelHostControl
 
     #region Configuration
 
+    private bool CanViewMaps => Security.CanView<Equipment>()
+        || Security.CanView<Job>()
+        || Security.CanView<TimeSheet>()
+        || Security.CanView<GPSTracker>();
+
     private void ConfigureMainScreen(IProgress<string>? progress)
     {
-        var bMaps = Security.CanView<Equipment>()
-                    || Security.CanView<Job>()
-                    || Security.CanView<TimeSheet>()
-                    || Security.CanView<GPSTracker>();
+        var bMaps = CanViewMaps;
+
+        ProgressSection ConfigureTab(string progress, Func<Fluent.RibbonTabItem?> createTab)
+        {
+            return new ProgressSection(progress, () =>
+            {
+                var tab = createTab();
+                if (tab is not null)
+                {
+                    _ribbon.Tabs.Add(tab);
+                }
+            });
+        }
 
         var sections = new[]
         {
+            new ProgressSection("Initial Setup", () =>
+            {
+                _ribbon.Tabs.Clear();
+            }),
             new ProgressSection("Configuring Main Screen", SetupMainScreen),
-            new ProgressSection("Configuring Projects", () => SetupProjectsTab(bMaps)),
-            new ProgressSection("Configuring Manufacturing", () => SetupManufacturingTab(bMaps)),
-            new ProgressSection("Configuring Logistics", () => SetupLogisticsTab(bMaps)),
-            new ProgressSection("Configuring Products", () => SetupProductsTab(bMaps)),
-            new ProgressSection("Configuring Human Resources", () => SetupHumanResourcesTab(bMaps)),
-            new ProgressSection("Configuring Accounts Receivable", () => SetupAccountsReceivableTab(bMaps)),
-            new ProgressSection("Configuring Accounts Payable", () => SetupAccountsPayableTab(bMaps)),
-            new ProgressSection("Configuring Equipment", () => SetupEquipmentTab(bMaps)),
-            new ProgressSection("Configuring DigitalForms", () => SetupDigitalFormsTab(bMaps)),
-            new ProgressSection("Configuring Dashboards", () => SetupDashboardsTab(bMaps)),
+            ConfigureTab("Configuring Projects", SetupProjectsTab),
+            ConfigureTab("Configuring Manufacturing", SetupManufacturingTab),
+            ConfigureTab("Configuring Logistics", SetupLogisticsTab),
+            ConfigureTab("Configuring Products", SetupProductsTab),
+            ConfigureTab("Configuring Human Resources", SetupHumanResourcesTab),
+            ConfigureTab("Configuring Accounts Receivable", SetupAccountsReceivableTab),
+            ConfigureTab("Configuring Accounts Payable", SetupAccountsPayableTab),
+            ConfigureTab("Configuring Equipment", SetupEquipmentTab),
+            ConfigureTab("Configuring DigitalForms", SetupDigitalFormsTab),
+            ConfigureTab("Configuring Dashboards", SetupDashboardsTab),
             new ProgressSection("Configuring System Modules", SetupSystemModules)
         };
 
@@ -782,475 +804,464 @@ public partial class MainWindow : IPanelHostControl
         _ribbon.InvalidateArrange();
     }
 
-    private void SetupDashboardsTab(bool bMaps)
-    {
-        if (!Security.IsAllowed<ViewDesktopDashboardsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(DashboardsDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(DashboardMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(DashboardsTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(DashboardsAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(DashboardsMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(DashboardsDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<DatabaseActivityDashboard>(DatabaseActivityButton,
-            ClientFactory.IsSupported<UserTracking>() 
-            && Security.IsAllowed<CanViewDatabaseActivity>()
-            && Security.IsAllowed<ViewDesktopDatabaseActivityDashboard>());
-
-        SetModuleVisibility<UserActivity>(UserActivityButton, ClientFactory.IsSupported<ModuleTracking>() 
-                                                        && Security.IsAllowed<CanViewUserActivity>()
-                                                        && Security.IsAllowed<ViewDesktopUserActivityDashboard>());
-
-        SetModuleVisibility<WidgetDashboard>(QuickStatusButton, Security.IsAllowed<CanViewQuickStatus>() && Security.IsAllowed<ViewDesktopQuickStatusDashboard>());
-
-        SetVisibleIfEither(DashboardsTaskSeparator,
-            new FrameworkElement[]
-            {
-                            DashboardsDashboardButton, DashboardMessagesButton, DashboardsTaskButton, DashboardsAttendanceButton,
-                            DashboardsMapButton,
-                            DashboardsDailyReportButton
-            },
-            new FrameworkElement[]
-            {
-                            DatabaseActivityButton, UserActivityButton, QuickStatusButton
-            });
-        SetVisibleIfAny(DashboardsActions, DashboardsDashboardButton, DashboardMessagesButton, DashboardsTaskButton,
-            DashboardsAttendanceButton, DashboardsDailyReportButton,
-            DatabaseActivityButton, UserActivityButton, QuickStatusButton);
-
-        //DashboardsActions.IsLauncherButtonVisible = Security.IsAllowed<CanCustomiseModules>();
-        //DashboardsReports.IsLauncherButtonVisible = Security.IsAllowed<CanDesignReports>();
-
-        SetVisibleIfAny(DashboardsTab, DatabaseActivityButton, UserActivityButton, QuickStatusButton);
-    }
+    private Fluent.RibbonTabItem? SetupDashboardsTab() =>
+        CreateTab<ViewDesktopDashboardsTab>("Dashboards", x => x
+            .NewGroup(x => x
+                .Add<DatabaseActivityDashboard>("Database Activity", SvgImages.kpi,
+                    ClientFactory.IsSupported<UserTracking>()
+                    && Security.IsAllowed<CanViewDatabaseActivity>()
+                    && Security.IsAllowed<ViewDesktopDatabaseActivityDashboard>())
+                .Add<UserActivity>("User Activity", SvgImages.kpi,
+                    ClientFactory.IsSupported<ModuleTracking>()
+                    && Security.IsAllowed<CanViewUserActivity>()
+                    && Security.IsAllowed<ViewDesktopUserActivityDashboard>())
+                .Add<WidgetDashboard>("Quick Status", SvgImages.kpi,
+                    Security.IsAllowed<CanViewQuickStatus>() && Security.IsAllowed<ViewDesktopQuickStatusDashboard>())));
     
-    private void SetupDigitalFormsTab(bool bMaps)
+    private Fluent.RibbonTabItem? SetupDigitalFormsTab() =>
+        CreateTab<ViewDesktopDigitalFormsTab>("Digital Forms", x => x
+            .NewGroup(x => x
+                .Add<DigitalFormsLibrary>("Forms Library", SvgImages.formslibrary,
+                    ClientFactory.IsSupported<DigitalForm>()
+                    && Security.CanView<DigitalForm>()
+                    && Security.IsAllowed<CanAdministerDigitalFormsLibrary>())
+                .Add<CompletedFormsPanel>("Forms Dashboard", SvgImages.formsinstance,
+                    Security.IsAllowed<CanViewDigitalFormsDashbaord>()
+                    && Security.IsAllowed<ViewDesktopDigitalFormsDashboard>())));
+    
+    private Fluent.RibbonTabItem? SetupEquipmentTab() =>
+        CreateTab<ViewDesktopEquipmentTab>("Equipment", x => x
+            .NewGroup(x => x
+                .Add<EquipmentPanel>("Equipment List", PRSDesktop.Resources.specifications,
+                    ClientFactory.IsSupported<Equipment>()
+                    && Security.CanView<Equipment>()
+                    && Security.IsAllowed<ViewDesktopEquipmentListScreen>())
+                .Add<EquipmentMaintenancePanel>("Planned Maintenance", PRSDesktop.Resources.service,
+                    ClientFactory.IsSupported<Equipment>()
+                    && Security.CanView<Equipment>()
+                    && Security.IsAllowed<ViewDesktopEquipmentMaintenanceScreen>())
+                .Add<EquipmentPlannerPanel>("Equipment Planner", PRSDesktop.Resources.calendar,
+                    ClientFactory.IsSupported<Equipment>()
+                    && Security.CanView<Equipment>()
+                    && ClientFactory.IsSupported<Assignment>()
+                    && Security.CanView<Assignment>()
+                    && Security.IsAllowed<ViewDesktopEquipmentPlannerScreen>())
+                .Add<GPSTrackers>("GPS Trackers", PRSDesktop.Resources.milestone,
+                    Security.CanView<GPSTracker>() && Security.IsAllowed<ViewDesktopGPSTrackersScreen>())));
+
+    private Fluent.RibbonTabItem? SetupAccountsReceivableTab() =>
+        CreateTab<ViewDesktopAccountsTab>("Accounts Receivable", x => x
+            .NewGroup(x => x
+                .Add<CustomerPanel>("Customers", PRSDesktop.Resources.customer,
+                    ClientFactory.IsSupported<Customer>()
+                    && Security.CanView<Customer>()
+                    && Security.IsAllowed<ViewDesktopCustomersScreen>())
+                .Add<InvoicePanel>("Invoices", PRSDesktop.Resources.invoice,
+                    ClientFactory.IsSupported<Invoice>()
+                    && Security.CanView<Invoice>()
+                    && Security.IsAllowed<ViewDesktopInvoicesScreen>())
+                .Add<CustomerReceipts>("Receipts", PRSDesktop.Resources.receipt,
+                    ClientFactory.IsSupported<Receipt>()
+                    && Security.CanView<Receipt>()
+                    && Security.IsAllowed<ViewDesktopReceiptsScreen>())));
+
+    private Fluent.RibbonTabItem? SetupAccountsPayableTab() =>
+        CreateTab<ViewDesktopAccountsTab>("Accounts Payable", x => x
+            .NewGroup(x => x
+                .Add<SupplierPanel>("Suppliers", PRSDesktop.Resources.supplier,
+                    ClientFactory.IsSupported<Supplier>()
+                    && Security.CanView<Supplier>()
+                    && Security.IsAllowed<ViewDesktopSuppliersScreen>())
+                .Add<DataEntryPanel>("Data Entry", PRSDesktop.Resources.pencil,
+                    Security.IsAllowed<CanViewDataEntryPanel>())
+                .Add<SupplierPurchaseOrderPanel>("Purchase Orders", PRSDesktop.Resources.purchase,
+                    ClientFactory.IsSupported<PurchaseOrder>()
+                    && Security.CanView<PurchaseOrder>()
+                    && Security.IsAllowed<ViewDesktopPurchaseOrdersScreen>())
+                .Add<SupplierBillPanel>("Bills", PRSDesktop.Resources.bill,
+                    ClientFactory.IsSupported<Bill>()
+                    && Security.CanView<Bill>()
+                    && Security.IsAllowed<ViewDesktopBillsScreen>())
+                .Add<SupplierPayments>("Payments", PRSDesktop.Resources.payment,
+                    ClientFactory.IsSupported<Payment>()
+                    && Security.CanView<Payment>()
+                    && Security.IsAllowed<ViewDesktopPaymentsScreen>())));
+
+    private Fluent.RibbonTabItem? SetupHumanResourcesTab() =>
+        CreateTab<ViewDesktopHumanResourcesTab>("Human Resources", x => x
+            .NewGroup(x => x
+                .Add<CalendarPanel>("Calendar", PRSDesktop.Resources.assignments,
+                    Security.CanView<Assignment>() && Security.IsAllowed<ViewDesktopCalendarScreen>())
+                .Add<EmployeeResourcePlannerPanel>("Employee Planner", PRSDesktop.Resources.calendar,
+                    Security.CanView<Assignment>() && Security.IsAllowed<ViewDesktopEmployeePlannerScreen>())
+                .Add<TimesheetPanel>("Staff Timesheets", PRSDesktop.Resources.clock,
+                    Security.CanView<TimeSheet>() && Security.IsAllowed<ViewDesktopStaffTimeSheetsScreen>())
+                .Add<LeaveRequestPanel>("Leave Requests", SvgImages.beach,
+                    Security.CanView<LeaveRequest>() && Security.IsAllowed<ViewDesktopLeaveRequestsScreen>())
+                .Add<MeetingPanel>("Meetings", PRSDesktop.Resources.employees,
+                    Security.IsAllowed<ViewDesktopMeetingsScreen>()))
+            .NewGroup(x => x
+                .Add<UserPanel>("User Accounts", PRSDesktop.Resources.user,
+                    Security.CanView<User>() && Security.IsAllowed<ViewDesktopUserAccountsScreen>())
+                .Add<EmployeePanel>("Employee List", PRSDesktop.Resources.employee,
+                    Security.CanView<Employee>() && Security.IsAllowed<ViewDesktopEmployeeListScreen>())
+                .Add<OrgChartPanel>("Org Chart", PRSDesktop.Resources.orgchart,
+                    ClientFactory.IsSupported<Employee>() && Security.IsAllowed<ViewDesktopOrgChartScreen>())));
+
+    private Fluent.RibbonTabItem? SetupProductsTab() =>
+        CreateTab<ViewDesktopProductManagementTab>("Products", x => x
+            .NewGroup(x => x
+                .Add<ProductsPanel>("Product List", PRSDesktop.Resources.product,
+                    Security.CanView<Product>() && Security.IsAllowed<ViewDesktopProductListScreen>())
+                .Add<StockLocationPanel>("Stock Locations", PRSDesktop.Resources.parcel,
+                    Security.CanView<StockLocation>() && Security.IsAllowed<ViewDesktopStockLocationsScreen>())
+                .Add<StockMovementPanel>("Stock Movements", PRSDesktop.Resources.forklift,
+                    Security.CanView<StockMovement>() && Security.IsAllowed<ViewDesktopStockMovementsScreen>())
+                .Add<StockForecastPanel>("Stock Forecast", SvgImages.kpi,
+                    Security.CanView<Product>()
+                    && Security.CanView<JobMaterial>()
+                    && Security.IsAllowed<ViewDesktopStockForecastScreen>())
+                .Add<ReservationManagementPanel>("Reservation Management", PRSDesktop.Resources.requisition,
+                    Security.IsAllowed<ViewDesktopReservationManagementScreen>())));
+
+    private Fluent.RibbonTabItem? SetupLogisticsTab() =>
+        CreateTab<ViewDesktopLogisticsTab>("Logistics", x => x
+            .NewGroup(x => x
+                .Add<ReadyToGoPanel>("Ready To Go", SvgImages.truck,
+                    ClientFactory.IsSupported<DeliveryItem>()
+                    && Security.IsAllowed<CanViewLogisticsReadyToGo>()
+                    && Security.IsAllowed<ViewDesktopReadyToGoScreen>())
+                .Add<DispatchPanel>("Rack List", PRSDesktop.Resources.barcode,
+                    Security.CanView<Shipment>()
+                    && Security.CanView<DeliveryItem>()
+                    && Security.IsAllowed<ViewDesktopRackListScreen>())
+                .Add<RequisitionPanel>("Picking Lists", SvgImages.box,
+                    Security.CanView<Requisition>() && Security.IsAllowed<ViewDesktopSiteRequisitionsScreen>())
+                .Add<DeliveryPanel>("Deliveries", SvgImages.truck,
+                    Security.IsAllowed<CanViewDeliveriesModule>() && Security.IsAllowed<ViewDesktopDeliveriesScren>())
+                .Add<DeliveredOnSitePanel>("Delivered On Site", PRSDesktop.Resources.lifter,
+                    ClientFactory.IsSupported<DeliveryItem>()
+                    && Security.IsAllowed<CanViewDeliveredOnSite>()
+                    && Security.IsAllowed<ViewDesktopDeliveredOnSiteScreen>()))
+            .NewGroup(x => x
+                .Add<ConsignmentsPanel>("Incoming Consignments", PRSDesktop.Resources.consignment,
+                    Security.CanView<Consignment>() && Security.IsAllowed<ViewDesktopIncomingConsignmentsScreen>())));
+
+    private Fluent.RibbonTabItem? SetupManufacturingTab() =>
+        CreateTab<ViewDesktopManufacturingTab>("Manufacturing", x => x
+            .NewGroup(x => x
+                .Add<StagingPanel>("Design Management", PRSDesktop.Resources.design,
+                    Security.CanView<Job>() && Security.IsAllowed<ViewDesktopDesignManagementScreen>()))
+            .NewGroup(x => x
+                .Add<ManufacturingPanel>("Manufacturing Status", PRSDesktop.Resources.factory,
+                    ClientFactory.IsSupported<ManufacturingFactory, ManufacturingPacket>()
+                    && Security.IsAllowed<CanViewFactoryStatus>()
+                    && Security.IsAllowed<ViewDesktopManufacturingStatusScreen>())
+                .Add<ManufacturingAllocationPanel>("Factory Allocation", PRSDesktop.Resources.assignments,
+                    ClientFactory.IsSupported<ManufacturingFactory, ManufacturingPacket, ManufacturingPacketStage>()
+                    && Security.IsAllowed<CanViewFactoryAllocation>()
+                    && Security.IsAllowed<ViewDesktopFactoryAllocationScreen>())
+                .Add<FactoryPanel>("Factory Floor", PRSDesktop.Resources.wrench,
+                    ClientFactory.IsSupported<ManufacturingPacket>()
+                    && Security.IsAllowed<CanViewFactoryFloor>()
+                    && Security.IsAllowed<ViewDesktopFactoryFloorScreen>()))
+            .NewGroup(x => x
+                .Add<FactoryProductivityDashboard>("Factory KPIs", SvgImages.kpi,
+                    ClientFactory.IsSupported<ManufacturingHistory>() 
+                    && Security.IsAllowed<CanViewFactoryKPIs>()
+                    && Security.IsAllowed<ViewDesktopFactoryKPIsDashboard>())
+                .Add<ManufacturingTemplateAnalysis>("Template Analysis", SvgImages.kpi,
+                    ClientFactory.IsSupported<ManufacturingTemplate, ManufacturingHistory>() 
+                    && Security.IsAllowed<CanViewTemplateAnalysis>()
+                    && Security.IsAllowed<ViewDesktopTemplateAnalysisDashboard>())
+                .Add<FactoryFloorAnalysis>("Factory Analysis", SvgImages.kpi,
+                    ClientFactory.IsSupported<ManufacturingTemplate, ManufacturingHistory>() 
+                    && Security.IsAllowed<CanViewFactoryAnalysis>()
+                    && Security.IsAllowed<ViewDesktopFactoryAnalysisDashboard>())));
+
+    private Fluent.RibbonTabItem? SetupProjectsTab() =>
+        CreateTab<ViewDesktopProjectsTab>("Projects", x => x
+            .NewGroup(x => x
+                .Add<QuotePanel>("Quotes", PRSDesktop.Resources.quotation,
+                    Security.CanView<Quote>() && Security.IsAllowed<ViewDesktopQuotesScreen>())
+                .Add<ProjectsPanel>("Projects", PRSDesktop.Resources.project,
+                    Security.CanView<Job>() && Security.IsAllowed<ViewDesktopProjectsScreen>())
+                .Add<JobResourcePlannerPanel>("Project Planner", PRSDesktop.Resources.calendar,
+                    Security.CanView<Job>() && Security.IsAllowed<ViewDesktopProjectPlannerScreen>()))
+            .NewGroup(x => x
+                .Add<KitPanel>("Product Kits", PRSDesktop.Resources.kit,
+                    Security.CanView<Kit>() && Security.IsAllowed<ViewDesktopProductKitsScreen>())
+                .Add<CostSheetPanel>("Cost Sheets", PRSDesktop.Resources.costsheet,
+                    Security.CanView<CostSheet>() && Security.IsAllowed<ViewDesktopCostSheetsScreen>()),
+                groupName: "Setup"));
+    
+    private void SetupDock<TSecurityDescriptor>(LayoutAnchorable layout, IDockPanel dock)
+        where TSecurityDescriptor : ISecurityDescriptor, new()
     {
-        if (!Security.IsAllowed<ViewDesktopDigitalFormsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(DigitalFormsDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(DigitalFormsMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(DigitalFormsTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(DigitalFormsAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(DigitalFormsMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(DigitalFormsDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<DigitalFormsLibrary>(DigitalFormsFormsLibraryButton, ClientFactory.IsSupported<DigitalForm>()
-                                                                           && Security.CanView<DigitalForm>()
-                                                                           && Security.IsAllowed<CanAdministerDigitalFormsLibrary>());
-
-        SetModuleVisibility<CompletedFormsPanel>(DigitalFormsCompletedFormsButton, Security.IsAllowed<CanViewDigitalFormsDashbaord>() && Security.IsAllowed<ViewDesktopDigitalFormsDashboard>());
-
-        SetVisibleIfEither(DigitalFormsTaskSeparator,
-            new FrameworkElement[]
+        if (Security.IsAllowed<TSecurityDescriptor>())
+        {
+            if (!DockGroup.Children.Any(x => x == layout))
             {
-                DigitalFormsDashboardButton, DigitalFormsMessagesButton, DigitalFormsTaskButton, DigitalFormsAttendanceButton, DigitalFormsMapButton,
-                DigitalFormsDailyReportButton
-            }, new FrameworkElement[] { DigitalFormsFormsLibraryButton, DigitalFormsCompletedFormsButton });
-
-        SetVisibleIfAny(DigitalFormsActions, DigitalFormsDashboardButton, DigitalFormsMessagesButton, DigitalFormsTaskButton,
-            DigitalFormsAttendanceButton, DigitalFormsDailyReportButton, DigitalFormsFormsLibraryButton, DigitalFormsCompletedFormsButton);
-
-        SetTabVisibleIfAny(DigitalFormsTab, DigitalFormsFormsLibraryButton, DigitalFormsCompletedFormsButton);
-
+                DockGroup.Children.Add(layout);
+            }
+            if (layout.IsVisible && (ClientFactory.UserGuid != Guid.Empty))
+                dock.Setup();
+        }
+        else
+        {
+            DockGroup.RemoveChild(layout);
+        }
     }
-    
-    private void SetupEquipmentTab(bool bMaps)
-    {
-        if (!Security.IsAllowed<ViewDesktopEquipmentTab>())
-            return;
 
-        SetModuleVisibility<UtilityDashboard>(EquipmentDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
+    private class HeaderTab(string header, MainWindow window)
+    {
+        public string Header { get; set; } = header;
 
-        SetModuleVisibility<NotificationPanel>(EquipmentMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(EquipmentTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(EquipmentAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(EquipmentMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(EquipmentDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
+        public List<Tuple<string, List<HeaderGroup>>> Groups { get; set; } = new();
 
-        SetModuleVisibility<EquipmentPanel>(EquipmentButton, ClientFactory.IsSupported<Equipment>() 
-                                                       && Security.CanView<Equipment>()
-                                                       && Security.IsAllowed<ViewDesktopEquipmentListScreen>());
-        
-        SetModuleVisibility<EquipmentMaintenancePanel>(EquipmentMaintenanceButton,
-            ClientFactory.IsSupported<Equipment>() 
-            && Security.CanView<Equipment>()
-            && Security.IsAllowed<ViewDesktopEquipmentMaintenanceScreen>() );
+        public HeaderTab NewGroup(Action<HeaderGroup> modify, string? groupName = null)
+        {
+            var currentGroup = (groupName is not null ? Groups.FirstOrDefault(x => x.Item1 == groupName) : Groups.LastOrDefault())?.Item2;
+            if(currentGroup is null)
+            {
+                currentGroup = new List<HeaderGroup>();
+                Groups.Add(new(groupName ?? "", currentGroup));
+            }
 
-        SetModuleVisibility<EquipmentPlannerPanel>(EquipmentPlannerButton, 
-            ClientFactory.IsSupported<Equipment>() 
-            && Security.CanView<Equipment>()
-            && ClientFactory.IsSupported<Assignment>() 
-            && Security.CanView<Assignment>()
-            && Security.IsAllowed<ViewDesktopEquipmentPlannerScreen>());
+            var group = new HeaderGroup(window);
+            currentGroup.Add(group);
+            modify(group);
+            return this;
+        }
 
+        public Fluent.RibbonTabItem? Create()
+        {
+            var item = new Fluent.RibbonTabItem
+            {
+                Header = Header
+            };
 
-        SetVisibleIfEither(EquipmentTaskSeparator,
-            new FrameworkElement[]
+            var hasNonDefault = false;
+            foreach(var (name, groups) in Groups)
             {
-                            EquipmentDashboardButton, EquipmentMessagesButton, EquipmentTaskButton, EquipmentAttendanceButton, EquipmentMapButton,
-                            EquipmentDailyReportButton
-            }, new FrameworkElement[] { EquipmentButton, EquipmentPlannerButton });
-        
-        SetVisibleIfAny(EquipmentActions, EquipmentDashboardButton, EquipmentMessagesButton, EquipmentTaskButton,
-            EquipmentAttendanceButton, EquipmentDailyReportButton, EquipmentButton, EquipmentPlannerButton);
+                var groupBox = new Fluent.RibbonGroupBox
+                {
+                    Header = name
+                };
+                var needsSeparator = false;
+                foreach(var group in groups)
+                {
+                    var addedSeparator = false;
+                    foreach(var button in group.Actions)
+                    {
+                        if (button.Visibility != Visibility.Visible) continue;
 
-        SetModuleVisibility<GPSTrackers>(TrackersMasterList, Security.CanView<GPSTracker>() && Security.IsAllowed<ViewDesktopGPSTrackersScreen>());
+                        if (!addedSeparator && needsSeparator)
+                        {
+                            groupBox.Items.Add(new RibbonSeparator());
+                            needsSeparator = false;
+                            addedSeparator = true;
+                        }
+                        if (!group.IsDefaultGroup)
+                        {
+                            hasNonDefault = true;
+                        }
+                        groupBox.Items.Add(button);
+                        needsSeparator = true;
+                    }
+                }
 
-        SetTabVisibleIfAny(EquipmentTab, EquipmentButton, TrackersMasterList);
+                if (groupBox.Items.Count > 0)
+                {
+                    item.Groups.Add(groupBox);
+                }
+            }
+
+            return hasNonDefault ? item : null;
+        }
     }
 
-    private void SetupAccountsReceivableTab(bool bMaps)
+    private class HeaderGroup(MainWindow window)
     {
-        if (!Security.IsAllowed<ViewDesktopAccountsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(AccountsReceivableDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
+        public List<Fluent.Button> Actions { get; set; } = new();
 
-        SetModuleVisibility<NotificationPanel>(AccountsReceivableMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(AccountsReceivableTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(AccountsReceivableAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(AccountsReceivableMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(AccountsReceivableDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
+        public bool IsDefaultGroup { get; set; } = false;
 
-        SetModuleVisibility<CustomerPanel>(CustomerList, ClientFactory.IsSupported<Customer>() 
-                                                   && Security.CanView<Customer>()
-                                                   && Security.IsAllowed<ViewDesktopCustomersScreen>());
+        private bool _locked = false;
 
-        SetModuleVisibility<InvoicePanel>(InvoiceList, ClientFactory.IsSupported<Invoice>() 
-                                                 && Security.CanView<Invoice>()
-                                                 && Security.IsAllowed<ViewDesktopInvoicesScreen>());
-
-        SetModuleVisibility<CustomerReceipts>(ReceiptList, ClientFactory.IsSupported<Receipt>() 
-                                                     && Security.CanView<Receipt>()
-                                                     && Security.IsAllowed<ViewDesktopReceiptsScreen>());
-        SetVisibleIfEither(AccountsReceivableTaskSeparator1,
-            new FrameworkElement[]
+        private Fluent.Button CreateButton(string name, ImageSource image)
+        {
+            if (_locked) throw new Exception("Header Group is locked!");
+            var button = new Fluent.Button
             {
-                            AccountsReceivableDashboardButton, AccountsReceivableMessagesButton, AccountsReceivableTaskButton, AccountsReceivableAttendanceButton, AccountsReceivableMapButton,
-                            AccountsReceivableDailyReportButton
-            }, new FrameworkElement[] { CustomerList, InvoiceList, ReceiptList });
-        SetVisibleIfAny(AccountsReceivableActions, AccountsReceivableDashboardButton, AccountsReceivableMessagesButton, AccountsReceivableTaskButton,
-            AccountsReceivableAttendanceButton,
-            AccountsReceivableDailyReportButton, CustomerList, InvoiceList, ReceiptList);
-
-        SetTabVisibleIfAny(AccountsReceivableTab, CustomerList, InvoiceList, ReceiptList);
-    }
-
-    private void SetupAccountsPayableTab(bool bMaps)
-    {
-        if (!Security.IsAllowed<ViewDesktopAccountsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(AccountsPayableDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
+                Header = name,
+                LargeIcon = image,
+                MinWidth = 60
+            };
+            Actions.Add(button);
+            return button;
+        }
 
-        SetModuleVisibility<NotificationPanel>(AccountsPayableMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(AccountsPayableTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(AccountsPayableAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(AccountsPayableMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(AccountsPayableDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
+        private Fluent.Button CreateButton(string name, Bitmap image)
+        {
+            return CreateButton(name, image.AsBitmapImage());
+        }
 
-        SetModuleVisibility<SupplierPanel>(SupplierList, ClientFactory.IsSupported<Supplier>() 
-                                                   && Security.CanView<Supplier>()
-                                                   && Security.IsAllowed<ViewDesktopSuppliersScreen>());
+        public HeaderGroup Add(string name, ImageSource image, Action onClick)
+        {
+            var button = CreateButton(name, image);
+            button.Command = new SimpleCommand(() => onClick());
+            return this;
+        }
 
-        SetModuleVisibility<DataEntryPanel>(AccountsDataButton, Security.IsAllowed<CanViewDataEntryPanel>());
+        public HeaderGroup Add(string name, Bitmap image, Action onClick)
+        {
+            var button = CreateButton(name, image);
+            button.Command = new SimpleCommand(() => onClick());
+            return this;
+        }
 
-        SetModuleVisibility<SupplierPurchaseOrderPanel>(PurchasesList, ClientFactory.IsSupported<PurchaseOrder>() 
-                                                                 && Security.CanView<PurchaseOrder>()
-                                                                 && Security.IsAllowed<ViewDesktopPurchaseOrdersScreen>());
+        public HeaderGroup Add<T>(string name, ImageSource image, bool visible = true)
+            where T : class, IBasePanel, new()
+        {
+            var button = CreateButton(name, image);
+            button.Command = new SimpleCommand(() => window.LoadWindow<T>(button));
+            
+            var menu = new ContextMenu();
+            menu.AddItem("Open in New Window", PRSDesktop.Resources.target, () => window.LoadSecondaryWindow<T>(button));
+            button.ContextMenu = menu;
 
-        SetModuleVisibility<SupplierBillPanel>(BillsList, ClientFactory.IsSupported<Bill>() 
-                                                    && Security.CanView<Bill>()
-                                                    && Security.IsAllowed<ViewDesktopBillsScreen>());
+            window.SetFrameworkItemVisibility(button, visible);
 
-        SetModuleVisibility<SupplierPayments>(PaymentsList, ClientFactory.IsSupported<Payment>() 
-                                                      && Security.CanView<Payment>()
-                                                      && Security.IsAllowed<ViewDesktopPaymentsScreen>());
+            return this;
+        }
 
-        SetVisibleIfEither(AccountsPayableTaskSeparator1,
-            new FrameworkElement[]
-            {
-                            AccountsPayableDashboardButton, AccountsPayableMessagesButton, AccountsPayableTaskButton, AccountsPayableAttendanceButton, AccountsPayableMapButton,
-                            AccountsPayableDailyReportButton
-            }, new FrameworkElement[] { SupplierList, AccountsDataButton, PurchasesList, BillsList, PaymentsList });
-        SetVisibleIfAny(AccountsPayableActions, AccountsPayableDashboardButton, AccountsPayableMessagesButton, AccountsPayableTaskButton,
-            AccountsPayableAttendanceButton,
-            AccountsPayableDailyReportButton, SupplierList, PurchasesList, BillsList, PaymentsList);
+        public HeaderGroup Add<T>(string name, Bitmap image, bool visible = true)
+            where T : class, IBasePanel, new()
+        {
+            return Add<T>(name, image.AsBitmapImage(), visible: visible);
+        }
 
-        SetTabVisibleIfAny(AccountsPayableTab, SupplierList, AccountsDataButton, PurchasesList, BillsList, PaymentsList);
+        public HeaderGroup Lock()
+        {
+            _locked = true;
+            return this;
+        }
     }
 
-    private void SetupHumanResourcesTab(bool bMaps)
+    private Fluent.RibbonTabItem? CreateTab(string header, Action<HeaderTab> modify)
     {
-        if (!Security.IsAllowed<ViewDesktopHumanResourcesTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(HumanResourcesDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(HumanResourcesMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(HumanResourcesTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(HumanResourcesAttendanceButton,
-            ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(HumanResourcesMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(HumanResourcesDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<CalendarPanel>(CalendarButton, Security.CanView<Assignment>() && Security.IsAllowed<ViewDesktopCalendarScreen>());
-        SetModuleVisibility<EmployeeResourcePlannerPanel>(EmployeePlannerButton, Security.CanView<Assignment>() && Security.IsAllowed<ViewDesktopEmployeePlannerScreen>());
-        SetModuleVisibility<TimesheetPanel>(TimesheetsButton, Security.CanView<TimeSheet>() && Security.IsAllowed<ViewDesktopStaffTimeSheetsScreen>());
-        SetModuleVisibility<LeaveRequestPanel>(LeaveRequestsButton, Security.CanView<LeaveRequest>() && Security.IsAllowed<ViewDesktopLeaveRequestsScreen>());
-        SetModuleVisibility<OrgChartPanel>(OrgChartButton,
-            ClientFactory.IsSupported<Employee>()
-            && 
-            Security.IsAllowed<ViewDesktopOrgChartScreen>()
-        );
-        SetModuleVisibility<MeetingPanel>(MeetingsButton, Security.IsAllowed<ViewDesktopMeetingsScreen>());
-
-        SetVisibleIfEither(HumanResourcesTaskSeparator,
-            new FrameworkElement[]
+        var tab = new HeaderTab(header, this)
+            .NewGroup(x => x
+                .Add("Refresh", PRSDesktop.Resources.refresh, PanelHost.Refresh)
+                .Lock(),
+                groupName: "Actions")
+            .NewGroup(x => x
+                .Add<UtilityDashboard>("Dashboards", SvgImages.kpi, Security.IsAllowed<CanViewUserDefinedDashboards>())
+                .Add<NotificationPanel>("Notification Centre", PRSDesktop.Resources.email, Security.CanView<Notification>())
+                .Add<TaskPanel>("Task List", SvgImages.kanban, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>())
+                .Add<AttendancePanel>("In/Out Board", PRSDesktop.Resources.attendance, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>())
+                .Add<LiveMapsPanel>("Live Maps", PRSDesktop.Resources.map, CanViewMaps)
+                .Add<DailyReport>("Daily Report", PRSDesktop.Resources.report, ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>())
+                .Lock());
+        foreach(var (_, groupList) in tab.Groups)
+        {
+            foreach(var group in groupList)
             {
-                            HumanResourcesDashboardButton, HumanResourcesMessagesButton, HumanResourcesTaskButton, HumanResourcesAttendanceButton,
-                            HumanResourcesMapButton, HumanResourcesDailyReportButton
-            }, new FrameworkElement[] { CalendarButton, EmployeePlannerButton, TimesheetsButton, LeaveRequestsButton, OrgChartButton });
-        SetVisibleIfAny(HumanResourcesActions, HumanResourcesDashboardButton, HumanResourcesTaskButton,
-            HumanResourcesAttendanceButton,
-            HumanResourcesDailyReportButton, CalendarButton, EmployeePlannerButton, TimesheetsButton, LeaveRequestsButton, OrgChartButton);
-
-        SetModuleVisibility<UserPanel>(UsersButton, Security.CanView<User>() && Security.IsAllowed<ViewDesktopUserAccountsScreen>());
-        SetModuleVisibility<EmployeePanel>(EmployeesButton, Security.CanView<Employee>() && Security.IsAllowed<ViewDesktopEmployeeListScreen>());
+                group.IsDefaultGroup = true;
+            }
+        }
+        modify(tab);
+        var result = tab.Create();
+        if(result is null)
+        {
+            // This means no other items were added; in this case don't create the tab.
+            return null;
+        }
 
-        SetVisibleIfEither(HumanResourcesSetupSeparator1,
-            new FrameworkElement[] { CalendarButton, TimesheetsButton, LeaveRequestsButton, OrgChartButton },
-            new FrameworkElement[] { UsersButton, EmployeesButton });
+        var box = new Fluent.RibbonGroupBox
+        {
+            Header = "Print",
+            Visibility = Visibility.Collapsed
+        };
+        result.Groups.Add(box);
 
-        SetTabVisibleIfAny(HumanResourcesTab, CalendarButton, TimesheetsButton, LeaveRequestsButton, OrgChartButton, UsersButton, EmployeesButton);
+        return result;
     }
-
-    private void SetupProductsTab(bool bMaps)
+    private Fluent.RibbonTabItem? CreateTab<TSecurity>(string header, Action<HeaderTab> modify)
+        where TSecurity : ISecurityDescriptor, new()
     {
-        if (!Security.IsAllowed<ViewDesktopProductManagementTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(ProductsDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(ProductsMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(ProductsTaskButton, Security.CanView<Kanban>());
-        SetModuleVisibility<AttendancePanel>(ProductsAttendanceButton, Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(ProductsMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(ProductsDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<ProductsPanel>(ProductsMasterList, Security.CanView<Product>() && Security.IsAllowed<ViewDesktopProductListScreen>());
-        SetModuleVisibility<StockLocationPanel>(StockLocationList, Security.CanView<StockLocation>() && Security.IsAllowed<ViewDesktopStockLocationsScreen>());
-        SetModuleVisibility<StockMovementPanel>(StockMovementList, Security.CanView<StockMovement>() && Security.IsAllowed<ViewDesktopStockMovementsScreen>());
-        SetModuleVisibility<StockForecastPanel>(StockForecastButton, Security.CanView<Product>()
-                                                                     && Security.CanView<JobMaterial>()
-                                                                     && Security.IsAllowed<ViewDesktopStockForecastScreen>());
-        SetModuleVisibility<ReservationManagementPanel>(ReservationManagementButton, Security.IsAllowed<ViewDesktopReservationManagementScreen>());
-
-        SetVisibleIfEither(ProductsTaskSeparator,
-            new FrameworkElement[]
-            {
-                            ProductsDashboardButton, ProductsMessagesButton, ProductsTaskButton, ProductsAttendanceButton, ProductsMapButton,
-                            ProductsDailyReportButton
-            }, new FrameworkElement[] { ProductsMasterList, StockLocationList, StockMovementList, StockForecastButton });
-
-        SetVisibleIfAny(ProductActions, ProductsMasterList, StockLocationList, StockMovementList, StockForecastButton);
-
-        SetTabVisibleIfAny(ProductTab, ProductActions);
+        if (!Security.IsAllowed<TSecurity>()) return null;
+        return CreateTab(header, modify);
     }
 
-    private void SetupLogisticsTab(bool bMaps)
-    {
-        if (!Security.IsAllowed<ViewDesktopLogisticsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(LogisticsDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(LogisticsMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(LogisticsTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(LogisticsAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(LogisticsMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(LogisticsDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<ReadyToGoPanel>(ReadyToGoItemsButton,
-            ClientFactory.IsSupported<DeliveryItem>()
-            && Security.IsAllowed<CanViewLogisticsReadyToGo>()
-            && Security.IsAllowed<ViewDesktopReadyToGoScreen>());
-
-        SetModuleVisibility<DispatchPanel>(DispatchButton, Security.CanView<Shipment>()
-                                                           && Security.CanView<DeliveryItem>()
-                                                           && Security.IsAllowed<ViewDesktopRackListScreen>());
-
-        SetModuleVisibility<RequisitionPanel>(RequisitionsButton, Security.CanView<Requisition>() && Security.IsAllowed<ViewDesktopSiteRequisitionsScreen>());
-
-        SetModuleVisibility<DeliveryPanel>(DeliveriesButton, Security.IsAllowed<CanViewDeliveriesModule>() && Security.IsAllowed<ViewDesktopDeliveriesScren>());
-
-        SetModuleVisibility<DeliveredOnSitePanel>(DeliveredItemsButton,
-            ClientFactory.IsSupported<DeliveryItem>()
-            && Security.IsAllowed<CanViewDeliveredOnSite>()
-            && Security.IsAllowed<ViewDesktopDeliveredOnSiteScreen>());
+    #region Visibility
 
-        SetModuleVisibility<ConsignmentsPanel>(ConsignmentButton, Security.CanView<Consignment>() && Security.IsAllowed<ViewDesktopIncomingConsignmentsScreen>());
 
-        SetVisibleIfEither(LogisticsTaskSeparator1,
-            new FrameworkElement[]
-            {
-                            LogisticsDashboardButton, LogisticsMessagesButton, LogisticsTaskButton, LogisticsAttendanceButton, LogisticsMapButton,
-                            LogisticsDailyReportButton
-            },
-            new FrameworkElement[]
-                { ReadyToGoItemsButton, DispatchButton, RequisitionsButton, DeliveriesButton, DeliveredItemsButton });
-        SetVisibleIfEither(LogisticsTaskSeparator2,
-            new FrameworkElement[]
-                { ReadyToGoItemsButton, DispatchButton, RequisitionsButton, DeliveriesButton, DeliveredItemsButton },
-            new FrameworkElement[] { ConsignmentButton });
+    private void SetFrameworkItemVisibility(FrameworkElement button, bool visible)
+    {
+        var vResult = true;
+        var eResult = ClientFactory.UserGuid != Guid.Empty && visible;
+        button.Visibility = vResult && eResult ? Visibility.Visible : Visibility.Collapsed;
 
-        SetTabVisibleIfAny(LogisticsTab, DispatchButton, RequisitionsButton, DeliveriesButton, ReadyToGoItemsButton,
-            DeliveredItemsButton,
-            ConsignmentButton);
+        if (button is Fluent.Button rb)
+        {
+            CustomModules.Register(rb.Header?.ToString() ?? "");
+            rb.IsEnabled = !OutstandingDailyReports(false);
+        }
     }
-
-    private void SetupManufacturingTab(bool bMaps)
+    
+    private void SetModuleVisibility<T>(Fluent.Button button, bool visible) where T : class, IBasePanel, new()
     {
-        if (!Security.IsAllowed<ViewDesktopManufacturingTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(ManufacturingDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(ManufacturingMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(ManufacturingTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(ManufacturingAttendanceButton,
-            ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(ManufacturingMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(ManufacturingDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-        
-        SetVisibleIfAny(ManufacturingTaskSeparator,
-            new FrameworkElement[]
-            {
-                ManufacturingDashboardButton, ManufacturingMessagesButton, ManufacturingTaskButton, ManufacturingAttendanceButton,
-                ManufacturingMapButton, ManufacturingDailyReportButton
-            });
-        
-        SetModuleVisibility<StagingPanel>(DesignManagementButton, Security.CanView<Job>() && Security.IsAllowed<ViewDesktopDesignManagementScreen>());
-        SetFrameworkItemVisibility(ManufacturingDesignSeparator, Security.CanView<Job>() && Security.IsAllowed<ViewDesktopDesignManagementScreen>());
+        SetFrameworkItemVisibility(button,visible);
         
-        SetModuleVisibility<ManufacturingPanel>(FactoryStatusButton,
-            ClientFactory.IsSupported<ManufacturingFactory, ManufacturingPacket>()
-            && Security.IsAllowed<CanViewFactoryStatus>()
-            && Security.IsAllowed<ViewDesktopManufacturingStatusScreen>());
-
-        SetModuleVisibility<ManufacturingAllocationPanel>(FactoryAllocationButton,
-            ClientFactory.IsSupported<ManufacturingFactory, ManufacturingPacket, ManufacturingPacketStage>()
-            && Security.IsAllowed<CanViewFactoryAllocation>()
-            && Security.IsAllowed<ViewDesktopFactoryAllocationScreen>());
-
-        //SetModuleVisibility<>(FactoryScheduleButton, ClientFactory.IsSupported<Booking>() && ClientFactory.IsEnabled<>());
-        SetModuleVisibility<FactoryPanel>(FactoryFloorButton,
-            ClientFactory.IsSupported<ManufacturingPacket>()
-            && Security.IsAllowed<CanViewFactoryFloor>()
-            && Security.IsAllowed<ViewDesktopFactoryFloorScreen>());
-        //SetModuleVisibility<>(FactoryReadyButton, ClientFactory.IsSupported<ManufacturingPacket>() && Security.IsAllowed<CanViewFactoryReadyToGo>());
+        button.MinWidth = 60;
         
-        SetVisibleIfAny(ManufacturingActionSeparator,
-            new FrameworkElement[]
+        if (button.Command == null)
+        {
+            button.Command = new SimpleCommand(() => LoadWindow<T>(button));
+       
+            var menu = new ContextMenu();
+            menu.Items.Add(new MenuItem()
             {
-                FactoryStatusButton, FactoryAllocationButton, FactoryFloorButton
+                Header = "Open in New Window",
+                Icon =  new System.Windows.Controls.Image() { Source = PRSDesktop.Resources.target.AsBitmapImage() },
+                Command = new SimpleCommand(() => LoadSecondaryWindow<T>(button))
             });
-
-        SetModuleVisibility<FactoryProductivityDashboard>(FactoryProductivityButton,
-            ClientFactory.IsSupported<ManufacturingHistory>() 
-            && Security.IsAllowed<CanViewFactoryKPIs>()
-            && Security.IsAllowed<ViewDesktopFactoryKPIsDashboard>());
-        SetModuleVisibility<ManufacturingTemplateAnalysis>(TemplateAnalysisButton,
-            ClientFactory.IsSupported<ManufacturingTemplate, ManufacturingHistory>() 
-            && Security.IsAllowed<CanViewTemplateAnalysis>()
-            && Security.IsAllowed<ViewDesktopTemplateAnalysisDashboard>());
-
-        SetModuleVisibility<FactoryFloorAnalysis>(FactoryAnalysisButton,
-            ClientFactory.IsSupported<ManufacturingTemplate, ManufacturingHistory>() 
-            && Security.IsAllowed<CanViewFactoryAnalysis>()
-            && Security.IsAllowed<ViewDesktopFactoryAnalysisDashboard>());
-        
-        SetVisibleIfAny(ManufacturingAnalysisSeparator, [FactoryProductivityButton, TemplateAnalysisButton, FactoryAnalysisButton]);
-        
-        
-        SetVisibleIfAny(ManufacturingActions, ManufacturingDashboardButton, ManufacturingMessagesButton, ManufacturingTaskButton,
-            ManufacturingAttendanceButton, ManufacturingDailyReportButton, FactoryStatusButton, FactoryAllocationButton,
-            FactoryFloorButton, FactoryProductivityButton, TemplateAnalysisButton, FactoryAnalysisButton);
-
-        SetTabVisibleIfAny(ManufacturingTab, FactoryStatusButton, FactoryAllocationButton, FactoryFloorButton);
+            button.ContextMenu = menu;
+        }
     }
 
-    private void SetupProjectsTab(bool bMaps)
+    private static void SetVisibleIfEither(FrameworkElement separator, FrameworkElement[] left, FrameworkElement[] right)
     {
-        if (!Security.IsAllowed<ViewDesktopProjectsTab>())
-            return;
-
-        SetModuleVisibility<UtilityDashboard>(ProjectsDashboardButton, Security.IsAllowed<CanViewUserDefinedDashboards>());
-
-        SetModuleVisibility<NotificationPanel>(ProjectMessagesButton, Security.CanView<Notification>());
-        SetModuleVisibility<TaskPanel>(ProjectTaskButton, ClientFactory.IsSupported<Kanban>() && Security.IsAllowed<CanViewTasks>());
-        SetModuleVisibility<AttendancePanel>(ProjectAttendanceButton, ClientFactory.IsSupported<TimeSheet>() && Security.IsAllowed<CanViewInOutBoard>());
-        SetModuleVisibility<LiveMapsPanel>(ProjectsMapButton, bMaps);
-        SetModuleVisibility<DailyReport>(ProjectDailyReportButton,
-            ClientFactory.IsSupported<TimeSheet, Assignment>() && Security.IsAllowed<CanViewDailyReports>());
-
-        SetModuleVisibility<ProjectsPanel>(ProjectsButton, Security.CanView<Job>() && Security.IsAllowed<ViewDesktopProjectsScreen>());
-        //SetModuleVisibility<>(ServiceButton, Security.CanView<Job>() && Security.IsAllowed<ViewDesktopServiceScreen>());
-        SetModuleVisibility<JobResourcePlannerPanel>(ProjectPlannerButton, Security.CanView<Job>() && Security.IsAllowed<ViewDesktopProjectPlannerScreen>());
-        
-        SetVisibleIfEither(ProjectTaskSeparator,
-            new FrameworkElement[]
-            {
-                            ProjectsDashboardButton, ProjectMessagesButton, ProjectTaskButton, ProjectAttendanceButton, ProjectsMapButton,
-                            ProjectDailyReportButton
-            }, new FrameworkElement[] { QuotesButton, ProjectsButton, ProjectPlannerButton });
-        
-        SetModuleVisibility<QuotePanel>(QuotesButton, Security.CanView<Quote>() && Security.IsAllowed<ViewDesktopQuotesScreen>());
-        SetModuleVisibility<KitPanel>(KitsMasterList, Security.CanView<Kit>() && Security.IsAllowed<ViewDesktopProductKitsScreen>());
-        SetModuleVisibility<CostSheetPanel>(CostSheetsMasterList, Security.CanView<CostSheet>() && Security.IsAllowed<ViewDesktopCostSheetsScreen>());
-        SetVisibleIfAny(ProjectsSetup, KitsMasterList, CostSheetsMasterList);
-
+        var bLeft = false;
+        foreach (var button in left)
+            bLeft = bLeft || button.Visibility == Visibility.Visible;
 
-        //ProjectsActions.IsLauncherButtonVisible = Security.IsAllowed<CanCustomiseModules>();
-        //ProjectReports.IsLauncherButtonVisible = Security.IsAllowed<CanDesignReports>();
+        var bRight = false;
+        foreach (var button in right)
+            bRight = bRight || button.Visibility == Visibility.Visible;
 
-        SetTabVisibleIfAny(ProjectsTab, QuotesButton, ProjectsButton, ProjectPlannerButton, CostSheetsMasterList, KitsMasterList);
+        separator.Visibility = bLeft && bRight ? Visibility.Visible : Visibility.Collapsed;
     }
-    
-    private void SetupDock<TSecurityDescriptor>(LayoutAnchorable layout, IDockPanel dock)
-        where TSecurityDescriptor : ISecurityDescriptor, new()
+
+    private static void SetVisibleIfAny(FrameworkElement separator, params FrameworkElement[] buttons)
     {
-        if (Security.IsAllowed<TSecurityDescriptor>())
-        {
-            if (!DockGroup.Children.Any(x => x == layout))
-            {
-                DockGroup.Children.Add(layout);
-            }
-            if (layout.IsVisible && (ClientFactory.UserGuid != Guid.Empty))
-                dock.Setup();
-        }
-        else
-        {
-            DockGroup.RemoveChild(layout);
-        }
+        var bVisible = false;
+        foreach (var button in buttons)
+            bVisible = bVisible || button.Visibility == Visibility.Visible;
+        separator.Visibility = bVisible ? Visibility.Visible : Visibility.Collapsed;
     }
+    private static void SetTabVisibleIfAny(Fluent.RibbonTabItem tab, params FrameworkElement[] buttons)
+    {
+        var bVisible = false;
+        foreach (var button in buttons)
+            bVisible = bVisible || button.Visibility == Visibility.Visible;
 
+        tab.Visibility = bVisible ? Visibility.Visible : Visibility.Collapsed;
+    }
 
+    #endregion
 
     private void LoadApplicationState()
     {
@@ -2017,74 +2028,6 @@ public partial class MainWindow : IPanelHostControl
                     });
     }
 
-    #region Visibility
-
-
-    private void SetFrameworkItemVisibility(FrameworkElement button, bool visible)
-    {
-        var vResult = true;
-        var eResult = ClientFactory.UserGuid != Guid.Empty && visible;
-        button.Visibility = vResult && eResult ? Visibility.Visible : Visibility.Collapsed;
-
-        if (button is Fluent.Button rb)
-        {
-            CustomModules.Register(rb.Header?.ToString() ?? "");
-            rb.IsEnabled = !OutstandingDailyReports(false);
-        }
-    }
-    
-    private void SetModuleVisibility<T>(Fluent.Button button, bool visible) where T : class, IBasePanel, new()
-    {
-        SetFrameworkItemVisibility(button,visible);
-        
-        button.MinWidth = 60;
-        
-        if (button.Command == null)
-        {
-            button.Command = new SimpleCommand(() => LoadWindow<T>(button));
-       
-            var menu = new ContextMenu();
-            menu.Items.Add(new MenuItem()
-            {
-                Header = "Open in New Window",
-                Icon =  new System.Windows.Controls.Image() { Source = PRSDesktop.Resources.target.AsBitmapImage() },
-                Command = new SimpleCommand(() => LoadSecondaryWindow<T>(button))
-            });
-            button.ContextMenu = menu;
-        }
-    }
-
-    private static void SetVisibleIfEither(FrameworkElement separator, FrameworkElement[] left, FrameworkElement[] right)
-    {
-        var bLeft = false;
-        foreach (var button in left)
-            bLeft = bLeft || button.Visibility == Visibility.Visible;
-
-        var bRight = false;
-        foreach (var button in right)
-            bRight = bRight || button.Visibility == Visibility.Visible;
-
-        separator.Visibility = bLeft && bRight ? Visibility.Visible : Visibility.Collapsed;
-    }
-
-    private static void SetVisibleIfAny(FrameworkElement separator, params FrameworkElement[] buttons)
-    {
-        var bVisible = false;
-        foreach (var button in buttons)
-            bVisible = bVisible || button.Visibility == Visibility.Visible;
-        separator.Visibility = bVisible ? Visibility.Visible : Visibility.Collapsed;
-    }
-    private static void SetTabVisibleIfAny(Fluent.RibbonTabItem tab, params FrameworkElement[] buttons)
-    {
-        var bVisible = false;
-        foreach (var button in buttons)
-            bVisible = bVisible || button.Visibility == Visibility.Visible;
-
-        tab.Visibility = bVisible ? Visibility.Visible : Visibility.Collapsed;
-    }
-
-    #endregion
-
     private static Fluent.RibbonGroupBox? FindRibbonBar(Fluent.RibbonTabItem tab, Func<Fluent.RibbonGroupBox, bool> predicate)
     {
         foreach (var group in tab.Groups)

+ 1 - 0
prs.desktop/PRSDesktop.csproj

@@ -906,6 +906,7 @@
       <PackageReference Include="Dirkster.AvalonDock" Version="4.72.1" />
       <PackageReference Include="Dirkster.AvalonDock.Themes.Metro" Version="4.72.1" />
       <PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
+      <PackageReference Include="DotNetProjects.SVGImage" Version="5.2.12" />
       <PackageReference Include="Fluent.Ribbon" Version="10.1.0" />
       <PackageReference Include="gmaps-api-net" Version="0.33.0" />
       <PackageReference Include="Microsoft.Office.Interop.Outlook" Version="15.0.4797.1004" />

+ 11 - 0
prs.desktop/Resources.Designer.cs

@@ -1,6 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -218,6 +219,16 @@ namespace PRSDesktop {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap calendar {
+            get {
+                object obj = ResourceManager.GetObject("calendar", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized resource of type System.Drawing.Bitmap.
         /// </summary>

+ 4 - 0
prs.desktop/Resources.resx

@@ -142,6 +142,10 @@
     <value>.\Resources\box.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
             PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="calendar" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>.\Resources\calendar.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
+            PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="change" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>.\Resources\change.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral,
             PublicKeyToken=b77a5c561934e089</value>

+ 42 - 0
prs.desktop/SvgImages.cs

@@ -0,0 +1,42 @@
+using SVGImage.SVG;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace PRSDesktop;
+
+public static class SvgImages
+{
+    private static ImageSource SvgImage(string filename)
+    {
+        var render = new SVGRender();
+        var uri = new Uri(filename, UriKind.Relative);
+        var info = Application.GetResourceStream(uri);
+        return new DrawingImage(render.LoadDrawing(info.Stream));
+    }
+
+    private static readonly Lazy<ImageSource> _beach = new(() => SvgImage("/Resources/beach.svg"));
+    public static ImageSource beach => _beach.Value;
+
+    private static readonly Lazy<ImageSource> _box = new(() => SvgImage("/Resources/box.svg"));
+    public static ImageSource box => _box.Value;
+
+    private static readonly Lazy<ImageSource> _formsinstance = new(() => SvgImage("/Resources/formsinstance.svg"));
+    public static ImageSource formsinstance => _formsinstance.Value;
+
+    private static readonly Lazy<ImageSource> _formslibrary = new(() => SvgImage("/Resources/formslibrary.svg"));
+    public static ImageSource formslibrary => _formslibrary.Value;
+
+    private static readonly Lazy<ImageSource> _kanban = new(() => SvgImage("/Resources/kanban.svg"));
+    public static ImageSource kanban => _kanban.Value;
+
+    private static readonly Lazy<ImageSource> _kpi = new(() => SvgImage("/Resources/kpi.svg"));
+    public static ImageSource kpi => _kpi.Value;
+
+    private static readonly Lazy<ImageSource> _truck = new(() => SvgImage("/Resources/truck.svg"));
+    public static ImageSource truck => _truck.Value;
+}