Просмотр исходного кода

Config-Management abgeschlossen und Reporting verbessert!

Arne Diekmann 8 лет назад
Родитель
Сommit
fd9375b937
26 измененных файлов с 1335 добавлено и 94 удалено
  1. 1 1
      GreenTree.Nachtragsmanagement.Data/AppendixObjectContext.cs
  2. 4 0
      GreenTree.Nachtragsmanagement.Web.Framework/ApplicationContext.cs
  3. 69 13
      GreenTree.Nachtragsmanagement.Web/Controllers/AppendixController.cs
  4. 15 1
      GreenTree.Nachtragsmanagement.Web/Controllers/MiscController.cs
  5. 9 20
      GreenTree.Nachtragsmanagement.Web/Extensions/GridViewSettingsHelper.cs
  6. 564 0
      GreenTree.Nachtragsmanagement.Web/Extensions/MVCxGridViewGeneratorHelper.cs
  7. 154 0
      GreenTree.Nachtragsmanagement.Web/Extensions/MVCxGridViewState.cs
  8. 31 13
      GreenTree.Nachtragsmanagement.Web/Global.asax.cs
  9. 18 0
      GreenTree.Nachtragsmanagement.Web/GreenTree.Nachtragsmanagement.Web.csproj
  10. 0 3
      GreenTree.Nachtragsmanagement.Web/Implementations/AppendixNotificationPlugin.cs
  11. 6 4
      GreenTree.Nachtragsmanagement.Web/Implementations/DeviationNotificationPlugin.cs
  12. 2 0
      GreenTree.Nachtragsmanagement.Web/Models/Config/ConfigItemDataModel.cs
  13. 13 0
      GreenTree.Nachtragsmanagement.Web/Models/Global/PrintGridModel.cs
  14. 1 0
      GreenTree.Nachtragsmanagement.Web/Properties/licenses.licx
  15. 51 0
      GreenTree.Nachtragsmanagement.Web/Reports/XtraReportGridView.Designer.cs
  16. 18 0
      GreenTree.Nachtragsmanagement.Web/Reports/XtraReportGridView.cs
  17. 10 12
      GreenTree.Nachtragsmanagement.Web/Views/Appendices/View.cshtml
  18. 26 19
      GreenTree.Nachtragsmanagement.Web/Views/Config/View.cshtml
  19. 123 0
      GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemEditPartial.cshtml
  20. 22 7
      GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemGridPartial.cshtml
  21. 83 0
      GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemValueEditPartial.cshtml
  22. 10 0
      GreenTree.Nachtragsmanagement.Web/Views/Home/Index.cshtml
  23. 47 0
      GreenTree.Nachtragsmanagement.Web/Views/Shared/SaveDocumentViewer.cshtml
  24. 25 0
      GreenTree.Nachtragsmanagement.Web/Views/Shared/_PrintDocumentViewerPartial.cshtml
  25. 32 0
      GreenTree.Nachtragsmanagement.Web/Views/Shared/_PrintPopupPartial.cshtml
  26. 1 1
      GreenTree.Nachtragsmanagement.Web/Views/Sites/_SiteEditPartial.cshtml

+ 1 - 1
GreenTree.Nachtragsmanagement.Data/AppendixObjectContext.cs

@@ -86,7 +86,7 @@ namespace GreenTree.Nachtragsmanagement.Data
             //Database.SetInitializer(new CreateDatabaseIfNotExists<AppendixObjectContext>());
             Database.SetInitializer(new DropCreateDatabaseIfModelChanges<AppendixObjectContext>());
 
-            Database.CreateIfNotExists();
+            //Database.CreateIfNotExists();
 
             ((IObjectContextAdapter)this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
 

+ 4 - 0
GreenTree.Nachtragsmanagement.Web.Framework/ApplicationContext.cs

@@ -131,6 +131,10 @@ namespace GreenTree.Nachtragsmanagement.Web.Framework
 
             _appContainer = builder.Build();
 
+            var selfBuilder = new ContainerBuilder();
+            selfBuilder.RegisterInstance(_appContainer).As<IContainer>();
+            selfBuilder.Update(_appContainer);
+
             Singleton<IContainer>.Instance = _appContainer;
 
             // Register plugin controllers in a new container builder

+ 69 - 13
GreenTree.Nachtragsmanagement.Web/Controllers/AppendixController.cs

@@ -1,10 +1,13 @@
 using DevExpress.Web.Mvc;
+using DevExpress.XtraPrinting;
+using DevExpress.XtraReports.UI;
 using GreenTree.Nachtragsmanagement.Core;
 using GreenTree.Nachtragsmanagement.Core.Authentication;
 using GreenTree.Nachtragsmanagement.Services.Appendix;
 using GreenTree.Nachtragsmanagement.Services.Deviation;
 using GreenTree.Nachtragsmanagement.Services.Logging;
 using GreenTree.Nachtragsmanagement.Services.Site;
+using GreenTree.Nachtragsmanagement.Web.Extensions;
 using GreenTree.Nachtragsmanagement.Web.Framework.Authorization;
 using GreenTree.Nachtragsmanagement.Web.Models.Appendix;
 using GreenTree.Nachtragsmanagement.Web.Models.Deviation;
@@ -12,9 +15,11 @@ using GreenTree.Nachtragsmanagement.Web.Models.Global;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
+using static GreenTree.Nachtragsmanagement.Web.Extensions.MVCxGridViewGeneratorHelper;
 
 namespace GreenTree.Nachtragsmanagement.Web.Controllers
 {
@@ -105,9 +110,9 @@ namespace GreenTree.Nachtragsmanagement.Web.Controllers
         /// Export result for appendix grid
         /// </summary>
         [HttpPost]
-        public ActionResult ExportPartialAppendices(GridViewExportFormat exportformat)
+        public ActionResult ExportPartialAppendices(string displayMode, string exportformat)
         {
-            if (exportformat == null || String.IsNullOrEmpty(exportformat.Format))
+            if (String.IsNullOrEmpty(displayMode))
                 return new EmptyResult();
 
             var currentUser = _userHelper.FromCookies();
@@ -119,23 +124,74 @@ namespace GreenTree.Nachtragsmanagement.Web.Controllers
 
             var viewContext = new ViewContext();
             var viewPage = new ViewPage();
-            var htmlHelper = new HtmlHelper(viewContext, viewPage);
+            var htmlHelper = new System.Web.Mvc.HtmlHelper(viewContext, viewPage);
 
-            var gridViewSettings = Extensions.GridViewSettingsHelper.AppendixGridViewSettings(htmlHelper);
+            MVCxGridViewState gridViewState = (MVCxGridViewState)Session["AppendixGridViewState"];
 
-            switch (exportformat.Format.ToLower())
+            if (gridViewState != null)
             {
-                case "xlsx":
-                    return GridViewExtension.ExportToXlsx(gridViewSettings, appendixModels);
-                case "xls":
-                    return GridViewExtension.ExportToXls(gridViewSettings, appendixModels);
-                case "pdf":
-                    return GridViewExtension.ExportToPdf(gridViewSettings, appendixModels);
-                default:
-                    return new EmptyResult();
+                var generator = new MVCReportGeneratonHelper();
+
+                generator.CustomizeColumnsCollection += new CustomizeColumnsCollectionEventHandler(generator_CustomizeColumnsCollection);
+                generator.CustomizeColumnSummary += new CustomizeColumnSummaryEventHandler(generator_CustomizeColumnSummary);
+
+                var report = generator.GenerateMVCReport(gridViewState, appendixModels);
+
+                if (displayMode == "popup")
+                    return PartialView("~/Views/Shared/_PrintPopupPartial.cshtml", new PrintGridModel { Report = report });
+                else if (displayMode == "callback")
+                    return PartialView("~/Views/Shared/_PrintDocumentViewerPartial.cshtml", new PrintGridModel { Report = report });
+                else if (displayMode == "export")
+                {
+                    switch (exportformat.ToLower())
+                    {
+                        case "xlsx":
+                            generator.WriteXlsxToResponse(Response, "test.xlsx", 
+                                System.Net.Mime.DispositionTypeNames.Attachment.ToString());
+                            break;
+                        case "xls":
+                            generator.WriteXlsToResponse(Response, "test.xls", 
+                                System.Net.Mime.DispositionTypeNames.Attachment.ToString());
+                            break;
+                        case "pdf":
+                            generator.WritePdfToResponse(Response, "test.pdf", 
+                                System.Net.Mime.DispositionTypeNames.Attachment.ToString());
+                            break;
+                    }
+                }
+
+                return new EmptyResult();
+            }
+            else
+                return new EmptyResult();
+        }
+
+        /// <summary>
+        /// Customize created columns
+        /// </summary>
+        private void generator_CustomizeColumnsCollection(object source, ColumnsCreationEventArgs e)
+        {
+            foreach (var column in e.ColumnsInfo)
+            {
+                if (column.FieldName == "CustomNumber") { column.ColumnWidth = 30; }
+                if (column.FieldName == "SiteDescription") { column.ColumnWidth = 60; }
+                if (column.FieldName == "DeviationDescription") { column.ColumnWidth = 50; }
+                if (column.FieldName == "RelationOfferingToNegotiation") { column.ColumnWidth = 70; }
+                if (column.FieldName == "RelationOfferingToDeviations") { column.ColumnWidth = 80; }
+                if (column.FieldName == "StateDescription") { column.ColumnWidth = 60; }
             }
         }
 
+        /// <summary>
+        /// Customize column summary
+        /// </summary>
+        private void generator_CustomizeColumnSummary(object source, ColumnSummaryCreationEventArgs e)
+        {
+            if (e.FieldName == "OfferingValue") { e.Summary.FormatString = "{0:c2}"; }
+            if (e.FieldName == "NegotiationValue") { e.Summary.FormatString = "{0:c2}"; }
+            if (e.FieldName == "Description") { e.Summary.FormatString = "Alle = {0:n0}"; }
+        }
+
         /// <summary>
         /// Partial edit for editing of existing or for new appendix
         /// </summary>

+ 15 - 1
GreenTree.Nachtragsmanagement.Web/Controllers/MiscController.cs

@@ -512,6 +512,20 @@ namespace GreenTree.Nachtragsmanagement.Web.Controllers
             return PartialView("~/Views/Config/_ConfigItemGridPartial.cshtml", configItemModels);
         }
 
+        /// <summary>
+        /// Partial edit for config item value
+        /// </summary>
+        /// <param name="typeFullName">Value type.</param>
+        public ActionResult GetValueTypePartialEdit(string typeFullName)
+        {
+            var model = new ConfigItemDataModel
+            {
+                TypeFullName = typeFullName
+            };
+
+            return PartialView("~/Views/Config/_ConfigItemValueEditPartial.cshtml", model);
+        }
+
         /// <summary>
         /// Partial edit for editing of existing or for new configItem
         /// </summary>
@@ -551,7 +565,7 @@ namespace GreenTree.Nachtragsmanagement.Web.Controllers
                     configItem.Name = configItemModel.Name;
                     configItem.TypeFullName = configItemModel.TypeFullName;
                     configItem.Value = configItemModel.Value;
-                    configItem.Description = configItem.Description;
+                    configItem.Description = configItemModel.Description;
 
                     _configurationService.UpdateConfigItem(configItem);
 

+ 9 - 20
GreenTree.Nachtragsmanagement.Web/Extensions/GridViewSettingsHelper.cs

@@ -653,27 +653,10 @@ namespace GreenTree.Nachtragsmanagement.Web.Extensions
                 });
                 t.Items.Add(i =>
                 {
-                    i.Text = "Exportieren nach";
-                    i.Image.IconID = IconID.ActionsDownload16x16office2013;
+                    i.Text = "Drucken";
+                    i.Name = "Print";
+                    i.Image.IconID = IconID.PrintDefaultprinter16x16;
                     i.BeginGroup = true;
-                    i.Items.Add(exportitem =>
-                    {
-                        exportitem.Name = "Pdf";
-                        exportitem.Text = "PDF";
-                        exportitem.Image.IconID = IconID.ExportExporttopdf16x16office2013;
-                    });
-                    i.Items.Add(exportitem =>
-                    {
-                        exportitem.Name = "Xlsx";
-                        exportitem.Text = "XLSX";
-                        exportitem.Image.IconID = IconID.ExportExporttoxlsx16x16office2013;
-                    });
-                    i.Items.Add(exportitem =>
-                    {
-                        exportitem.Name = "Xls";
-                        exportitem.Text = "XLS";
-                        exportitem.Image.IconID = IconID.ExportExporttoxls16x16office2013;
-                    });
                 });
             });
 
