Commits (4)
using pEp.DPE.Interfaces;
using pEp.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace pEp.DPE
{
internal class DistributedPolicyEngine : IDistributedPolicyEngine
{
private readonly static string DPE_FOLDER = Path.Combine(Globals.PEPUserFolder, "DPE");
private readonly static string PATCH_EXTENSION = ".patch";
private readonly static string DPE_FOLDER = Path.Combine(Globals.PEPUserFolder, "DPE");
public readonly static string DPE_BACKUP_LOCATION = Path.Combine(DistributedPolicyEngine.DPE_FOLDER, "temp");
private const string PATCH_EXTENSION = ".patch";
private const string PATCH_MESSAGE_SUBJECT = "Configuration changes";
public const string DPE_MESSAGE_CLASS = "IPM.Note.DPE";
private readonly PEPIdentity ownIdentity;
private readonly PatchEvents patchEvents;
/// <summary>
......@@ -19,16 +26,17 @@ namespace pEp.DPE
{
this.patchEvents = new PatchEvents();
this.Subscribe(this.patchEvents);
this.ownIdentity = new PEPIdentity(Globals.ThisAddIn.Settings.AccountSettingsList.First().SmtpAddress);
}
#region Event handlers
/// <summary>
/// Event handler for when a patch has been accepted.
/// </summary>
private void PatchEvents_PatchAccepted(object sender, PatchEventArgs e)
{
ThisAddIn.PEPEngine.ShowNotification("pEp Distributed Policy Engine", $"Patch with id {e.Patch.Id} was accepted.");
ThisAddIn.PEPEngine.ShowNotification("pEp Distributed Policy Engine", $"Patch with id { e.Patch.Id } was accepted.");
}
/// <summary>
......@@ -36,7 +44,7 @@ namespace pEp.DPE
/// </summary>
private void PatchEvents_PatchRejected(object sender, PatchEventArgs e)
{
ThisAddIn.PEPEngine.ShowNotification("pEp Distributed Policy Engine", $"Patch with id {e.Patch.Id} was rejected.");
ThisAddIn.PEPEngine.ShowNotification("pEp Distributed Policy Engine", $"Patch with id { e.Patch.Id } was rejected.");
}
/// <summary>
......@@ -46,10 +54,58 @@ namespace pEp.DPE
{
// Save the patch and show a notification
Patch patch = e.Patch;
this.SavePatch(patch);
this.CreatePatchMailItem(patch, e.Submitter);
ThisAddIn.PEPEngine.ShowNotification("New patch suggested", patch.CommitMessage + " " + patch.Diff);
}
/// <summary>
/// Creates a mail item that shows a suggested patch.
/// </summary>
/// <param name="patch">The patch to show.</param>
/// <param name="submitter">The submitter of the patch.</param>
private void CreatePatchMailItem(Patch patch, PEPIdentity submitter)
{
Outlook.MailItem omi = null;
Outlook.MailItem mi = null;
try
{
// Use a PEPMessage to define the message to create
PEPMessage patchMessage = new PEPMessage
{
From = submitter,
LongMsgFormattedHtml = patch.Serialize(),
ShortMsg = DistributedPolicyEngine.PATCH_MESSAGE_SUBJECT,
};
patchMessage.To.Add(this.ownIdentity);
// Create the mail item and apply the PEPMessage
omi = Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
patchMessage.ApplyTo(omi, false, true, true);
// Add custom message class, set time, and mark as Sent (so that it won't appear as draft)
MapiHelper.SetProperties(omi, new MAPIProperties
{
{ MapiProperty.PidTagMessageClass, DistributedPolicyEngine.DPE_MESSAGE_CLASS },
{ MapiProperty.PidTagMessageDeliveryTime, DateTime.UtcNow }
});
omi.SetMessageFlag(MapiPropertyValue.EnumPidTagMessageFlags.mfUnsent, false);
// Move to inbox and set Received time
mi = omi.Move(Globals.ThisAddIn.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox));
mi.Save();
}
catch (Exception ex)
{
Log.Error("CreatePatchMailItem: Error creating patch mail item. " + ex);
}
finally
{
omi = null;
mi = null;
}
}
#endregion
#region Methods
......@@ -115,9 +171,9 @@ namespace pEp.DPE
/// <param name="patchEvents">The patch events to unsubscribe from.</param>
public void Unsubscribe(PatchEvents patchEvents)
{
patchEvents.PatchAccepted += PatchEvents_PatchAccepted;
patchEvents.PatchRejected += PatchEvents_PatchRejected;
patchEvents.PatchSuggested += PatchEvents_PatchSuggested;
patchEvents.PatchAccepted -= PatchEvents_PatchAccepted;
patchEvents.PatchRejected -= PatchEvents_PatchRejected;
patchEvents.PatchSuggested -= PatchEvents_PatchSuggested;
}
/// <summary>
......@@ -146,27 +202,6 @@ namespace pEp.DPE
return false;
}
/// <summary>
/// Saves the patch to disk.
/// </summary>
/// <param name="patch">The patch to save.</param>
/// <returns>True if the patch was saved successfully, otherwise false.</returns>
private bool SavePatch(Patch patch)
{
try
{
string fileName = Path.Combine(DistributedPolicyEngine.DPE_FOLDER, patch.Id + DistributedPolicyEngine.PATCH_EXTENSION);
string xml = patch.Serialize();
File.WriteAllText(fileName, xml);
return File.Exists(fileName);
}
catch (Exception ex)
{
Log.Error("SavePatch: Error saving patch. " + ex.ToString());
}
return false;
}
#endregion
#region Static methods
......
......@@ -2,7 +2,7 @@
{
internal interface IPatchEvents
{
void Suggested(Patch patch);
void Suggested(Patch patch, PEPIdentity submitter);
void Rejected(Patch patch, Patch.RejectReason rejectReason);
void Accepted(Patch patch);
}
......
......@@ -4,7 +4,8 @@ namespace pEp.DPE
{
public class PatchEventArgs : EventArgs
{
public Patch Patch { get; set; }
public Patch.RejectReason Reason { get; set; } = Patch.RejectReason.None;
public Patch Patch { get; set; }
internal PEPIdentity Submitter { get; set; }
public Patch.RejectReason Reason { get; set; } = Patch.RejectReason.None;
}
}
......@@ -33,7 +33,7 @@ namespace pEp.DPE
Patch patch;
if ((patch = Patch.Deserialize(e.Request)) != null)
{
this.Suggested(patch);
this.Suggested(patch, new PEPIdentity("patchadmin@pep.security"));
}
}
......@@ -72,9 +72,9 @@ namespace pEp.DPE
/// Raises the Patch suggested event.
/// </summary>
/// <param name="patch">The patch that has been suggested.</param>
public void Suggested(Patch patch)
public void Suggested(Patch patch, PEPIdentity submitter)
{
this.PatchSuggested?.Invoke(this, new PatchEventArgs { Patch = patch });
this.PatchSuggested?.Invoke(this, new PatchEventArgs { Patch = patch, Submitter = submitter });
}
#endregion
......
......@@ -578,6 +578,8 @@ namespace pEp
[FieldOffset(0)]
public double at;
[FieldOffset(0)]
public System.Runtime.InteropServices.ComTypes.FILETIME ft;
[FieldOffset(0)]
public IntPtr lpszA;
[FieldOffset(0)]
public IntPtr lpszW;
......@@ -1455,6 +1457,23 @@ namespace pEp
}
}
break;
case MapiProperty.MapiDataType.PtypTime:
{
try
{
long fileTime = ((DateTime)value).ToFileTimeUtc();
sPropValue.Value.ft = new System.Runtime.InteropServices.ComTypes.FILETIME
{
dwLowDateTime = (int)(fileTime & 0xFFFFFFFF),
dwHighDateTime = (int)(fileTime >> 32)
};
}
catch (Exception ex)
{
throw new Exception(string.Format("Error converting to Filetime. Property tag: {0}. Value: {1}. Exception: {2}.", property.DaslName, value?.ToString(), ex.ToString()));
}
}
break;
default:
{
throw new Exception(string.Format("Error creating SPropValue. Data type {0} not supported.", Enum.GetName(typeof(MapiProperty.MapiDataType), property.DataType)));
......@@ -1769,6 +1788,23 @@ namespace pEp
}
}
break;
case MapiProperty.MapiDataType.PtypTime:
{
try
{
long fileTime = ((DateTime)value).ToFileTimeUtc();
sPropValue.Value.ft = new System.Runtime.InteropServices.ComTypes.FILETIME
{
dwLowDateTime = (int)(fileTime & 0xFFFFFFFF),
dwHighDateTime = (int)(fileTime >> 32)
};
}
catch (Exception ex)
{
throw new Exception(string.Format("Error converting to Filetime. Property tag: {0}. Value: {1}. Exception: {2}.", mapiProperty.DaslName, value?.ToString(), ex.ToString()));
}
}
break;
default:
{
throw new Exception(string.Format("Error creating SPropValue. Data type {0} not supported.", Enum.GetName(typeof(MapiProperty.MapiDataType), mapiProperty.DataType)));
......
......@@ -2,10 +2,6 @@
using pEp.UI.Models;
using pEp.UI.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace pEp
......@@ -14,7 +10,7 @@ namespace pEp
{
#region Form Region Factory
[Microsoft.Office.Tools.Outlook.FormRegionMessageClass("IPM.Note.DPE")]
[Microsoft.Office.Tools.Outlook.FormRegionMessageClass(DistributedPolicyEngine.DPE_MESSAGE_CLASS)]
[Microsoft.Office.Tools.Outlook.FormRegionName("pEpForOutlook.FormRegionDPE")]
public partial class FormRegionDPEFactory
{
......@@ -39,8 +35,8 @@ namespace pEp
omi = this.OutlookItem as Outlook.MailItem;
string xml = omi.HTMLBody;
Patch patch = Patch.Deserialize(xml);
FormControlPatchViewModel formControlPatchViewModel = new FormControlPatchViewModel(patch, PatchDialog.PatchAction.SupportOrRejectPatch);
this.FormControlPatchView.DataContext = formControlPatchViewModel;
PEPIdentity.GetFromIdentity(omi, out PEPIdentity submitter);
this.FormControlPatchView.DataContext = new FormControlPatchViewModel(patch, submitter);
}
catch (Exception ex)
{
......
......@@ -62,11 +62,11 @@ namespace pEp.UI.Models
{
// Get group manager
pEpIdentity groupManager = (pEpIdentity)AdapterExtensions.ExecuteWithPassphraseCheck(() => ThisAddIn.PEPEngine.GroupQueryManager(groupIdentity));
Log.Verbose("GetManagedGroupe: Retrieved group manager " + groupManager.Address);
Log.Verbose("GetManagedGroups: Retrieved group manager " + groupManager.Address);
// Get group members
pEpIdentity[] members = (pEpIdentity[])AdapterExtensions.ExecuteWithPassphraseCheck(() => ThisAddIn.PEPEngine.GroupQueryMembers(groupIdentity));
Log.Verbose("GetManagedGroupe: Retrieved group {0} group members", members.Length);
Log.Verbose("GetManagedGroups: Retrieved group {0} group members", members.Length);
// Add group
messageGroups.Add(new MessageGroup(groupIdentity, groupManager, members));
......
using pEp.DPE;
using pEp.UI.Models;
using System;
using System.Windows.Documents;
using System.Windows.Media;
......@@ -12,13 +10,6 @@ namespace pEp.UI.ViewModels
private Patch patch;
private FlowDocument _DisplayDiff = null;
private bool _IsCommitMessageValid = false;
private bool _IsDiffValid = false;
private bool _IsUriValid = false;
private bool _IsValid = false;
private RelayCommand _LoadFromFileCommand = null;
#endregion
#region Properties
......@@ -32,11 +23,15 @@ namespace pEp.UI.ViewModels
set
{
this.patch.CommitMessage = value;
this.ValidatePatch();
this.OnPropertyChanged();
}
}
/// <summary>
/// Gets the creation date as string.
/// </summary>
public string CreationDateString => this.patch?.CreationDate.ToString("F");
/// <summary>
/// The diff of this patch.
/// </summary>
......@@ -46,7 +41,6 @@ namespace pEp.UI.ViewModels
set
{
this.patch.Diff = value;
this.ValidatePatch();
this.OnPropertyChanged();
}
}
......@@ -54,55 +48,13 @@ namespace pEp.UI.ViewModels
/// <summary>
/// Gets the diff of this patch as formatted flow document.
/// </summary>
public FlowDocument DisplayDiff { get => this._DisplayDiff; set => SetProperty(ref this._DisplayDiff, value); }
public FlowDocument DisplayDiff { get; }
/// <summary>
/// The explanation shown in the UI regarding this patch.
/// </summary>
public string Explanation { get; }
/// <summary>
/// Gets whether the Cancel button is visible.
/// </summary>
public bool IsCancelButtonVisible { get; } = true;
/// <summary>
/// Gets or sets whether the commit message is valid.
/// </summary>
public bool IsCommitMessageValid
{
get => this._IsCommitMessageValid;
set
{
if (value != this._IsCommitMessageValid)
{
this._IsCommitMessageValid = value;
this.OnPropertyChanged();
}
}
}
/// <summary>
/// Gets or sets whether the diff is valid.
/// </summary>
public bool IsDiffValid
{
get => this._IsDiffValid;
set
{
if (value != this._IsDiffValid)
{
this._IsDiffValid = value;
this.OnPropertyChanged();
}
}
}
/// <summary>
/// Gets whether the patch in this dialog is editable.
/// </summary>
public bool IsEditable { get; } = false;
/// <summary>
/// Gets whether the OK button is visible.
/// </summary>
......@@ -113,58 +65,10 @@ namespace pEp.UI.ViewModels
/// </summary>
public bool IsRejectButtonVisible { get; } = false;
/// <summary>
/// Gets or sets whether the URI is valid.
/// </summary>
public bool IsUriValid
{
get => this._IsUriValid;
set
{
if (value != this._IsUriValid)
{
this._IsUriValid = value;
this.OnPropertyChanged();
}
}
}
/// <summary>
/// Gets or sets whether this patch is valid.
/// </summary>
public bool IsValid
{
get => this._IsValid;
set
{
if (value != this._IsValid)
{
this._IsValid = value;
this.OnPropertyChanged();
}
}
}
/// <summary>
/// Gets the command to load the diff from file.
/// </summary>
public RelayCommand LoadFromFileCommand
{
get
{
if (this._LoadFromFileCommand == null)
{
this._LoadFromFileCommand = new RelayCommand(LoadFromFile);
}
return this._LoadFromFileCommand;
}
}
/// <summary>
/// The command to accept the patch dialog.
/// </summary>
public RelayCommand OKButtonCommand => new RelayCommand(this.SupportPatch, p => this.IsValid);
public RelayCommand OKButtonCommand => new RelayCommand(this.SupportPatch);
/// <summary>
/// Gets the OK button text.
......@@ -181,6 +85,11 @@ namespace pEp.UI.ViewModels
/// </summary>
public string RejectButtonText { get; } = Properties.Resources.SyncWizard_RejectButton;
/// <summary>
/// Gets the submitter of this patch.
/// </summary>
public PEPIdentity Submitter { get; }
/// <summary>
/// Gets or sets the tag of the patch.
/// </summary>
......@@ -203,7 +112,6 @@ namespace pEp.UI.ViewModels
set
{
this.patch.Uri = value;
this.ValidatePatch();
this.OnPropertyChanged();
}
}
......@@ -212,39 +120,19 @@ namespace pEp.UI.ViewModels
#region Constructors
public FormControlPatchViewModel(Patch patch, PatchDialog.PatchAction patchAction, bool isEditable = false)
/// <summary>
/// Primary constructor.
/// </summary>
/// <param name="patch">The patch to create the form region with.</param>
/// <param name="submitter">The submitter of the patch.</param>
public FormControlPatchViewModel(Patch patch, PEPIdentity submitter)
{
this.patch = patch;
this.IsEditable = isEditable;
switch (patchAction)
{
case PatchDialog.PatchAction.EditPatch:
break;
case PatchDialog.PatchAction.NewPatch:
{
this.Explanation = "New patch";
}
break;
case PatchDialog.PatchAction.ShowPatch:
{
this.Explanation = "Patch " + patch.Id;
this.IsCancelButtonVisible = false;
}
break;
case PatchDialog.PatchAction.SupportOrRejectPatch:
{
this.Explanation = "Support or reject patch";
this.IsRejectButtonVisible = true;
this.OKButtonText = "Support";
}
break;
default:
break;
}
this.Submitter = submitter;
this.Explanation = "New configuration changes pending approval";
this.IsRejectButtonVisible = true;
this.OKButtonText = "Support";
this.DisplayDiff = this.FormatDiff();
this.ValidatePatch();
}
#endregion
......@@ -266,7 +154,7 @@ namespace pEp.UI.ViewModels
{
FontFamily = new FontFamily("Courier New"),
FontSize = 12.0,
Background = Brushes.White,
Background = Brushes.White
};
string[] lines = this.Diff?.Replace("\r\n", "\n")?.Split('\n') ?? new string[] { };
......@@ -297,31 +185,22 @@ namespace pEp.UI.ViewModels
return document;
}
private void LoadFromFile(object parameter)
{
// Get diff from disk
}
/// <summary>
/// Rejects this patch.
/// </summary>
/// <param name="parameter">The command parameter.</param>
private void RejectPatch(object parameter)
{
Globals.ThisAddIn.DistributedPolicyEngine.Reject(this.patch, new PEPIdentity());
}
private void SupportPatch(object parameter)
{
Globals.ThisAddIn.DistributedPolicyEngine.Support(this.patch, new PEPIdentity());
}
/// <summary>
/// Validates the patch.
/// Supports this patch.
/// </summary>
private void ValidatePatch()
/// <param name="parameter">The command parameter.</param>
private void SupportPatch(object parameter)
{
this.IsCommitMessageValid = !string.IsNullOrEmpty(this.CommitMessage);
this.IsDiffValid = !string.IsNullOrEmpty(this.Diff);
this.IsUriValid = !string.IsNullOrEmpty(this.Uri);
this.IsValid = this.IsCommitMessageValid && this.IsDiffValid && this.IsUriValid;
Globals.ThisAddIn.DistributedPolicyEngine.Support(this.patch, new PEPIdentity());
}
#endregion
......
This diff is collapsed.
......@@ -7,7 +7,9 @@
xmlns:ui="clr-namespace:pEp.UI"
xmlns:vm="clr-namespace:pEp.UI.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=vm:PatchDialogViewModel}"
FontFamily="Segoe UI"
FontSize="12"
d:DataContext="{d:DesignInstance Type=vm:FormControlPatchViewModel}"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
......@@ -24,10 +26,13 @@
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
......@@ -37,78 +42,82 @@
</Grid.RowDefinitions>
<Label Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="2"
Content="{Binding Explanation}"
Margin="10"/>
<Button Grid.Column="1"
Grid.Row="0"
Content="Load from file"
Margin="10"
HorizontalAlignment="Right"
Style="{StaticResource StyleButtonGray}"
Command="{Binding LoadFromFileCommand}"
Visibility="{Binding IsEditable, Converter={StaticResource BoolToVisibility}}"/>
FontWeight="Bold"
Margin="10,5"/>
<Label Grid.Column="0"
Grid.Row="1"
Content="Diff*"
Grid.ColumnSpan="2"
Content="{Binding Submitter.DisplayString}"
Margin="10,1" />
<Label Grid.Column="0"
Grid.Row="2"
Grid.ColumnSpan="2"
Content="{Binding CreationDateString}"
Margin="10,1" />
<Image Grid.Column="2"
Grid.Row="0"
Grid.RowSpan="3"
Width="100"
Height="41"
Source="pack://application:,,,/pEp;component/Resources/ImageLogoMedium.png"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="5,5,10,5"/>
<Label Grid.Column="0"
Grid.Row="3"
Content="Diff"
Margin="10,10,5,10"/>
<ui:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="1"
Text="{Binding Diff, UpdateSourceTrigger=PropertyChanged}"
MultiLine="True"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
IsValidInput="{Binding IsDiffValid}"
Placeholder="Please add diff"
Height="400"
Width="600"
Margin="5,10,10,10"
Visibility="{Binding IsEditable, Converter={StaticResource BoolToVisibility}}"/>
<FlowDocumentScrollViewer Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="3"
BorderBrush="Black"
BorderThickness="1"
Grid.Row="1"
MinHeight="400"
MinWidth="600"
Margin="5,10,10,10"
Document="{Binding DisplayDiff}"
Visibility="{Binding IsEditable, Converter={StaticResource InvertBoolToVisibility}}"/>
Document="{Binding DisplayDiff}" />
<Label Grid.Column="0"
Grid.Row="2"
Content="Uri*"
Grid.Row="4"
Content="Uri"
Margin="10,10,5,10"/>
<ui:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="2"
Text="{Binding Uri}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
IsValidInput="{Binding IsUriValid}"
Placeholder="URI"
MinWidth="400"
Margin="5,10,10,10"/>
<TextBox Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="4"
VerticalAlignment="Center"
Padding="2"
Text="{Binding Uri}"
IsReadOnly="True"
MinWidth="400"
Margin="5,10,10,10"/>
<Label Grid.Column="0"
Grid.Row="3"
Content="Commit message*"
Grid.Row="5"
Content="Commit message"
Margin="10,10,5,10"/>
<ui:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="3"
Text="{Binding CommitMessage}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
IsValidInput="{Binding IsCommitMessageValid}"
Placeholder="Commit message"
MinWidth="400"
Margin="5,10,10,10"/>
<TextBox Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="5"
VerticalAlignment="Center"
Padding="2"
Text="{Binding CommitMessage}"
IsReadOnly="True"
MinWidth="400"
Margin="5,10,10,10"/>
<Label Grid.Column="0"
Grid.Row="4"
Grid.Row="6"
Content="Tag"
Margin="10,10,5,10"/>
<ui:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="4"
Text="{Binding Tag}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
Placeholder="Tag (optional)"
MinWidth="400"
Margin="5,10,10,10"/>
<TextBox Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="6"
VerticalAlignment="Center"
Padding="2"
Text="{Binding Tag}"
IsReadOnly="True"
MinWidth="400"
Margin="5,10,10,10"/>
<StackPanel Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="5"
Grid.ColumnSpan="3"
Grid.Row="7"
Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Content="{Binding OKButtonText}"
......
<UserControl xmlns:UI="clr-namespace:pEp.UI"
x:Class="pEp.UI.Views.PatchDialogView"
<UserControl x:Class="pEp.UI.Views.PatchDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p="clr-namespace:pEp.Properties"
xmlns:ui="clr-namespace:pEp.UI"
xmlns:vm="clr-namespace:pEp.UI.ViewModels"
xmlns:vm="clr-namespace:pEp.UI.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=vm:PatchDialogViewModel}"
d:DesignHeight="450" d:DesignWidth="800">
......@@ -26,105 +24,83 @@
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
Grid.Row="0"
Content="{Binding Explanation}"
<Label Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Content="Change config"
Margin="10"/>
<Button Grid.Column="1"
Grid.Row="0"
Content="Load from file"
Margin="10"
HorizontalAlignment="Right"
Style="{StaticResource StyleButtonGray}"
Command="{Binding LoadFromFileCommand}" />
<Label Grid.Column="0"
Grid.Row="1"
Content="Diff*"
Margin="10,10,5,10"/>
<UI:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="1"
Text="{Binding Diff, UpdateSourceTrigger=PropertyChanged}"
MultiLine="True"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
IsValidInput="{Binding IsDiffValid}"
Placeholder="Please add diff"
Height="400"
Width="600"
Margin="5,10,10,10"
Visibility="{Binding IsEditable, Converter={StaticResource BoolToVisibility}}"/>
<FlowDocumentScrollViewer Grid.Column="1"
<ListBox Grid.Row="1"
Grid.Column="0"
Margin="10"
Width="500"
Height="500"
SelectedItem="{Binding SelectedFile}"
ItemsSource="{Binding ConfigFiles}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Item1}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1"
Grid.Column="1">
<Button Content="Add file"
Margin="5"
Style="{StaticResource StyleButtonGray}"
Command="{Binding LoadFromFileCommand}"/>
<Button Content="Remove file"
Margin="5"
Style="{StaticResource StyleButtonGray}"
Command="{Binding RemoveButtonCommand}" />
</StackPanel>
<FlowDocumentScrollViewer Grid.Column="2"
Grid.Row="1"
Height="400"
Width="600"
Width="500"
Height="500"
BorderBrush="Black"
BorderThickness="1"
Margin="5,10,10,10"
Document="{Binding DisplayDiff}"
Visibility="{Binding IsEditable, Converter={StaticResource InvertBoolToVisibility}}"/>
<Label Grid.Column="0"
Grid.Row="2"
Content="Uri*"
Margin="10,10,5,10"/>
<UI:TextBoxWithPlaceholder Grid.Column="1"
Document="{Binding VisibleDiff}"/>
<ui:TextBoxWithPlaceholder Grid.Column="0"
Grid.ColumnSpan="3"
Grid.Row="2"
Text="{Binding Uri}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
IsValidInput="{Binding IsUriValid}"
Placeholder="URI"
MinWidth="400"
Margin="5,10,10,10"/>
<Label Grid.Column="0"
Grid.Row="3"
Content="Commit message*"
Margin="10,10,5,10"/>
<UI:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="3"
Text="{Binding CommitMessage}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
Text="{Binding CommitMessage, UpdateSourceTrigger=PropertyChanged}"
IsValidInput="{Binding IsCommitMessageValid}"
Placeholder="Commit message"
MinWidth="400"
Margin="5,10,10,10"/>
<Label Grid.Column="0"
Grid.Row="4"
Content="Tag"
Margin="10,10,5,10"/>
<UI:TextBoxWithPlaceholder Grid.Column="1"
Grid.Row="4"
Text="{Binding Tag}"
IsReadOnly="{Binding IsEditable, Converter={StaticResource InvertBool}}"
Margin="5,10,10,10"
Visibility="{Binding IsEditable, Converter={StaticResource BoolToVisibility}}"/>
<ui:TextBoxWithPlaceholder Grid.Column="0"
Grid.ColumnSpan="3"
Grid.Row="3"
Text="{Binding Tag, UpdateSourceTrigger=PropertyChanged}"
Placeholder="Tag (optional)"
MinWidth="400"
Margin="5,10,10,10"/>
Margin="5,10,10,10"
Visibility="{Binding IsEditable, Converter={StaticResource BoolToVisibility}}"/>
<StackPanel Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="5"
Grid.ColumnSpan="3"
Grid.Row="4"
Orientation="Horizontal"
HorizontalAlignment="Center">
HorizontalAlignment="Center"
Margin="10">
<Button Content="{Binding OKButtonText}"
Command="{Binding OKButtonCommand}"
IsDefault="True"
Visibility="{Binding IsOKButtonVisible, Converter={StaticResource BoolToVisibility}}"
Style="{StaticResource StyleButtonGray}"
Margin="10" />
<Button Content="{Binding RejectButtonText}"
Command="{Binding RejectButtonCommand}"
Visibility="{Binding IsRejectButtonVisible, Converter={StaticResource BoolToVisibility}}"
Style="{StaticResource StyleButtonGray}"
Margin="10" />
IsEnabled="{Binding IsValid}"
Margin="10"
Style="{StaticResource StyleButtonGray}"/>
<Button Content="{Binding CancelButtonText}"
Margin="10"
Command="{Binding CancelButtonCommand}"
Visibility="{Binding IsCancelButtonVisible, Converter={StaticResource BoolToVisibility}}"
Style="{StaticResource StyleButtonGray}"
Margin="10"/>
Style="{StaticResource StyleButtonGray}"/>
</StackPanel>
</Grid>
</UserControl>
......@@ -251,6 +251,9 @@
-->
<ItemGroup>
<Reference Include="Accessibility" />
<Reference Include="DiffPlex, Version=1.7.0.0, Culture=neutral, PublicKeyToken=1d35e91d1bd7bc0f, processorArchitecture=MSIL">
<HintPath>..\packages\DiffPlex.1.7.0\lib\net40\DiffPlex.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Office.Interop.Outlook, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DiffPlex" version="1.7.0" targetFramework="net45" />
<package id="Microsoft.VisualStudio.OLE.Interop" version="16.7.30328.74" targetFramework="net45" />
<package id="MimeKitLite" version="2.10.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net45" />
......