@@ -860,6 +843,12 @@ namespace GreenTree.Nachtragsmanagement.Web.Extensions
                 else
                     System.Web.HttpContext.Current.Session["AppendixGridState"] = e.LayoutData;
             };
+
+            s.PreRender = s.BeforeGetCallbackResult = (sender, e) => {
+                MVCxGridView gridView = sender as MVCxGridView;
+                System.Web.HttpContext.Current.Session["AppendixGridViewState"] = new MVCxGridViewState(gridView);
+            };
+
             s.ClientSideEvents.BeginCallback = "function (s, e) { e.customArgs['scrollHeight'] = [ gridScrollHeight ]; }";
             s.ClientSideEvents.ToolbarItemClick = "function (s, e) { onToolbarItemClick(s, e); }";
             s.ClientSideEvents.ColumnResized = "function (s, e) { setGridScrollHeight(); }";

+ 564 - 0
GreenTree.Nachtragsmanagement.Web/Extensions/MVCxGridViewGeneratorHelper.cs

@@ -0,0 +1,564 @@
+using DevExpress.Data;
+using DevExpress.XtraEditors.Controls;
+using DevExpress.XtraPrinting;
+using DevExpress.XtraReports.UI;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Net.Mime;
+using System.Web;
+
+namespace GreenTree.Nachtragsmanagement.Web.Extensions
+{
+    public class MVCxGridViewGeneratorHelper
+    {
+        public delegate void CustomizeColumnsCollectionEventHandler(object source, ColumnsCreationEventArgs e);
+        public delegate void CustomizeColumnEventHandler(object source, ControlCustomizationEventArgs e);
+        public delegate void CustomizeColumnSummaryEventHandler(object source, ColumnSummaryCreationEventArgs e);
+
+        public class MVCReportGeneratonHelper
+        {
+            const int initialGroupOffset = 0;
+            const int subGroupOffset = 10;
+            const int bandHeight = 20;
+            const bool shouldRepeatGroupHeadersOnEveryPage = false;
+
+            XtraReport report;
+
+            Hashtable detailsInfo = new Hashtable();
+            Hashtable detailsWidth = new Hashtable();
+
+            public event CustomizeColumnsCollectionEventHandler CustomizeColumnsCollection;
+            public event CustomizeColumnEventHandler CustomizeColumn;
+            public event CustomizeColumnSummaryEventHandler CustomizeColumnSummary;
+
+            public XtraReport GenerateMVCReport(MVCxGridViewState gridViewState, object model)
+            {
+                report = new XtraReport
+                {
+                    Font = new Font("Calibri", 10f, FontStyle.Regular),
+                    Landscape = true,
+                    PaperKind = System.Drawing.Printing.PaperKind.A4
+                };
+
+                InitStyles();
+                InitDataSource(model);
+                InitDetailsAndPageHeader(gridViewState);
+                InitSortings(gridViewState);
+                InitGroupHeaders(gridViewState);
+                InitFilters(gridViewState);
+                InitTotalSummaries(gridViewState);
+
+                return report;
+            }
+
+            private void InitStyles()
+            {
+                report.StyleSheet.Add(new XRControlStyle
+                {
+                    Name = "OddRow",
+                    Borders = (DevExpress.XtraPrinting.BorderSide.Bottom | 
+                               DevExpress.XtraPrinting.BorderSide.Left | 
+                               DevExpress.XtraPrinting.BorderSide.Right),
+                    Padding = new PaddingInfo(30, 600)
+                });
+
+                report.StyleSheet.Add(new XRControlStyle
+                {
+                    Name = "EvenRow",
+                    BackColor = Color.LightGray,
+                    Borders = (DevExpress.XtraPrinting.BorderSide.Bottom |
+                               DevExpress.XtraPrinting.BorderSide.Left |
+                               DevExpress.XtraPrinting.BorderSide.Right),
+                    Padding = new PaddingInfo(30, 600)
+                });
+
+                report.StyleSheet.Add(new XRControlStyle
+                {
+                    Name = "HeaderRow",
+                    BackColor = Color.FromArgb(156, 183, 191),
+                    Borders = DevExpress.XtraPrinting.BorderSide.All,
+                    Padding = new PaddingInfo(30, 600),
+                    Font = new Font(report.Font, FontStyle.Bold)
+                });
+
+                report.StyleSheet.Add(new XRControlStyle
+                {
+                    Name = "SummaryRow",
+                    BackColor = Color.FromArgb(35, 133, 160),
+                    Borders = DevExpress.XtraPrinting.BorderSide.All,
+                    BorderColor = Color.FromArgb(35, 133, 160),
+                    Padding = new PaddingInfo(30, 600),
+                    ForeColor = Color.White,
+                    Font = new Font(report.Font, FontStyle.Bold)
+                });
+            }
+
+            private void InitDataSource(object model)
+            {
+                report.DataSource = model;
+            }
+
+            private void InitDetailsAndPageHeader(MVCxGridViewState gridViewState)
+            {
+                var groupedColumns = gridViewState.GroupedColumns;
+
+                var pagewidth = (report.PageWidth - (report.Margins.Left + report.Margins.Right)) - groupedColumns.Count * subGroupOffset;
+                var columns = GetColumnsInfo(gridViewState, pagewidth);
+
+                if (CustomizeColumnsCollection != null)
+                    CustomizeColumnsCollection(report, new ColumnsCreationEventArgs(pagewidth)
+                    {
+                        ColumnsInfo = columns
+                    });
+
+                report.Bands.Add(new DetailBand()
+                {
+                    HeightF = bandHeight
+                });
+                report.Bands.Add(new PageHeaderBand()
+                {
+                    HeightF = bandHeight
+                });
+
+                var headerTable = new XRTable()
+                {
+                    StyleName = "HeaderRow"
+                };
+                var row = new XRTableRow();
+
+                var detailTable = new XRTable
+                {
+                    OddStyleName = "OddRow",
+                    EvenStyleName = "EvenRow"
+                };
+                var row2 = new XRTableRow();
+
+                for (var i = 0; i < columns.Count; i++)
+                {
+                    if (columns[i].IsVisible)
+                    {
+                        var cell = new XRTableCell
+                        {
+                            Width = columns[i].ColumnWidth,
+                            Text = columns[i].GridViewColumn.Caption,
+                            Borders = DevExpress.XtraPrinting.BorderSide.All,
+                            TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
+                        };
+                        row.Cells.Add(cell);
+
+                        var cell2 = new XRTableCell
+                        {
+                            Width = columns[i].ColumnWidth
+                        };
+
+                        var cc = new ControlCustomizationEventArgs
+                        {
+                            FieldName = columns[i].FieldName,
+                            IsModified = false,
+                            Owner = cell2,
+                            Header = cell
+                        };
+
+                        if (CustomizeColumn != null)
+                            CustomizeColumn(report, cc);
+
+                        if (cc.IsModified == false)
+                            cell2.DataBindings.Add("Text", null, columns[i].FieldName,
+                                "{0:" + columns[i].GridViewColumn.DisplayFormat + "}");
+
+                        detailsInfo.Add(columns[i].GridViewColumn, cell2);
+
+                        row2.Cells.Add(cell2);
+
+                        detailsWidth.Add(columns[i].GridViewColumn, cell2.WidthF);
+                    }
+                }
+                headerTable.Rows.Add(row);
+                headerTable.Width = pagewidth;
+                headerTable.LocationF = new PointF(groupedColumns.Count * subGroupOffset, 0);
+                headerTable.Borders = DevExpress.XtraPrinting.BorderSide.Bottom;
+
+                detailTable.Rows.Add(row2);
+                detailTable.LocationF = new PointF(groupedColumns.Count * subGroupOffset, 0);
+                detailTable.Width = pagewidth;
+
+                report.Bands[BandKind.PageHeader].Controls.Add(headerTable);
+                report.Bands[BandKind.Detail].Controls.Add(detailTable);
+            }
+
+            private void InitSortings(MVCxGridViewState gridViewState)
+            {
+                var columns = gridViewState.Columns;
+                var groupedColumns = gridViewState.GroupedColumns;
+
+                for (var i = 0; i < columns.Count; i++)
+                {
+                    if (!groupedColumns.Contains(columns[i]))
+                    {
+                        if (columns[i].SortOrder != ColumnSortOrder.None)
+                            ((DetailBand)report.Bands[BandKind.Detail]).SortFields.Add(new GroupField(columns[i].FieldName, columns[i].SortOrder == ColumnSortOrder.Ascending ? XRColumnSortOrder.Ascending : XRColumnSortOrder.Descending));
+                    }
+                }
+            }
+
+            private void InitGroupHeaders(MVCxGridViewState gridViewState)
+            {
+                GridViewDataColumnStateCollection groupedColumns = gridViewState.GroupedColumns;
+                for (int i = groupedColumns.Count - 1; i >= 0; i--)
+                {
+                    {
+                        GridViewDataColumnState groupedColumn = groupedColumns[i];
+                        GroupHeaderBand gb = new GroupHeaderBand();
+                        gb.Height = bandHeight;
+                        XRLabel l = new XRLabel();
+                        l.Text = groupedColumn.FieldName + ": [" + groupedColumn.FieldName + "]";
+                        l.LocationF = new PointF(initialGroupOffset + i * 10, 0);
+                        l.BackColor = Color.Beige;
+                        l.SizeF = new SizeF((report.PageWidth - (report.Margins.Left + report.Margins.Right)) - (initialGroupOffset + i * subGroupOffset), bandHeight);
+                        gb.Controls.Add(l);
+                        gb.RepeatEveryPage = shouldRepeatGroupHeadersOnEveryPage;
+                        GroupField gf = new GroupField(groupedColumn.FieldName, groupedColumn.SortOrder == ColumnSortOrder.Ascending ? XRColumnSortOrder.Ascending : XRColumnSortOrder.Descending);
+                        gb.GroupFields.Add(gf);
+                        report.Bands.Add(gb);
+                    }
+                }
+            }
+
+            private void InitFilters(MVCxGridViewState gridViewState)
+            {
+                report.FilterString = gridViewState.FilterExpression;
+            }
+
+            private void InitTotalSummaries(MVCxGridViewState gridViewState)
+            {
+                if (gridViewState.TotalSummary.Count == 0) return;
+
+                report.Bands.Add(new ReportFooterBand
+                {
+                    HeightF = bandHeight,
+                    StyleName = "SummaryRow"
+                });
+
+                foreach (MVCxSummaryItemState item in gridViewState.TotalSummary)
+                {
+                    var col = gridViewState.Columns[item.ShowInColumn == string.Empty ? item.FieldName : item.ShowInColumn];
+
+                    if (col == null) continue;
+
+                    if (!detailsInfo.Contains(col)) return;
+
+                    var label = new XRLabel
+                    {
+                        LocationF = ((XRTableCell)detailsInfo[col]).LocationF,
+                        SizeF = ((XRTableCell)detailsInfo[col]).SizeF
+                    };
+                    label.DataBindings.Add("Text", null, col.FieldName);
+                    label.Summary = new XRSummary
+                    {
+                        Running = SummaryRunning.Report
+                    };
+                    label.Summary.FormatString = item.DisplayFormat;
+                    label.Summary.Func = GetSummaryFunc(item.SummaryType);
+
+                    report.Bands[BandKind.ReportFooter].Controls.Add(label);
+
+                    if (CustomizeColumnSummary != null)
+                        CustomizeColumnSummary(report, new ColumnSummaryCreationEventArgs(col.FieldName, label.Summary));
+                }
+            }
+
+            private List<MVCxColumnInfo> GetColumnsInfo(MVCxGridViewState gridViewState, int pagewidth)
+            {
+                var columns = new List<MVCxColumnInfo>();
+                var visibleColumns = gridViewState.Columns;
+
+                foreach (var dataColumn in visibleColumns)
+                {
+                    MVCxColumnInfo column = new MVCxColumnInfo(dataColumn)
+                    {
+                        ColumnCaption = string.IsNullOrEmpty(dataColumn.Caption) ? dataColumn.FieldName : dataColumn.Caption,
+                        ColumnWidth = ((int)pagewidth / visibleColumns.Count),
+                        FieldName = dataColumn.FieldName,
+                        IsVisible = true
+                    };
+                    columns.Add(column);
+                }
+
+                return columns;
+            }
+
+            private SummaryFunc GetSummaryFunc(SummaryItemType summaryItemType)
+            {
+                switch (summaryItemType)
+                {
+                    case SummaryItemType.Sum:
+                        return SummaryFunc.Sum;
+                    case SummaryItemType.Average:
+                        return SummaryFunc.Avg;
+                    case SummaryItemType.Max:
+                        return SummaryFunc.Max;
+                    case SummaryItemType.Min:
+                        return SummaryFunc.Min;
+                    case SummaryItemType.Count:
+                        return SummaryFunc.Count;
+                    default:
+                        return SummaryFunc.Custom;
+                }
+            }
+
+            public void WritePdfToResponse(HttpResponseBase Response, string fileName, string type)
+            {
+                report.CreateDocument(false);
+                using (MemoryStream ms = new MemoryStream())
+                {
+                    report.ExportToPdf(ms);
+                    ms.Seek(0, SeekOrigin.Begin);
+                    WriteResponse(Response, ms.ToArray(), "application/pdf", type, fileName);
+                }
+            }
+
+            public void WriteXlsToResponse(HttpResponseBase Response, string fileName, string type)
+            {
+                report.CreateDocument(false);
+                using (MemoryStream ms = new MemoryStream())
+                {
+                    report.ExportToXls(ms);
+                    ms.Seek(0, SeekOrigin.Begin);
+                    WriteResponse(Response, ms.ToArray(), "application/vnd.ms-excel", type, fileName);
+                }
+            }
+
+            public void WriteXlsxToResponse(HttpResponseBase Response, string fileName, string type)
+            {
+                report.CreateDocument(false);
+                using (MemoryStream ms = new MemoryStream())
+                {
+                    report.ExportToXlsx(ms);
+                    ms.Seek(0, SeekOrigin.Begin);
+                    WriteResponse(Response, ms.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type, fileName);
+                }
+            }
+
+            public static void WriteResponse(HttpResponseBase response, byte[] filearray, string contentType, string type, string fileName)
+            {
+                response.ClearContent();
+                response.Buffer = true;
+                response.Cache.SetCacheability(HttpCacheability.Private);
+                response.ContentType = contentType;
+                ContentDisposition contentDisposition = new ContentDisposition();
+                contentDisposition.FileName = fileName;
+                contentDisposition.DispositionType = type;
+                response.AddHeader("Content-Disposition", contentDisposition.ToString());
+                response.BinaryWrite(filearray);
+                HttpContext.Current.ApplicationInstance.CompleteRequest();
+                try
+                {
+                    response.End();
+                }
+                catch (System.Threading.ThreadAbortException)
+                {
+
+                }
+            }
+        }
+
+        public class ControlCustomizationEventArgs : EventArgs
+        {
+            XRControl owner;
+
+            public XRControl Owner
+            {
+                get
+                {
+                    return owner;
+                }
+                set
+                {
+                    owner = value;
+                }
+            }
+
+            XRControl header;
+
+            public XRControl Header
+            {
+                get
+                {
+                    return header;
+                }
+                set
+                {
+                    header = value;
+                }
+            }
+
+            bool isModified;
+
+            public bool IsModified
+            {
+                get
+                {
+                    return isModified;
+                }
+                set
+                {
+                    isModified = value;
+                }
+            }
+
+            string fieldName;
+
+            public string FieldName
+            {
+                get
+                {
+                    return fieldName;
+                }
+                set
+                {
+                    fieldName = value;
+                }
+            }
+        }
+
+        public class ColumnSummaryCreationEventArgs : EventArgs
+        {
+            public ColumnSummaryCreationEventArgs(string fieldName, XRSummary summary)
+            {
+                this.fieldName = fieldName;
+                this.summary = summary;
+            }
+
+            XRSummary summary;
+
+            public XRSummary Summary
+            {
+                get
+                {
+                    return summary;
+                }
+                set
+                {
+                    summary = value;
+                }
+            }
+
+            string fieldName;
+
+            public string FieldName
+            {
+                get
+                {
+                    return fieldName;
+                }
+                set
+                {
+                    fieldName = value;
+                }
+            }
+        }
+
+        public class ColumnsCreationEventArgs : EventArgs
+        {
+            int pageWidth;
+            public int PageWidth
+            {
+                get
+                {
+                    return pageWidth;
+                }
+            }
+            public ColumnsCreationEventArgs(int pageWidth)
+            {
+                this.pageWidth = pageWidth;
+            }
+            List<MVCxColumnInfo> columnsInfo;
+
+            public List<MVCxColumnInfo> ColumnsInfo
+            {
+                get
+                {
+                    return columnsInfo;
+                }
+                set
+                {
+                    columnsInfo = value;
+                }
+            }
+        }
+
+        public class MVCxColumnInfo
+        {
+            public MVCxColumnInfo(GridViewDataColumnState gridViewColumn)
+            {
+                this.gridViewColumn = gridViewColumn;
+            }
+            GridViewDataColumnState gridViewColumn;
+
+            public GridViewDataColumnState GridViewColumn
+            {
+                get
+                {
+                    return gridViewColumn;
+                }
+            }
+
+
+            string columnCaption;
+            public string ColumnCaption
+            {
+                get
+                {
+                    return columnCaption;
+                }
+                set
+                {
+                    columnCaption = value;
+                }
+            }
+            string fieldName;
+
+            public string FieldName
+            {
+                get
+                {
+                    return fieldName;
+                }
+                set
+                {
+                    fieldName = value;
+                }
+            }
+            int columnWidth;
+
+            public int ColumnWidth
+            {
+                get
+                {
+                    return columnWidth;
+                }
+                set
+                {
+                    columnWidth = value;
+                }
+            }
+            bool isVisible;
+
+            public bool IsVisible
+            {
+                get
+                {
+                    return isVisible;
+                }
+                set
+                {
+                    isVisible = value;
+                }
+            }
+        }
+    }
+}

+ 154 - 0
GreenTree.Nachtragsmanagement.Web/Extensions/MVCxGridViewState.cs

@@ -0,0 +1,154 @@
+using DevExpress.Data;
+using DevExpress.Web;
+using DevExpress.Web.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace GreenTree.Nachtragsmanagement.Web.Extensions
+{
+    public class MVCxGridViewState
+    {
+        public MVCxGridViewState(MVCxGridView gridView)
+        {
+            Columns = new GridViewDataColumnStateCollection(gridView.VisibleColumns);
+            GroupedColumns = new GridViewDataColumnStateCollection(gridView.GetGroupedColumns());
+            TotalSummary = new System.Collections.ObjectModel.Collection<MVCxSummaryItemState>();
+
+            foreach (ASPxSummaryItem item in gridView.TotalSummary)
+            {
+                var column = Columns
+                    .FirstOrDefault(c => c.FieldName == item.FieldName);
+
+                if (column != null)
+                    TotalSummary.Add(new MVCxSummaryItemState(item));
+            }
+
+            FilterExpression = gridView.FilterExpression;
+        }
+
+        public GridViewDataColumnStateCollection Columns
+        {
+            get;
+            protected set;
+        }
+
+        public GridViewDataColumnStateCollection GroupedColumns
+        {
+            get;
+            protected set;
+        }
+
+        public System.Collections.ObjectModel.Collection<MVCxSummaryItemState> TotalSummary
+        {
+            get;
+            protected set;
+        }
+
+        public string FilterExpression
+        {
+            get;
+            protected set;
+        }
+    }
+
+    public class GridViewDataColumnState
+    {
+        public GridViewDataColumnState(GridViewDataColumn column)
+        {
+            Caption = column.Caption;
+            FieldName = column.FieldName;
+            SortOrder = column.SortOrder;
+            DisplayFormat = column.PropertiesEdit.DisplayFormatString;
+        }
+
+        public string Caption
+        {
+            get;
+            protected set;
+        }
+
+        public string FieldName
+        {
+            get;
+            protected set;
+        }
+
+        public string DisplayFormat
+        {
+            get;
+            protected set;
+        }
+
+        public ColumnSortOrder SortOrder
+        {
+            get;
+            protected set;
+        }
+    }
+
+    public class GridViewDataColumnStateCollection : System.Collections.ObjectModel.Collection<GridViewDataColumnState>
+    {
+        public GridViewDataColumnStateCollection(ICollection<GridViewColumn> columns)
+        {
+            foreach (GridViewColumn col in columns)
+            {
+                var dataCol = col as GridViewDataColumn;
+
+                if (dataCol != null)
+                {
+                    this.Add(new GridViewDataColumnState(dataCol));
+                }
+            }
+        }
+
+        public GridViewDataColumnStateCollection(ICollection<GridViewDataColumn> columns)
+        {
+            foreach (GridViewDataColumn col in columns)
+            {
+                this.Add(new GridViewDataColumnState(col));
+            }
+        }
+
+        public GridViewDataColumnState this[string fieldName]
+        {
+            get
+            {
+                return this.Single((item) => item.FieldName == fieldName);
+            }
+        }
+    }
+
+    public class MVCxSummaryItemState
+    {
+        public MVCxSummaryItemState(ASPxSummaryItem item)
+        {
+            FieldName = item.FieldName;
+            ShowInColumn = item.ShowInColumn;
+            DisplayFormat = item.DisplayFormat;
+            SummaryType = item.SummaryType;
+        }
+
+        public string FieldName
+        {
+            get;
+            protected set;
+        }
+        public string ShowInColumn
+        {
+            get;
+            protected set;
+        }
+        public string DisplayFormat
+        {
+            get;
+            protected set;
+        }
+        public SummaryItemType SummaryType
+        {
+            get;
+            protected set;
+        }
+    }
+}

+ 31 - 13
GreenTree.Nachtragsmanagement.Web/Global.asax.cs

@@ -661,16 +661,7 @@ namespace GreenTree.Nachtragsmanagement.Web
                         TypeFullName = "System.Int32",
                         Value = "56",
                         Description =
-                            "Die Anzahl der Tage ab dem Verhandlungstermin eines Nachtrags, damit er bei der Überprüfung des " +
-                            "Verhandlungsdatums mit berücksichtigt werden soll"
-                    },
-                    new ConfigItem
-                    {
-                        Name = "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.StateCondition",
-                        TypeFullName = "System.Int32",
-                        Value = states[0].Id.ToString(),
-                        Description =
-                            "Die ID des Nachtragsstatus, den ein Nachtrag haben muss, damit er bei der Überprüfung des " +
+                            "Die Anzahl der Tage ab dem Angebotstermin eines Nachtrags, damit er bei der Überprüfung des " +
                             "Verhandlungsdatums mit berücksichtigt werden soll"
                     },
                     new ConfigItem
@@ -695,19 +686,46 @@ namespace GreenTree.Nachtragsmanagement.Web
                     {
                         Name = "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.AgeDays",
                         TypeFullName = "System.Int32",
-                        Value = "14"
+                        Value = "14",
+                        Description =
+                            "Die Anzahl der Tage ab dem Verhandlungstermin eines Nachtrags, damit er bei der Überprüfung des " +
+                            "Protokolls mit berücksichtigt werden soll"
                     },
                     new ConfigItem
                     {
                         Name = "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.StateCondition",
                         TypeFullName = "System.Int32",
-                        Value = states[2].Id.ToString()
+                        Value = states[2].Id.ToString(),
+                        Description =
+                            "Die ID des Nachtragsstatus, den ein Nachtrag haben muss, damit er bei der Überprüfung des " +
+                            "Verhandlungsprotokolls mit berücksichtigt werden soll"
                     },
                     new ConfigItem
                     {
                         Name = "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.Interval",
                         TypeFullName = "System.Int32",
-                        Value = "2"
+                        Value = "2",
+                        Description =
+                            "Der Wocheninterval, in dem weitere Benachrichtigungen über die Nachträge ohne Protokoll gesendet werden " +
+                            "soll"
+                    },
+                    new ConfigItem
+                    {
+                        Name = "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.AgeDaysLevel1",
+                        TypeFullName = "System.Int32",
+                        Value = "40",
+                        Description =
+                            "Die Anzahl der Tage ab dem Einreichungsdatum einer Vertragsabweichung, die bei der Überprüfung der " +
+                            "Zuordnung eines Nachtrags, erreicht sein muss (Stufe 1)"
+                    },
+                    new ConfigItem
+                    {
+                        Name = "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.AgeDaysLevel2",
+                        TypeFullName = "System.Int32",
+                        Value = "60",
+                        Description =
+                            "Die Anzahl der Tage ab dem Einreichungsdatum einer Vertragsabweichung, die bei der Überprüfung der " +
+                            "Zuordnung eines Nachtrags, erreicht sein muss (Stufe 2)"
                     },
                 };
 

+ 18 - 0
GreenTree.Nachtragsmanagement.Web/GreenTree.Nachtragsmanagement.Web.csproj

@@ -61,6 +61,7 @@
     <Reference Include="CronExpressionDescriptor, Version=2.0.2.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\CronExpressionDescriptor.2.0.2\lib\netstandard1.1\CronExpressionDescriptor.dll</HintPath>
     </Reference>
+    <Reference Include="DevExpress.RichEdit.v17.1.Export, Version=17.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
     <Reference Include="DevExpress.XtraScheduler.v17.1.Core, Version=17.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
     <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
       <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
@@ -327,6 +328,11 @@
     <Content Include="Views\Admin\Plugins\_PluginsGridPartial.cshtml" />
     <Content Include="Views\Config\View.cshtml" />
     <Content Include="Views\Config\_ConfigItemGridPartial.cshtml" />
+    <Content Include="Views\Config\_ConfigItemValueEditPartial.cshtml" />
+    <Content Include="Views\Config\_ConfigItemEditPartial.cshtml" />
+    <Content Include="Views\Shared\_PrintPopupPartial.cshtml" />
+    <Content Include="Views\Shared\_PrintDocumentViewerPartial.cshtml" />
+    <Content Include="Views\Shared\SaveDocumentViewer.cshtml" />
     <None Include="Web.Debug.config">
       <DependentUpon>Web.config</DependentUpon>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -344,9 +350,12 @@
     <Compile Include="App_Start\WebApiConfig.cs" />
     <Compile Include="Controllers\MiscController.cs" />
     <Compile Include="Extensions\ControlHelper.cs" />
+    <Compile Include="Extensions\MVCxGridViewGeneratorHelper.cs" />
+    <Compile Include="Extensions\MVCxGridViewState.cs" />
     <Compile Include="Models\Admin\Plugins\PluginDataModel.cs" />
     <Compile Include="Models\Config\ConfigItemDataModel.cs" />
     <Compile Include="Models\Global\EditEntityCommentModel.cs" />
+    <Compile Include="Models\Global\PrintGridModel.cs" />
     <Compile Include="Models\Misc\LogDataModel.cs" />
     <Compile Include="Models\Misc\MailNotificationDataModel.cs" />
     <Compile Include="Implementations\DeviationNotificationPlugin.cs" />
@@ -388,6 +397,12 @@
     <Compile Include="Models\Global\OptionDialogModel.cs" />
     <Compile Include="Models\Site\SiteDataModel.cs" />
     <Compile Include="Models\Site\SiteTreeDataModel.cs" />
+    <Compile Include="Reports\XtraReportGridView.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Reports\XtraReportGridView.Designer.cs">
+      <DependentUpon>XtraReportGridView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Validation\Admin\User\RoleDataModelValidator.cs" />
     <Compile Include="Validation\Admin\User\UserDataModelValidator.cs" />
     <Compile Include="Models\Global\FooterModel.cs" />
@@ -437,6 +452,9 @@
   <ItemGroup>
     <Service Include="{4A0DDDB5-7A95-4FBF-97CC-616D07737A77}" />
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\licenses.licx" />
+  </ItemGroup>
   <PropertyGroup>
     <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
     <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

+ 0 - 3
GreenTree.Nachtragsmanagement.Web/Implementations/AppendixNotificationPlugin.cs

@@ -182,9 +182,6 @@ namespace GreenTree.Nachtragsmanagement.Web.Implementations
             var ageDays = _configurationService.TryGetConfigItemValue<int>(
                 "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.AgeDays", 56);
 
-            var stateConditionId = _configurationService.TryGetConfigItemValue<int>(
-                "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.StateCondition", 1);
-
             var stateSetId = _configurationService.TryGetConfigItemValue<int>(
                 "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.StateSet", 2);
 

+ 6 - 4
GreenTree.Nachtragsmanagement.Web/Implementations/DeviationNotificationPlugin.cs

@@ -232,8 +232,9 @@ namespace GreenTree.Nachtragsmanagement.Web.Implementations
                     templateLevel1List += String.Format(
                         "<li>Vertragsabweichung <b>\"{0}\"</b> " +
                         "in Baustelle <b>\"{1}\"</b> - " +
-                        "Einreichdatum: <b>{2:dd.MM.yyyy}</b>",
-                        deviation.CustomNumber, deviation.Site.CustomNumber, deviation.ReceiptDate);
+                        "Einreichdatum: <b>{2:dd.MM.yyyy} ({3} Tage)</b>",
+                        deviation.CustomNumber, deviation.Site.CustomNumber, deviation.ReceiptDate,
+                        (DateTime.Now - deviation.ReceiptDate).Value.Days);
                 }
             }
 
@@ -255,8 +256,9 @@ namespace GreenTree.Nachtragsmanagement.Web.Implementations
                     templateLevel2List += String.Format(
                         "<li>Vertragsabweichung <b>\"{0}\"</b> " +
                         "in Baustelle <b>\"{1}\"</b> - " +
-                        "Einreichdatum: <b>{2:dd.MM.yyyy}</b>",
-                        deviation.CustomNumber, deviation.Site.CustomNumber, deviation.ReceiptDate);
+                        "Einreichdatum: <b>{2:dd.MM.yyyy} ({3} Tage)</b>",
+                        deviation.CustomNumber, deviation.Site.CustomNumber, deviation.ReceiptDate,
+                        (DateTime.Now - deviation.ReceiptDate).Value.Days);
                 }
             }
 

+ 2 - 0
GreenTree.Nachtragsmanagement.Web/Models/Config/ConfigItemDataModel.cs

@@ -38,6 +38,7 @@ namespace GreenTree.Nachtragsmanagement.Web.Models.Config
             return new ConfigItemDataModel
             {
                 Id = configItemEntity.Id,
+                Name = configItemEntity.Name,
                 TypeFullName = configItemEntity.TypeFullName,
                 TypeDescription = FullTypeTranslations[configItemEntity.TypeFullName],
                 Value = configItemEntity.Value,
@@ -50,6 +51,7 @@ namespace GreenTree.Nachtragsmanagement.Web.Models.Config
             return new Core.Domain.Config.ConfigItem
             {
                 Id = this.Id,
+                Name = this.Name,
                 TypeFullName = this.TypeFullName,
                 Value = this.Value,
                 Description = this.Description

+ 13 - 0
GreenTree.Nachtragsmanagement.Web/Models/Global/PrintGridModel.cs

@@ -0,0 +1,13 @@
+using DevExpress.XtraReports.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace GreenTree.Nachtragsmanagement.Web.Models.Global
+{
+    public class PrintGridModel
+    {
+        public XtraReport Report { get; set; }
+    }
+}

+ 1 - 0
GreenTree.Nachtragsmanagement.Web/Properties/licenses.licx

@@ -0,0 +1 @@
+DevExpress.XtraReports.UI.XtraReport, DevExpress.XtraReports.v17.1, Version=17.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a

+ 51 - 0
GreenTree.Nachtragsmanagement.Web/Reports/XtraReportGridView.Designer.cs

@@ -0,0 +1,51 @@
+namespace GreenTree.Nachtragsmanagement.Web.Reports
+{
+    partial class XtraReportGridView
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+            this.Detail = new DevExpress.XtraReports.UI.DetailBand();
+            this.TopMargin = new DevExpress.XtraReports.UI.TopMarginBand();
+            this.BottomMargin = new DevExpress.XtraReports.UI.BottomMarginBand();
+            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
+            this.TopMargin.Height = 100;
+            this.BottomMargin.Height = 100;
+            this.Bands.AddRange(new DevExpress.XtraReports.UI.Band[] {
+            this.Detail,
+            this.TopMargin,
+            this.BottomMargin});
+            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
+        }
+
+        #endregion
+
+        private DevExpress.XtraReports.UI.DetailBand Detail;
+        private DevExpress.XtraReports.UI.TopMarginBand TopMargin;
+        private DevExpress.XtraReports.UI.BottomMarginBand BottomMargin;
+    }
+}

+ 18 - 0
GreenTree.Nachtragsmanagement.Web/Reports/XtraReportGridView.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using DevExpress.XtraReports.UI;
+using System.Data;
+using System.Web.UI.WebControls;
+
+namespace GreenTree.Nachtragsmanagement.Web.Reports
+{
+    public partial class XtraReportGridView : DevExpress.XtraReports.UI.XtraReport
+    {
+        public XtraReportGridView()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 10 - 12
GreenTree.Nachtragsmanagement.Web/Views/Appendices/View.cshtml

@@ -38,9 +38,16 @@
 
 	function onToolbarItemClick(s, e) {
 		if (!s || !e) return;
-		if (IsExportToolbarCommand(e.item.name)) {
-			$("#Format").val(e.item.name);
-			$("#appendixExportForm").submit();
+		if (e.item.name == "Print") {
+			parent.$(".printPopupContainer").remove();
+			$.ajax({
+				type: "POST",
+				url: '@Url.Action("ExportPartialAppendices", "Appendix")',
+				data: { displayMode: "popup", exportFormat: "" },
+				success: function (response) {
+					parent.$("body").append(response);
+				}
+			});
 		} else if (e.item.name == "ToggleColumnChooser") {
 			if (devGridViewAppendix.IsCustomizationWindowVisible())
 				devGridViewAppendix.HideCustomizationWindow();
@@ -49,10 +56,6 @@
 		}
 	}
 
-	function IsExportToolbarCommand(command) {
-		return command == "Pdf" || command == "Xlsx" || command == "Xls";
-	}
-
 	function editAppendix(id) {
 		if (!id) return;
 		$.ajax({
@@ -107,11 +110,6 @@
 	}
 </script>
 
-@using (Html.BeginForm("ExportPartialAppendices", "Appendix", FormMethod.Post, new { id = "appendixExportForm" }))
-{
-	@Html.Hidden("Format")
-}
-
 @Html.Partial("~/Views/Appendices/_AppendixGridPartial.cshtml", Model)
 @Html.Partial("~/Views/Shared/_PopupDialogYesNo.cshtml", new GreenTree.Nachtragsmanagement.Web.Models.Global.YesNoDialogModel
 {

+ 26 - 19
GreenTree.Nachtragsmanagement.Web/Views/Config/View.cshtml

@@ -7,7 +7,7 @@
 <script>
 	var deleteId;
 	var gridScrollHeight;
-	var gridScrollOffset = 240;
+	var gridScrollOffset = 130;
 	var resizeFinished;
 
 	$(document).ready(function () {
@@ -36,21 +36,11 @@
 		devGridViewConfigItem.PerformCallback();
 	}
 
-	function onToolbarItemClick(s, e) {
-		if (!s || !e) return;
-		if (IsExportToolbarCommand(e.item.name)) {
-			$("#Format").val(e.item.name);
-			$("#configItemExportForm").submit();
-		} else if (e.item.name == "ToggleColumnChooser") {
-			if (devGridViewConfigItem.IsCustomizationWindowVisible())
-				devGridViewConfigItem.HideCustomizationWindow();
-			else
-				devGridViewConfigItem.ShowCustomizationWindow();
-		}
-	}
-
-	function IsExportToolbarCommand(command) {
-		return command == "Pdf" || command == "Xlsx" || command == "Xls";
+	function showFullName(text, element) {
+		if (!element) return;
+		devPopupControlFullName.Hide();
+		$("#fullNameContent").text(text);
+		devPopupControlFullName.ShowAtElement(element);
 	}
 
 	function editConfigItem(id) {
@@ -62,6 +52,9 @@
 				setTimeout(function () {
 					$(".configItemEditContainer").remove();
 					$("body").append(response);
+					parent.addCustomEventListener("ConfigItemDataCallbackEventReceiver", function () {
+						devGridViewConfigItem.PerformCallback();
+					});
 				}, 200);
 			},
 			error: function () {
@@ -81,8 +74,8 @@
 				if (response == "notFound") return;
 				var configItem = JSON.parse(response);
 				var popupControl = MVCxClientPopupControl.Cast(devPopupControlDeleteConfigItem);
-				popupControl.SetHeaderText(popupControl.GetHeaderText().replace("{configItem}", configItem.NotificationPluginSystemNameDescription));
-				$(".dialogTextConfigItem").text($(".dialogTextConfigItem").text().replace("{configItem}", configItem.NotificationPluginSystemNameDescription));
+				popupControl.SetHeaderText(popupControl.GetHeaderText().replace("{configItem}", configItem.Name));
+				$(".dialogTextConfigItem").text($(".dialogTextConfigItem").text().replace("{configItem}", configItem.Name));
 				popupControl.Show();
 			}
 		});
@@ -118,4 +111,18 @@
 	YesFunction = "function (s, e) { deleteConfigItem(); }",
 	YesButtonName = "devButtonDeleteConfigItemYes",
 	NoButtonName = "devButtonDeleteConfigItemNo"
-})
+})
+
+@Html.DevExpress().PopupControl(p =>
+{
+	p.Name = "devPopupControlFullName";
+	p.ShowHeader = false;
+	p.ShowFooter = false;
+	p.ShowShadow = false;
+	p.PopupAnimationType = AnimationType.None;
+	p.Width = new Unit(300, UnitType.Pixel);
+	p.SetContent("<div id=\"fullNameContent\"></div>");
+	p.CloseAction = CloseAction.OuterMouseClick;
+	p.PopupHorizontalAlign = PopupHorizontalAlign.LeftSides;
+	p.PopupVerticalAlign = PopupVerticalAlign.Below;
+}).GetHtml()

+ 123 - 0
GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemEditPartial.cshtml

@@ -0,0 +1,123 @@
+@using GreenTree.Nachtragsmanagement.Web.Extensions
+
+@model GreenTree.Nachtragsmanagement.Web.Models.Config.ConfigItemDataModel
+
+<div class="configItemEditContainer">
+
+	<script>
+		function saveConfigItem() {
+			var form = $("#configItemEditForm");
+			$(form).submit(function (e) {
+				$.ajax({
+					type: "POST",
+					url: '@Url.Action("EditConfigItem", "Misc")',
+					data: form.serialize(),
+					success: function (response) {
+						setTimeout(function () {
+							$(".configItemEditContainer").remove();
+							if (response == "success") {
+								parent.callCustomEventListener('ConfigItemDataCallbackEventReceiver');
+							} else {
+								$("body").append(response);
+							}
+						}, 200);
+					}
+				});
+				e.preventDefault();
+			});
+			form.submit();
+		}
+
+		function getValueTypePartialEdit() {
+			$.ajax({
+				type: "GET",
+				url: '@Url.Action("GetValueTypePartialEdit", "Misc")',
+				data: { typeFullName: TypeFullName.GetValue() },
+				success: function (response) {
+					$(".configItemValueEdit").replaceWith(response);
+				}
+			});
+		}
+	</script>
+
+	@Html.DevExpress().PopupControl(s =>
+{
+	s.Name = "devPopupControlEditConfigItem";
+
+	if (Model.Id == -1)
+		s.HeaderText = "Neue Einstellung erstellen";
+	else
+	{
+		if (Model.Name.Length > 40)
+			s.HeaderText = "\"" + Model.Name.Substring(0, 15) + " ... " + Model.Name.Substring(Model.Name.Length - 15, 15) + "\" bearbeiten";
+	}
+
+	s.Modal = true;
+	s.Width = new Unit(500, UnitType.Pixel);
+	s.CloseAction = CloseAction.CloseButton;
+	s.PopupHorizontalAlign = PopupHorizontalAlign.WindowCenter;
+	s.PopupVerticalAlign = PopupVerticalAlign.TopSides;
+	s.PopupVerticalOffset = 20;
+	s.AllowDragging = false;
+	s.AllowResize = false;
+	s.ShowFooter = false;
+	s.ShowOnPageLoad = true;
+	s.SetContent(() =>
+	{
+		using (Html.BeginForm("EditConfigItem", "Deviation", FormMethod.Post, new { id = "configItemEditForm" }))
+		{
+			ViewContext.Writer.Write("<div class='editFormWrapper'>");
+
+			ViewContext.Writer.Write("<input type=\"hidden\" value=\"" + Model.Id + "\" id=\"Id\" name=\"Id\" />");
+
+			ViewContext.Writer.Write(Html.CustomLabelFor(m => m.Name, "Name:"));
+			ViewContext.Writer.Write(Html.ValidationMessageFor(m => m.Name).ToHtmlString());
+			Html.DevExpress().TextBoxFor(m => m.Name, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+			}).Render();
+
+			ViewContext.Writer.Write(Html.CustomLabelFor(m => m.TypeFullName, "Datentyp:"));
+			ViewContext.Writer.Write(Html.ValidationMessageFor(m => m.TypeFullName).ToHtmlString());
+			Html.DevExpress().ComboBoxFor(m => m.TypeFullName, t =>
+			{
+				t.Width = new Unit(60, UnitType.Percentage);
+				t.Properties.Items.AddRange(
+					GreenTree.Nachtragsmanagement.Web.Models.Config.ConfigItemDataModel.FullTypeTranslations
+						.Select(f => new ListEditItem(f.Value, f.Key))
+						.ToList());
+				t.Properties.ClientSideEvents.SelectedIndexChanged = "function (s, e) { getValueTypePartialEdit(); }";
+			}).Render();
+
+			ViewContext.Writer.Write("<div class=\"configItemEditContainerPlaceholder\">");
+			{
+				ViewContext.Writer.Write(Html.CustomLabelFor(m => m.Value, "Wert:"));
+				ViewContext.Writer.Write(Html.ValidationMessageFor(m => m.Value).ToHtmlString());
+				Html.RenderPartial("~/Views/Config/_ConfigItemValueEditPartial.cshtml", Model);
+			}
+			ViewContext.Writer.Write("</div>");
+
+			ViewContext.Writer.Write(Html.CustomLabelFor(m => m.Description, "Beschreibung:"));
+			ViewContext.Writer.Write(Html.ValidationMessageFor(m => m.Description).ToHtmlString());
+			Html.DevExpress().MemoFor(m => m.Description, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+				t.Height = new Unit(80, UnitType.Pixel);
+			}).Render();
+
+			ViewContext.Writer.Write("</div>");
+
+			Html.RenderPartial(
+				"~/Views/Shared/_PopupButtonPanel.cshtml",
+				new GreenTree.Nachtragsmanagement.Web.Models.Global.PopupModel
+				{
+					PopupName = "devPopupControlEditConfigItem",
+					AcceptFunction = "function (s, e) { saveConfigItem(); }"
+				}
+			);
+		}
+	});
+	s.Styles.Content.Paddings.Padding = new Unit(0);
+	s.Styles.ModalBackground.Opacity = 0;
+}).GetHtml()
+</div>

+ 22 - 7
GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemGridPartial.cshtml

@@ -40,36 +40,51 @@
 			});
 			column.Settings.AllowDragDrop = DefaultBoolean.False;
 			column.Settings.AllowSort = DefaultBoolean.False;
-			column.Width = new Unit(120, UnitType.Pixel);
+			column.Width = new Unit(150, UnitType.Pixel);
 		});
 	}
 	s.Columns.Add(column =>
 	{
 		column.Caption = "Name";
 		column.FieldName = "Name";
-		column.MinWidth = 120;
-		column.Width = new Unit(10, UnitType.Percentage);
+		column.MinWidth = 220;
+		column.Width = new Unit(20, UnitType.Percentage);
+		column.SetDataItemTemplateContent(c =>
+		{
+			var name = DataBinder.Eval(c.DataItem, "Name").ToString();
+
+			if (String.IsNullOrEmpty(name))
+				ViewContext.Writer.Write(String.Empty);
+			else
+			{
+				if (name.Length > 25)
+					ViewContext.Writer.Write(
+						"<a href=\"#\" onmouseover='showFullName(\"" + name + "\",this)'>" + name.Substring(0, 25) + " ...</a>");
+				else
+					ViewContext.Writer.Write(name);
+			}
+		});
 	});
 	s.Columns.Add(column =>
 	{
 		column.Caption = "Datentyp";
 		column.FieldName = "TypeDescription";
-		column.MinWidth = 80;
+		column.MinWidth = 100;
 		column.Width = new Unit(15, UnitType.Percentage);
 	});
 	s.Columns.Add(column =>
 	{
 		column.Caption = "Wert";
 		column.FieldName = "Value";
-		column.MinWidth = 150;
-		column.Width = new Unit(30, UnitType.Percentage);
+		column.MinWidth = 120;
+		column.Width = new Unit(15, UnitType.Percentage);
 	});
 	s.Columns.Add(column =>
 	{
 		column.Caption = "Beschreibung";
 		column.FieldName = "Description";
 		column.MinWidth = 300;
-		column.Width = new Unit(45, UnitType.Percentage);
+		column.Width = new Unit(40, UnitType.Percentage);
 	});
 
 	s.ClientLayout = (sender, e) =>

+ 83 - 0
GreenTree.Nachtragsmanagement.Web/Views/Config/_ConfigItemValueEditPartial.cshtml

@@ -0,0 +1,83 @@
+@using GreenTree.Nachtragsmanagement.Web.Extensions
+
+@model GreenTree.Nachtragsmanagement.Web.Models.Config.ConfigItemDataModel
+
+<div class="configItemValueEdit">
+
+	@switch (Model.TypeFullName)
+	{
+		case "System.Int32":
+			Html.DevExpress().SpinEditFor(m => m.Value, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+				t.Properties.MinValue = Int32.MinValue;
+				t.Properties.MaxValue = Int32.MaxValue;
+			}).GetHtml();
+			break;
+		case "System.Int64":
+			Html.DevExpress().SpinEditFor(m => m.Value, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+				t.Properties.MinValue = Int64.MinValue;
+				t.Properties.MaxValue = Int64.MaxValue;
+			}).GetHtml();
+			break;
+		case "System.Boolean":
+			ViewContext.Writer.Write("<div class='inlineModelPropertyContainer'>");
+			{
+				ViewContext.Writer.Write("<div class='inlineModelProperty' style='width: 100%'>");
+				{
+					ViewContext.Writer.Write("<div style=\"overflow: hidden\">");
+					{
+						ViewContext.Writer.Write("<div style=\"float: left\">");
+						{
+							Html.DevExpress().RadioButtonFor(m => m.Value, t =>
+							{
+								t.Text = "Ja";
+								t.GroupName = "isDefault";
+							}).Render();
+						}
+						ViewContext.Writer.Write("</div>");
+
+						ViewContext.Writer.Write("<div style=\"float: left; margin-left: 8px\">");
+						{
+							Html.DevExpress().RadioButton(t =>
+							{
+								t.Name = "isDefaultFalse";
+								t.Text = "Nein";
+								t.GroupName = "isDefault";
+								t.Checked = !Convert.ToBoolean(Model.Value);
+							}).Render();
+						}
+						ViewContext.Writer.Write("</div>");
+					}
+					ViewContext.Writer.Write("</div>");
+				}
+				ViewContext.Writer.Write("</div>");
+			}
+			ViewContext.Writer.Write("</div>");
+			break;
+		case "System.Double":
+			Html.DevExpress().SpinEditFor(m => m.Value, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+				t.Properties.NumberType = SpinEditNumberType.Float;
+				t.Properties.MinValue = Decimal.MinValue;
+				t.Properties.MaxValue = Decimal.MaxValue;
+			}).GetHtml();
+			break;
+		case "System.DateTime":
+			Html.DevExpress().DateEditFor(m => m.Value, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+			}).GetHtml();
+			break;
+		default:
+			Html.DevExpress().TextBoxFor(m => m.Value, t =>
+			{
+				t.Width = new Unit(100, UnitType.Percentage);
+			}).GetHtml();
+			break;
+	}
+
+</div>

+ 10 - 0
GreenTree.Nachtragsmanagement.Web/Views/Home/Index.cshtml

@@ -31,6 +31,8 @@
 
 	var eventListeners = [];
 
+	var exportFormat = "pdf";
+
 	@foreach (var g in Model.AvailableFunctions)
 	{
 		foreach (var i in g.Value)
@@ -245,6 +247,14 @@
 		}
 		event.stopPropagation();
 	}
+
+	function customizeExportToolbar(baseName) {
+		var controls = ASPxClientControl.GetControlCollection();
+		var formatComboBox = ASPxClientComboBox.Cast(controls.GetByName(baseName + "_Splitter_Toolbar_Menu_ITCNT11_SaveFormat"));
+		formatComboBox.SelectedIndexChanged.AddHandler(function (s, e) {
+			exportFormat = s.GetValue();
+		});
+	}
 </script>
 
 	@foreach (var g in Model.AvailableFunctions)

+ 47 - 0
GreenTree.Nachtragsmanagement.Web/Views/Shared/SaveDocumentViewer.cshtml

@@ -0,0 +1,47 @@
+@model GreenTree.Nachtragsmanagement.Web.Models.Global.PrintGridModel
+
+<head>
+
+	@Html.DevExpress().GetStyleSheets(
+		new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
+		new StyleSheet { ExtensionSuite = ExtensionSuite.Editors },
+		new StyleSheet { ExtensionSuite = ExtensionSuite.Report },
+		new StyleSheet { ExtensionSuite = ExtensionSuite.GridView },
+		new StyleSheet { ExtensionSuite = ExtensionSuite.TreeList }
+	)
+	@Html.DevExpress().GetScripts(
+		new Script { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
+		new Script { ExtensionSuite = ExtensionSuite.Editors },
+		new Script { ExtensionSuite = ExtensionSuite.Report },
+		new Script { ExtensionSuite = ExtensionSuite.GridView },
+		new Script { ExtensionSuite = ExtensionSuite.TreeList }
+	)
+
+	<link rel="stylesheet" type="text/css" href="~/Content/global.css" />
+	<link rel="stylesheet" type="text/css" href="~/Content/devex.css" />
+	<link rel="stylesheet" type="text/css" href="~/Content/function.css" />
+
+</head>
+
+<body>
+
+	@Html.DevExpress().DocumentViewer(t =>
+	{
+		t.Name = "devDocumentViewerReportGrid";
+		t.Width = new Unit(100, UnitType.Percentage);
+		t.Report = Model.Report;
+		t.CallbackRouteValues = new
+		{
+			Action = "ExportPartialAppendicesCallback",
+			Controller = "Appendix",
+			exportformatString = "Pdf"
+		};
+		t.ExportRouteValues = new
+		{
+			Action = "SavePartialAppendicesCallback",
+			Controller = "Appendix",
+			exportformatString = "Pdf"
+		};
+	}).GetHtml()
+
+</body>

+ 25 - 0
GreenTree.Nachtragsmanagement.Web/Views/Shared/_PrintDocumentViewerPartial.cshtml

@@ -0,0 +1,25 @@
+@model GreenTree.Nachtragsmanagement.Web.Models.Global.PrintGridModel
+
+@Html.DevExpress().DocumentViewer(t =>
+{
+	t.Name = "devDocumentViewerReportGrid";
+	t.Width = new Unit(100, UnitType.Percentage);
+	t.Report = Model.Report;
+	t.CallbackRouteValues = new
+	{
+		Action = "ExportPartialAppendices",
+		Controller = "Appendix",
+		displayMode = "callback",
+		exportformat = String.Empty
+	};
+	t.ExportRouteValues = new
+	{
+		Action = "ExportPartialAppendices",
+		Controller = "Appendix",
+		displayMode = "export"
+	};
+	t.ToolbarMode = DocumentViewerToolbarMode.StandardToolbar;
+	t.ClientSideEvents.Init = "function (s, e) { customizeExportToolbar('devDocumentViewerReportGrid'); }";
+	t.ClientSideEvents.ToolbarItemClick = "function (s, e) { console.log(e); }";
+	t.ClientSideEvents.BeforeExportRequest = "function (s, e) { e.customArgs['exportFormat'] = exportFormat; }";
+}).GetHtml()

+ 32 - 0
GreenTree.Nachtragsmanagement.Web/Views/Shared/_PrintPopupPartial.cshtml

@@ -0,0 +1,32 @@
+@model GreenTree.Nachtragsmanagement.Web.Models.Global.PrintGridModel
+
+<div class="printPopupContainer">
+
+	<script>
+
+		var selectedExportFormat = "";
+
+	</script>
+
+	@Html.DevExpress().PopupControl(s =>
+{
+	s.Name = "devPopupControlEditSite";
+	s.HeaderText = "";
+	s.Modal = true;
+	s.Width = new Unit(1100, UnitType.Pixel);
+	s.CloseAction = CloseAction.CloseButton;
+	s.PopupHorizontalAlign = PopupHorizontalAlign.WindowCenter;
+	s.PopupVerticalAlign = PopupVerticalAlign.TopSides;
+	s.PopupVerticalOffset = 10;
+	s.AllowDragging = true;
+	s.AllowResize = false;
+	s.ShowMaximizeButton = true;
+	s.ShowFooter = false;
+	s.ShowOnPageLoad = true;
+	s.SetContent(() =>
+	{
+		Html.RenderPartial("~/Views/Shared/_PrintDocumentViewerPartial.cshtml", Model);
+	});
+}).GetHtml()
+
+</div>

+ 1 - 1
GreenTree.Nachtragsmanagement.Web/Views/Sites/_SiteEditPartial.cshtml

@@ -324,7 +324,7 @@
 		.siteEditLayoutTable > tbody > tr > td { width: 50%; padding-right: 8px; vertical-align: top }
 	</style>
 
-	@Html.DevExpress().PopupControl(s =>
+@Html.DevExpress().PopupControl(s =>
 {
 	s.Name = "devPopupControlEditSite";