Merge pull request 'v2.3' (#9) from v2.3 into master

Reviewed-on: #9
This commit is contained in:
MattBurke 2023-12-29 18:54:44 -05:00
commit 0d28ff706f
55 changed files with 1453 additions and 299 deletions

10
Config/PracticeConfig.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<ODhost>10.0.1.107</ODhost>
<ODuser>root</ODuser>
<ODpassword></ODpassword>
<pwuserid>testdoctor</pwuserid>
<pwpassword>testdoctor</pwpassword>
<pwpracticeid>210</pwpracticeid>
<pwapiid>12345678</pwapiid>
</Config>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<PWBaseURI>http://apipatientweb.azurewebsites.net/</PWBaseURI>
<PWUpdateURI>https://localhost:44354/api/PWAppVersion</PWUpdateURI>
</Config>

View File

@ -1,10 +1,12 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.33529.622
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PWAPPv2", "PWAPPv2\PWAPPv2.csproj", "{45E26AF8-41D7-4308-A2C8-D55A0350DB47}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PWAppUpdaterForm", "PWAppUpdater2\PWAppUpdaterForm.csproj", "{093798DD-2EDD-4519-AAC6-9DFF0DE3C15A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.Build.0 = Release|Any CPU
{093798DD-2EDD-4519-AAC6-9DFF0DE3C15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{093798DD-2EDD-4519-AAC6-9DFF0DE3C15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{093798DD-2EDD-4519-AAC6-9DFF0DE3C15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{093798DD-2EDD-4519-AAC6-9DFF0DE3C15A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows;
namespace PWAPPv2
{
@ -16,7 +10,7 @@ namespace PWAPPv2
public static string[] Args;
void app_Startup(object sender, StartupEventArgs e)
{
if(e.Args.Length > 0)
if (e.Args.Length > 0)
{
Args = e.Args;
}

View File

@ -69,7 +69,7 @@
<GroupBox Header="Refer To" HorizontalAlignment="Left" Height="55" Margin="0,120,0,0" VerticalAlignment="Top" Width="458" Grid.Column="1">
<ComboBox x:Name="boxReferTo" HorizontalAlignment="Left" Margin="0,10,-2,0" VerticalAlignment="Top" Width="448"/>
</GroupBox>
<CheckBox x:Name="contact" Content="Contact Doctor" HorizontalAlignment="Left" Margin="0,175,0,0" VerticalAlignment="Top" Grid.Column="1" Checked="CheckBox_Checked" Height="15" Width="101"/>
<CheckBox x:Name="contact" Content="Contact Patient" HorizontalAlignment="Left" Margin="0,175,0,0" VerticalAlignment="Top" Grid.Column="1" Checked="CheckBox_Checked" Height="15" Width="101"/>
<GroupBox Header="Remarks" HorizontalAlignment="Left" Height="150" Margin="10,347,0,0" VerticalAlignment="Top" Width="309">
<RichTextBox x:Name="fieldRemakrs" HorizontalAlignment="Left" Height="127" VerticalAlignment="Top" Width="299" Margin="0,0,-2,0">
<FlowDocument>
@ -81,7 +81,7 @@
</GroupBox>
<Button Content="Send" HorizontalAlignment="Left" Margin="383,476,0,0" VerticalAlignment="Top" Width="75" Grid.Column="1" Height="20" Click="Button_Click_1"/>
<Button Content="Cancel" HorizontalAlignment="Left" Margin="303,476,0,0" VerticalAlignment="Top" Width="75" Grid.Column="1" Height="20" Click="Button_Click"/>
<GroupBox Header="Images" HorizontalAlignment="Left" Height="281" Margin="1,190,0,0" VerticalAlignment="Top" Width="457" Grid.Column="1">
<GroupBox Header="Attachments" HorizontalAlignment="Left" Height="281" Margin="1,190,0,0" VerticalAlignment="Top" Width="457" Grid.Column="1">
<Grid HorizontalAlignment="Left" Height="258" VerticalAlignment="Top" Width="447" Margin="0,0,-2,0">
<Grid.RowDefinitions>
<RowDefinition Height="4*"/>
@ -94,8 +94,8 @@
<ColumnDefinition Width="80*"/>
<ColumnDefinition Width="77*"/>
</Grid.ColumnDefinitions>
<Button x:Name="AddImageButton" Content="Add Image" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Height="20" Click="Button_Click_2"/>
<Button Content="Remove" Grid.Column="1" Margin="0,0,5,1" HorizontalAlignment="Right" Width="75" Click="Button_Click_3"/>
<Button x:Name="AddImageButton" Content="Add Attachment" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="20" Click="Button_Click_2" Grid.ColumnSpan="2" Margin="47,0,0,0"/>
<Button Content="Remove" Margin="257,0,0,1" HorizontalAlignment="Left" Width="75" Click="Button_Click_3" Grid.ColumnSpan="2"/>
</Grid>
<ListBox x:Name="ImageList" HorizontalAlignment="Left" Height="234" Grid.Row="1" VerticalAlignment="Top" Width="447"/>
</Grid>

View File

@ -1,19 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
using System.Windows.Forms;
/**
* TODO:
@ -27,21 +18,32 @@ namespace PWAPPv2
/// </summary>
public partial class MainWindow : Window
{
static Source.APIConfig apiconfig = new Source.APIConfig();
static Source.APIConfig apiconfig;// = new Source.APIConfig();
static Source.Database.DatabaseConfig DataConfig;
static Source.API.APIConnection apiConnection;
Source.DataObjects.APICredentials apiCreds;
Source.API.PWApiConnection pwapiConnection;
Source.DataObjects.ComboBoxData TypeBox;
Source.DataObjects.ComboBoxData ToBox;
Source.DataObjects.ComboBoxData FromBox;
Source.Config.Configuration practiceConfig;
Source.Config.Configuration universalConfig;
string[] args;
Source.Patient patient;
List<Source.DataObjects.PWImage> images;
List<Source.DataObjects.Attachment> attachments;
//string ConfigPath = "C:\\PWAPP\\Config\\Config.xml";
string ConfigPath;
public MainWindow()
{
@ -49,30 +51,91 @@ namespace PWAPPv2
{
args = App.Args;
}
catch(Exception)
catch (Exception)
{ }
ConfigPath = "C:\\PWAPP\\Config\\";
try
{
//ConfigPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
//ConfigPath = Path.Combine(ConfigPath, "PWAPP\\Config\\");
images = new List<Source.DataObjects.PWImage>();
apiconfig.LoadConfig("./Config/Config.xml");
DataConfig = new Source.Database.DatabaseConfig("./Config/Config.xml");
Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(DataConfig);
apiCreds = new Source.DataObjects.APICredentials(apiconfig);
practiceConfig = new Source.Config.Configuration("C:\\PWAPP\\Config\\PracticeConfig.xml");
universalConfig = new Source.Config.Configuration("C:\\PWAPP\\App\\Config\\UniversalConfig.xml");
}
catch
(Exception ex)
{
System.Windows.MessageBox.Show("An error has occured in the configurations files.\n(" + ex.Message + ")");
}
apiConnection = new Source.API.APIConnection("http://apipatientweb.azurewebsites.net/",
apiCreds);
pwapiConnection = new Source.API.PWApiConnection(practiceConfig, universalConfig);
InitializeComponent();
try
{
if (pwapiConnection.CheckForUpdate() == true)
{
string message = "An update is available! Would you like to install it?";
string title = "Update available!";
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
DialogResult result = System.Windows.Forms.MessageBox.Show(message, title, buttons);
if (result == System.Windows.Forms.DialogResult.Yes)
{
//System.Windows.MessageBox.Show("HAHA NO UPDATE FOR YOU!");
Process p = new Process();
p.StartInfo.FileName = "C:\\PWAPP\\Updater\\PWAppUpdaterForm.exe";
p.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
try
{
p.StartInfo.Arguments = args[0];
}
catch { }
if (System.Environment.OSVersion.Version.Major >= 6)
{
p.StartInfo.Verb = "runas";
}
p.Start();
Environment.Exit(0);
}
}
}
catch (Exception)
{
System.Windows.MessageBox.Show("An error has occured while checking for updates");
}
PopulateComboBoxes();
try
{
attachments = new List<Source.DataObjects.Attachment>();
patient = new Source.Patient();
Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(practiceConfig);
patient.BuildFromDatabase(dbcon, args[0]);
apiconfig = new Source.APIConfig(practiceConfig, universalConfig);
apiCreds = new Source.DataObjects.APICredentials(apiconfig);
apiConnection = new Source.API.APIConnection(universalConfig.Get("PWBaseURI"), apiCreds);
this.DataContext = new Source.PatientGUIAdapter(patient);
InitializeComponent();
PopulateComboBoxes();
patient = new Source.Patient();
patient.BuildFromDatabase(dbcon, args[0]);
this.DataContext = new Source.PatientGUIAdapter(patient);
}
catch (NullReferenceException)
{
}
catch (Exception e)
{
System.Windows.MessageBox.Show(e.Message);
}
}
private void PopulateComboBoxes()
@ -84,20 +147,21 @@ namespace PWAPPv2
private void PopulateReferTypesBox()
{
string ReferTypeString = apiConnection.SendPostRequestAsync("api/PWReferralTypes");
//string ReferTypeString = apiConnection.SendPostRequestAsync("api/PWReferralTypes");
string ReferTypeString = pwapiConnection.GetReferalTypes();
TypeBox = new Source.DataObjects.ReferralTypeBox(boxReferType, ReferTypeString);
}
private void PopulateReferToBox()
{
string ReferToString = apiConnection.SendPostRequestAsync("api/PWReferTo");
string ReferToString = pwapiConnection.GetReferTo(); //apiConnection.SendPostRequestAsync("api/PWReferTo");
ToBox = new Source.DataObjects.ReferToBox(boxReferTo, ReferToString);
}
private void PopulateReferFromBox()
{
string ReferFromString = apiConnection.SendPostRequestAsync("api/PWReferFrom");
string ReferFromString = pwapiConnection.GetReferFrom(); //apiConnection.SendPostRequestAsync("api/PWReferFrom");
FromBox = new Source.DataObjects.ReferFromBox(boxReferFrom, ReferFromString);
}
@ -122,15 +186,15 @@ namespace PWAPPv2
{
TypeBox.GetSelectedID();
}
catch(Source.DataObjects.ReferralTypeDefaultException)
catch (Source.DataObjects.ReferralTypeDefaultException)
{
}
catch(Source.DataObjects.InvalidReferralTypeException)
catch (Source.DataObjects.InvalidReferralTypeException)
{
}
catch(NullReferenceException)
catch (NullReferenceException)
{
}
@ -141,12 +205,13 @@ namespace PWAPPv2
{
this.Close();
}
//OK Button
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Source.DataObjects.Referral referral;
if(images.Count == 0)
if (attachments.Count == 0)
{
referral = new Source.DataObjects.Referral(apiCreds, patient,
(Source.DataObjects.ReferralTypeBox)TypeBox,
@ -163,27 +228,28 @@ namespace PWAPPv2
fieldRemakrs, contact, true);
}
try
{
string referralString = referral.ToJsonString();
string result = apiConnection.SendPostRequestAsync("api/PWMakeReferral", referralString);
if(images.Count > 0)
string result = pwapiConnection.SendReferral(referralString);
if (attachments.Count > 0)
{
foreach(Source.DataObjects.PWImage im in images)
foreach (Source.DataObjects.Attachment attachment in attachments)
{
Source.DataObjects.Attachment att = new Source.DataObjects.Attachment(apiCreds, im, result);
string json = att.ToJsonString();
apiConnection.SendPostRequestAsync("api/PWAttachment", json);
attachment.Token = result;
string json = attachment.ToJsonString();
apiConnection.SendPostWithCredsInHeader("api/PWAttachment", json);
}
MessageBox.Show("Referral added successfully!");
}
else
{
MessageBox.Show(result);
}
System.Windows.MessageBox.Show("Referral added successfully!");
this.Close();
}
catch(Source.DataObjects.Referral.InvalidReferalDataException)
catch (Source.DataObjects.Referral.InvalidReferalDataException)
{
}
@ -192,23 +258,43 @@ namespace PWAPPv2
//AddImage Button
private void Button_Click_2(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.Filter = "Image files (*.jpg,*.jpeg)|*.jpg;*.jpeg";
openFileDialog.Filter = "Attachment files (*.jpg,*.jpeg,*.pdf)|*.jpg;*.jpeg;*.pdf";
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
if(openFileDialog.ShowDialog() == true)
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
foreach (string filename in openFileDialog.FileNames)
{
try
if (Path.GetExtension(filename) == ".jpg" || Path.GetExtension(filename) == ".jpeg")
{
images.Add(new Source.DataObjects.PWImage(filename));
try
{
attachments.Add(new Source.DataObjects.Attachment(apiCreds, new Source.DataObjects.PWImage(filename)));
}
catch (NullReferenceException)
{
attachments = new List<Source.DataObjects.Attachment>
{
new Source.DataObjects.Attachment(apiCreds, new Source.DataObjects.PWImage(filename))
};
}
}
catch(NullReferenceException)
if (Path.GetExtension(filename) == ".pdf")
{
images = new List<Source.DataObjects.PWImage>();
images.Add(new Source.DataObjects.PWImage(filename));
try
{
attachments.Add(new Source.DataObjects.Attachment(apiCreds, new Source.DataObjects.PWPdf(filename)));
}
catch (NullReferenceException)
{
attachments = new List<Source.DataObjects.Attachment>()
{
new Source.DataObjects.Attachment(apiCreds, new Source.DataObjects.PWPdf(filename))
};
}
}
}
@ -217,12 +303,20 @@ namespace PWAPPv2
try
{
ImageList.Items.Clear();
foreach (Source.DataObjects.PWImage image in images)
foreach (var attachment in attachments)
{
ImageList.Items.Add(CreateImageGridItem(image));
if (attachment.image == null)
{
ImageList.Items.Add(CreateImageGridItem(new Source.DataObjects.PWImage("C:\\PWAPP\\App\\App\\pdf.jpg")));
}
else
{
ImageList.Items.Add(CreateImageGridItem(attachment.image));
}
}
}
catch(NullReferenceException)
catch (NullReferenceException)
{ }
}
@ -230,17 +324,26 @@ namespace PWAPPv2
private void Button_Click_3(object sender, RoutedEventArgs e)
{
int index = ImageList.SelectedIndex;
if(index == -1)
if (index == -1)
{
return;
}
images.RemoveAt(index);
attachments.RemoveAt(index);
try
{
ImageList.Items.Clear();
foreach (Source.DataObjects.PWImage image in images)
foreach (var attachment in attachments)
{
ImageList.Items.Add(CreateImageGridItem(image));
if (attachment.image == null)
{
ImageList.Items.Add(CreateImageGridItem(new Source.DataObjects.PWImage("C:\\PWAPP\\App\\App\\pdf.jpg")));
}
else
{
ImageList.Items.Add(CreateImageGridItem(attachment.image));
}
}
}
catch (NullReferenceException)
@ -251,10 +354,9 @@ namespace PWAPPv2
{
Grid imageGrid = new Grid();
imageGrid.Width = 477;
imageGrid.HorizontalAlignment = HorizontalAlignment.Left;
imageGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
imageGrid.VerticalAlignment = VerticalAlignment.Top;
imageGrid.ShowGridLines = true;
imageGrid.Background = new SolidColorBrush(Colors.LightSteelBlue);
ColumnDefinition imageColumn = new ColumnDefinition();
imageColumn.Width = new GridLength(50);

View File

@ -210,10 +210,11 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="PwImage.cs" />
<Compile Include="Source\API\APIConfig.cs" />
<Compile Include="Source\API\APIConnection.cs" />
<Compile Include="Source\API\APIRequestBuilder.cs" />
<Compile Include="Source\API\PWApiConnection.cs" />
<Compile Include="Source\Config\Configuration.cs" />
<Compile Include="Source\Database\DatabaseConfig.cs" />
<Compile Include="Source\Database\DatabaseConnection.cs" />
<Compile Include="Source\DataObjects\APICredentials.cs" />
@ -223,6 +224,7 @@
<Compile Include="Source\DataObjects\PWImage.cs" />
<Compile Include="Source\DataObjects\NumValList.cs" />
<Compile Include="Source\DataObjects\NumValPair.cs" />
<Compile Include="Source\DataObjects\PWPdf.cs" />
<Compile Include="Source\DataObjects\ReferFromBox.cs" />
<Compile Include="Source\DataObjects\Referral.cs" />
<Compile Include="Source\DataObjects\ReferralTypeBox.cs" />
@ -269,9 +271,6 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Resource Include="Config\Config.xml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Source\GUIData\" />
</ItemGroup>

View File

@ -1,6 +1,4 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;

View File

@ -1,6 +0,0 @@
namespace PWAPPv2
{
internal class PwImage
{
}
}

View File

@ -1,19 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PWAPPv2.Source.Config;
using System;
using System.Xml;
namespace PWAPPv2.Source
{
class APIConfig
public class APIConfig
{
public string PWUserID;
public string PWPassword;
public string PWPracticeID;
public string PWApiID;
public string PWBaseURI;
public string PWUpdateURI;
public string PWAppVersion;
public APIConfig() { }
public APIConfig(Config.Configuration practiceConfig, Config.Configuration universalConfig)
{
PWUserID = practiceConfig.Get("pwuserid");
PWPassword = practiceConfig.Get("pwpassword");
PWPracticeID = practiceConfig.Get("pwpracticeid");
PWApiID = practiceConfig.Get("pwapiid");
PWBaseURI = universalConfig.Get("PWBaseURI");
PWUpdateURI = universalConfig.Get("PWUpdateURI");
PWAppVersion = universalConfig.Get("PWAppVersion");
}
public void LoadConfig(string path)
{
XmlDocument cfgDoc = new XmlDocument();
@ -21,12 +37,12 @@ namespace PWAPPv2.Source
{
cfgDoc.Load(path);
}
catch(XmlException)
catch (XmlException)
{
Console.WriteLine("An error has occured parsing the config file.");
return;
}
catch(System.IO.FileNotFoundException)
catch (System.IO.FileNotFoundException)
{
Console.WriteLine("Config file could not be found!");
return;

View File

@ -1,50 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;
using Newtonsoft.Json;
using System.Text;
namespace PWAPPv2.Source.API
{
class APIConnection
public class APIConnection
{
private static string BaseURL;
public DataObjects.APICredentials Credentials;
private static bool ResponseReady = false;
private static string Response = "";
HttpClient Client;
public APIConnection(string baseUrl, DataObjects.APICredentials credentials)
{
Credentials = credentials;
BaseURL = baseUrl;
Client = new HttpClient();
Client.BaseAddress = new Uri(BaseURL);
Client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
Client.DefaultRequestHeaders.Add("UserID", Credentials.UserID);
Client.DefaultRequestHeaders.Add("Password", Credentials.Password);
Client.DefaultRequestHeaders.Add("PracticeID", Credentials.PracticeId);
Client.DefaultRequestHeaders.Add("ApiID", Credentials.APIid);
}
public string GetResponse()
{
while (!ResponseReady) ;
return Response;
}
/// <summary>
/// Dont use. Doesn't work, sillyhead.
/// </summary>
/// <param name="Call"></param>
public static async void APIGet(string Call)
{
//WebRequest request = WebRequest.Create(BaseURL + Call);
//request.Method = "GET";
//request.ContentType = "application/json; charset=utf-8";
//var response = (HttpWebResponse)request.GetResponse();
//string text;
//using (var sr = new StreamReader(response.GetResponseStream()))
//{
// text = sr.ReadToEnd();
//}
//return text;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(BaseURL);
@ -56,66 +52,16 @@ namespace PWAPPv2.Source.API
}
}
public string APIPost()
{
string text;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://apipatientweb.azurewebsites.net/api/PWReferralTypes");
request.Method = "POST";
request.ContentType = "application/json; charset=\"utf-8\"";
request.Accept = "application/json";
string postData = Source.API.APIRequestBuilder.BuildJsonBodyRequest(Credentials);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(postData);
request.ContentLength = data.Length;
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
}
catch(WebException wex)
{
text = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
}
return text;
}
/// <summary>
/// Send a post requst without data. Essentially an advanced get since I was a retard when I wrote the original API.
/// </summary>
/// <param name="apiUri"></param>
/// <returns></returns>
public string SendPostRequestAsync(string apiUri)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BaseURL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
StringContent contetnt = new StringContent(Credentials.ToJsonString(), Encoding.UTF8, "application/json");
var response = client.PostAsync(apiUri, contetnt).Result;
if(response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return "";
}
public string SendPostRequestAsync(string apiUri, string PostData)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BaseURL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
StringContent contetnt = new StringContent(PostData, Encoding.UTF8, "application/json");
var response = client.PostAsync(apiUri, contetnt).Result;
var response = Client.PostAsync(apiUri, contetnt).Result;
if (response.IsSuccessStatusCode)
{
@ -124,5 +70,63 @@ namespace PWAPPv2.Source.API
return "";
}
/// <summary>
/// Send a post request with data
/// </summary>
/// <param name="apiUri"></param>
/// <param name="PostData"></param>
/// <returns></returns>
public string SendPostRequestAsync(string apiUri, string PostData)
{
StringContent contetnt = new StringContent(PostData, Encoding.UTF8, "application/json");
var response = Client.PostAsync(apiUri, contetnt).Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return "";
}
/// <summary>
/// Send a post request with the API credengials in the header of the request.
/// </summary>
/// <param name="apiUri"></param>
/// <param name="PostData"></param>
/// <returns></returns>
/// <exception cref="RequestFailedExcpetion"></exception>
public string SendPostWithCredsInHeader(string apiUri, string PostData)
{
StringContent content = new StringContent(PostData, Encoding.UTF8, "application/json");
string conts = content.ToString();
var response = Client.PostAsync(apiUri, content).Result;
//Client.DefaultRequestHeaders.Remove("UserID");
//Client.DefaultRequestHeaders.Remove("Password");
//Client.DefaultRequestHeaders.Remove("PraticeID");
//Client.DefaultRequestHeaders.Remove("ApiID");
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
throw new RequestFailedExcpetion(response.StatusCode.ToString());
}
}
public class RequestFailedExcpetion : Exception
{
public string RequestError;
public RequestFailedExcpetion(string errorCode)
{
RequestError = "Server responded with error code: " + errorCode;
}
}
}

View File

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json;
using System;
namespace PWAPPv2.Source.API
{

View File

@ -0,0 +1,81 @@
using PWAPPv2.Source.DataObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.API
{
public class PWApiConnection
{
private APIConnection BaseConnection;
private APIConnection UpdateConnection;
private APIConnection AttachementConnection;
private APIConnection ReferralConnection;
private APIConnection ReferToConnection;
private APIConnection ReferFromConnection;
private APIConnection ReferTypesConnection;
private APICredentials Credentials;
private string AppVersion;
public PWApiConnection(Source.Config.Configuration practiceConfig, Source.Config.Configuration universalConfig)
{
Credentials = new APICredentials(practiceConfig);
BaseConnection = new APIConnection(universalConfig.Get("PWBaseURI"), Credentials);
UpdateConnection = new APIConnection(universalConfig.Get("PWUpdateURI"), Credentials);
AttachementConnection = new APIConnection(universalConfig.Get("PWAttachmentURI"), Credentials);
ReferralConnection = new APIConnection(universalConfig.Get("PWReferralURI"), Credentials);
ReferToConnection = new APIConnection(universalConfig.Get("PWReferToURI"), Credentials);
ReferFromConnection = new APIConnection(universalConfig.Get("PWReferFromURI"), Credentials);
ReferTypesConnection = new APIConnection(universalConfig.Get("PWReferTypesURI"), Credentials);
AppVersion = universalConfig.Get("PWAppVersion");
}
public string PostToApi(string uri, string data)
{
return BaseConnection.SendPostRequestAsync(uri, data);
}
public string GetFromApi(string uri)
{
return BaseConnection.SendPostRequestAsync(uri);
}
public bool CheckForUpdate()
{
string currentVersion = UpdateConnection.SendPostWithCredsInHeader("", "");
currentVersion = currentVersion.Replace("\"", "");
if(currentVersion != AppVersion)
{
return true;
}
return false;
}
public string GetReferalTypes()
{
return ReferTypesConnection.SendPostWithCredsInHeader("", "");
}
public string GetReferTo()
{
return ReferToConnection.SendPostWithCredsInHeader("", "");
}
public string GetReferFrom()
{
return ReferFromConnection.SendPostWithCredsInHeader("", "");
}
public string SendReferral(string JsonData)
{
return ReferralConnection.SendPostWithCredsInHeader("", JsonData);
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
namespace PWAPPv2.Source.Config
{
public class Configuration
{
private Dictionary<string, string> values;
public Configuration(string file)
{
values = new Dictionary<string, string>();
if(!File.Exists(file))
{
throw new ConfigFileNotFoundException();
}
string f = File.ReadAllText(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(f);
XmlNodeList xmlNodeList = xmlDoc.DocumentElement.ChildNodes;
foreach (XmlNode xmlNode in xmlNodeList)
{
values.Add(xmlNode.Name, xmlNode.InnerText);
}
}
public string Get(string key)
{
try
{
return values[key];
}
catch
{
throw new ConfigValueNotFoundException();
}
}
}
public class ConfigFileNotFoundException : Exception { }
public class ConfigValueNotFoundException: Exception { }
}

View File

@ -1,18 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
namespace PWAPPv2.Source.DataObjects
{
class APICredentials
public class APICredentials
{
public string UserID;
public string Password;
public string PracticeId;
public string APIid;
public APICredentials()
{
}
public APICredentials(Source.APIConfig config)
{
UserID = config.PWUserID;
@ -21,6 +20,14 @@ namespace PWAPPv2.Source.DataObjects
APIid = config.PWApiID;
}
public APICredentials(Source.Config.Configuration practiceConfig)
{
UserID = practiceConfig.Get("pwuserid");
Password = practiceConfig.Get("pwpassword");
PracticeId = practiceConfig.Get("pwpracticeid");
APIid = practiceConfig.Get("pwapiid");
}
public string BuildJsonBodyContents()
{
return "'UserID':'" + UserID + "'," +

View File

@ -1,40 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
namespace PWAPPv2.Source.DataObjects
{
class Attachment
{
APICredentials Credentials;
PWImage image;
public PWImage image { get; set; }
public PWPdf pdf { get; set; }
public string Token;
string Token;
private string fileType { get; set; }
public Attachment(APICredentials credentials, PWImage pwImage, string token)
public Attachment(APICredentials credentials, PWImage pwImage)
{
Credentials = credentials;
image = pwImage;
Token = token;
//Token = token;
pdf = null;
fileType = "image/jpeg";
}
public Attachment(APICredentials credentials, PWPdf pwPdf)
{
Credentials = credentials;
pdf = pwPdf;
image = null;
fileType = "application/pdf";
}
public string ToJsonString()
{
return "\"{" + Credentials.BuildJsonBodyContents() +
",'UserNum':'API'," +
"'AttToken':'" + Token.Replace("\"", "") + "'," +
"'FileName':'" + image.ShortFileName() + "'," +
"'ContentType':'_1'," +
"'ThumbExists':'1'," +
"'ZoomExists':'1'," +
"'FileDate':''," +
"'Base64FileContents':'" + image.GetBase64String() + "',\n" +
"'Base64ThumbContents':'" + image.GetBase64ThumbString() + "',\n" +
"'Base64ZoomContents':'" + image.GetBase64ZoomString() + "'}\"";
if (fileType == "image/jpeg")
{
return "\"{" + Credentials.BuildJsonBodyContents() +
",'UserNum':'API'," +
"'AttToken':'" + Token.Replace("\"", "") + "'," +
"'FileName':'" + image.ShortFileName() + "'," +
"'ThumbExists':'1'," +
"'ZoomExists':'1'," +
"'FileDate':''," +
"'FileType':'" + fileType + "'," +
"'Base64FileContents':'" + image.GetBase64String() + "',\n" +
"'Base64ThumbContents':'" + image.GetBase64ThumbString() + "',\n" +
"'Base64ZoomContents':'" + image.GetBase64ZoomString() + "'}\"";
}
else
{
return "\"{" + Credentials.BuildJsonBodyContents() +
",'UserNum':'API'," +
"'AttToken':'" + Token.Replace("\"", "") + "'," +
"'FileName':'" + pdf.ShortFileName() + "'," +
"'ThumbExists':'0'," +
"'ZoomExists':'0'," +
"'FileDate':''," +
"'FileType':'" + fileType + "'," +
"'Base64FileContents':'" + pdf.GetBase64String() + "',\n" +
"'Base64ThumbContents':'',\n" +
"'Base64ZoomContents':''}\"";
}
}
}
}

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects
{

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{
@ -18,11 +15,11 @@ namespace PWAPPv2.Source.DataObjects
public NumValList(string Content, char Delim)
{
string[] split = Content.Split(Delim);
if((split.Length % 2) != 0)
if ((split.Length % 2) != 0)
{
throw new UnevenValuesException();
}
for(int i = 0; i < split.Length; i++)
for (int i = 0; i < split.Length; i++)
{
this.Add(int.Parse(split[i]), split[i + 1]);
i++;

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
namespace PWAPPv2.Source.DataObjects
{
class NumValPair
{

View File

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;
namespace PWAPPv2.Source.DataObjects
{

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{
public class PWPdf
{
public string path;
public PWPdf(string path)
{
this.path = path;
}
public string GetBase64String()
{
byte[] bytes = File.ReadAllBytes(path);
return Convert.ToBase64String(bytes);
}
public string ShortFileName()
{
return path.Substring(path.LastIndexOf("\\") + 1);
}
}
}

View File

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects

View File

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects

View File

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows;
namespace PWAPPv2.Source.DataObjects
{
@ -40,7 +36,7 @@ namespace PWAPPv2.Source.DataObjects
string RemarksText = new TextRange(RemarksBox.Document.ContentStart, RemarksBox.Document.ContentEnd).Text;
int contact = 0;
if(ContactBox.IsChecked == true)
if (ContactBox.IsChecked == true)
{
contact = 1;
}
@ -76,11 +72,11 @@ namespace PWAPPv2.Source.DataObjects
{
MessageBox.Show("Please select a referral type");
}
catch(Source.DataObjects.ReferToDefaultException)
catch (Source.DataObjects.ReferToDefaultException)
{
MessageBox.Show("Please select a refer to");
}
catch(Source.DataObjects.ReferFromDefaultException)
catch (Source.DataObjects.ReferFromDefaultException)
{
MessageBox.Show("Please select a refer from");
}

View File

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects
@ -28,7 +24,7 @@ namespace PWAPPv2.Source.DataObjects
TypeID.Add(id);
}
catch(Exception)
catch (Exception)
{
throw new DataInvalidException();
}
@ -36,7 +32,7 @@ namespace PWAPPv2.Source.DataObjects
}
foreach(string name in TypeName)
foreach (string name in TypeName)
{
Add(name);
}
@ -52,9 +48,9 @@ namespace PWAPPv2.Source.DataObjects
{
throw new ReferralTypeDefaultException();
}
for(int i = 0; i < TypeName.Count; i++)
for (int i = 0; i < TypeName.Count; i++)
{
if(TypeName[i] == Selected)
if (TypeName[i] == Selected)
{
return TypeID[i];
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace PWAPPv2.Source.Database
@ -22,12 +18,12 @@ namespace PWAPPv2.Source.Database
{
cfg.Load(path);
}
catch(XmlException)
catch (XmlException)
{
Console.WriteLine("An error has occured parsing the config file.");
return;
}
catch(System.IO.FileNotFoundException)
catch (System.IO.FileNotFoundException)
{
Console.WriteLine("Config file could not be found!");
}

View File

@ -1,13 +1,12 @@
using System;
using MySqlConnector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using MySqlConnector;
namespace PWAPPv2.Source.Database
{
/// <summary>
/// Class <c>DatabaseConnection</c> creates and maintains a connection to and OpenDental MySqlDatabase.
/// </summary>
class DatabaseConnection
{
@ -22,13 +21,19 @@ namespace PWAPPv2.Source.Database
Connection = new MySqlConnection(SqlString);
}
public DatabaseConnection(Config.Configuration config)
{
SqlString = "server=" + config.Get("ODhost") + ";Uid=" + config.Get("ODuser") + ";database=" + config.Get("ODdatabase") + ";Pwd=" + config.Get("ODpassword");
Connection = new MySqlConnection(SqlString);
}
public void Connect()
{
try
{
Connection.Open();
}
catch(Exception)
catch (Exception)
{
throw new DatabaseConnectionException();
}
@ -99,7 +104,7 @@ namespace PWAPPv2.Source.Database
{
}
class DatabaseConnectionException : Exception
{ }

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace PWAPPv2.Source
{

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source
namespace PWAPPv2.Source
{
class PatientGUIAdapter
{

9
PWAppUpdater/App.xaml Normal file
View File

@ -0,0 +1,9 @@
<Application x:Class="PWAppUpdater.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PWAppUpdater"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

17
PWAppUpdater/App.xaml.cs Normal file
View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace PWAppUpdater
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Net;
namespace PWAppUpdater.FTP
{
class FTPManager
{
private string BaseUri;
private NetworkCredential credential;
public FTPManager(string baseUri, string username, string password)
{
BaseUri = baseUri;
credential = new NetworkCredential(username, password);
}
public void DownloadFile(string FTPPath, string localPath)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(BaseUri + FTPPath);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = credential;
request.KeepAlive = false;
request.UseBinary = true;
request.UsePassive = true;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
using (Stream s = File.Create(localPath))
{
responseStream.CopyTo(s);
}
response.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message.ToString());
}
}
}
}

View File

@ -0,0 +1,16 @@
<Window x:Class="PWAppUpdater.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PWAppUpdater"
mc:Ignorable="d"
Title="PWUpdater" Height="137" Width="266">
<Grid Margin="0,0,0,-4">
<ProgressBar x:Name="barProgressBar" Minimum="0" Maximum="100" HorizontalAlignment="Center" Height="10" VerticalAlignment="Top" Width="246" Margin="0,46,0,0"/>
<Label x:Name="statusText" Content="Please wait while the application is updating." HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Label x:Name="txtUpdateStep" Content="{Binding Path=txtUpdateStep}" HorizontalAlignment="Left" Margin="10,31,0,0" VerticalAlignment="Top"/>
<Button x:Name="OKButton" Content="OK" HorizontalAlignment="Center" Margin="0,70,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</Grid>
</Window>

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PWAppUpdater
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
statusText.Content = "The program will now be updated.\nPlease click \"OK\" to continue.";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OKButton.IsEnabled = false;
for(int i = 0; i < 100; i++)
{
barProgressBar.Value = i;
barProgressBar.UpdateLayout();
Thread.Sleep(100);
}
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Folder Include="Config\" />
</ItemGroup>
</Project>

52
PWAppUpdater/Updater.cs Normal file
View File

@ -0,0 +1,52 @@
using PWAppUpdater.FTP;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace PWAppUpdater
{
class Updater
{
public static void Update(string installPath, string practiceConfigLocation = "", string tempPath = "")
{
try
{
if (tempPath == "")
{
tempPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
tempPath = Path.Combine(tempPath, "PWAPP\\Temp");
}
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
FTP.FTPManager ftpManager = new FTPManager("ftp://waws-prod-blu-109.ftp.azurewebsites.windows.net/", "patientweb\\$patientweb", "vHBnkgxPDS4Q410eehaFlXb8DH67QW50m9Rsxf1omXyYWRDgYioWJL63Tagp");
ftpManager.DownloadFile("pwapp/current/Release.zip", tempPath);
if (Directory.Exists(installPath))
{
Directory.Delete(installPath, true);
}
Directory.CreateDirectory(installPath);
Zip.ZipManager.UnZip(tempPath, installPath, true);
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Updater does not have sufficent permissions to perform update. Please run with administrator privilages to continue.");
}
}
}
class CouldNotFindInstallPathException : Exception
{
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAppUpdater.Zip
{
class ZipManager
{
public static void UnZip(string source, string destination, bool Override)
{
if (Override)
{
if (Directory.Exists(destination))
{
Directory.Delete(destination, true);
}
}
ZipFile.ExtractToDirectory(source, destination);
}
}
}

View File

@ -0,0 +1,9 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="highestAvailable" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Net;
namespace PWAppUpdater.FTP
{
class FTPManager
{
private string BaseUri;
private NetworkCredential credential;
public FTPManager(string baseUri, string username, string password)
{
BaseUri = baseUri;
credential = new NetworkCredential(username, password);
}
public void DownloadFile(string FTPPath, string localPath)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(BaseUri + FTPPath);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = credential;
request.KeepAlive = false;
request.UseBinary = true;
request.UsePassive = true;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
using (Stream s = File.Create(localPath))
{
responseStream.CopyTo(s);
}
response.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message.ToString());
}
}
}
}

98
PWAppUpdater2/Form1.Designer.cs generated Normal file
View File

@ -0,0 +1,98 @@
namespace PWAppUpdater2
{
partial class Form1
{
/// <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 Windows Form 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()
{
progressBar1 = new ProgressBar();
button1 = new Button();
label1 = new Label();
StepInfo = new Label();
SuspendLayout();
//
// progressBar1
//
progressBar1.Location = new Point(30, 60);
progressBar1.Name = "progressBar1";
progressBar1.Size = new Size(200, 10);
progressBar1.TabIndex = 0;
progressBar1.Click += progressBar1_Click;
//
// button1
//
button1.Location = new Point(105, 80);
button1.Name = "button1";
button1.Size = new Size(50, 23);
button1.TabIndex = 1;
button1.Text = "OK";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point);
label1.Location = new Point(12, 9);
label1.Name = "label1";
label1.Size = new Size(168, 30);
label1.TabIndex = 2;
label1.Text = "The program will now update. \r\nPlease click \"OK\" to continue.";
label1.Click += label1_Click;
//
// StepInfo
//
StepInfo.AutoSize = true;
StepInfo.Location = new Point(30, 42);
StepInfo.Name = "StepInfo";
StepInfo.Size = new Size(0, 15);
StepInfo.TabIndex = 3;
StepInfo.Click += label2_Click;
//
// Form1
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(264, 111);
Controls.Add(StepInfo);
Controls.Add(label1);
Controls.Add(button1);
Controls.Add(progressBar1);
Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point);
Name = "Form1";
Text = "Form1";
ResumeLayout(false);
PerformLayout();
}
#endregion
private ProgressBar progressBar1;
private Button button1;
private Label label1;
private Label StepInfo;
}
}

52
PWAppUpdater2/Form1.cs Normal file
View File

@ -0,0 +1,52 @@
using PWAppUpdater;
namespace PWAppUpdater2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void progressBar1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Directory.SetCurrentDirectory("C:\\PWAPP");
label1.Text = "Updating.... Please wait.";
label1.Update();
progressBar1.Maximum = 8;
progressBar1.Step = 1;
button1.Enabled = false;
try
{
PWAppUpdater.Updater.Update("C:\\PWAPP\\App", progressBar1, StepInfo, "C:\\PWAPP\\Temp");
}
catch (NoAuthException)
{
MessageBox.Show("Please run the updater with administrator privilages or from the PWApp Application.");
Application.Exit();
}
MessageBox.Show("Done!");
Application.Exit();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
}
}

120
PWAppUpdater2/Form1.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

17
PWAppUpdater2/Program.cs Normal file
View File

@ -0,0 +1,17 @@
namespace PWAppUpdater2
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}

73
PWAppUpdater2/Updater.cs Normal file
View File

@ -0,0 +1,73 @@
using PWAppUpdater.FTP;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace PWAppUpdater
{
class Updater
{
public static void Update(string installPath, ProgressBar progress, Label stepInfo, string tempPath = "")
{
try
{
progress.PerformStep();
stepInfo.Text = "Creating temp directories...";
stepInfo.Update();
if (tempPath == "")
{
tempPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
tempPath = Path.Combine(tempPath, "PWAPP\\Temp");
}
progress.PerformStep();
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
progress.PerformStep();
stepInfo.Text = "Downloading update...";
stepInfo.Update();
FTP.FTPManager ftpManager = new FTPManager("ftp://waws-prod-blu-109.ftp.azurewebsites.windows.net/", "patientweb\\$patientweb", "vHBnkgxPDS4Q410eehaFlXb8DH67QW50m9Rsxf1omXyYWRDgYioWJL63Tagp");
ftpManager.DownloadFile("pwapp/current/Release.zip", tempPath + "\\Release.zip");
progress.PerformStep();
stepInfo.Text = "Removing old installation...";
stepInfo.Update();
progress.PerformStep();
stepInfo.Text = "Creating new install directory...";
stepInfo.Update();
Directory.CreateDirectory(installPath);
progress.PerformStep();
stepInfo.Text = "Unpacking update...";
stepInfo.Update();
Zip.ZipManager.UnZip(tempPath + "\\Release.zip", installPath, true);
progress.PerformStep();
stepInfo.Text = "Cleaning up installation...";
stepInfo.Update();
Directory.Delete(tempPath, true);
progress.PerformStep();
stepInfo.Text = "Complete!";
stepInfo.Update();
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Updater does not have sufficent permissions to perform update. Please run with administrator privilages to continue.");
throw new NoAuthException();
}
}
}
class NoAuthException : Exception { }
class CouldNotFindInstallPathException : Exception
{
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAppUpdater.Zip
{
class ZipManager
{
public static void UnZip(string source, string destination, bool Override)
{
if (Override)
{
if (Directory.Exists(destination))
{
Directory.Delete(destination, true);
}
}
ZipFile.ExtractToDirectory(source, destination);
}
}
}

21
UnitTests/ConfigTest.cs Normal file
View File

@ -0,0 +1,21 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using PWAPPv2.Source;
namespace UnitTests
{
[TestClass]
public class ConfigTest
{
[TestMethod]
public void TestGetPracticeConfigs()
{
PWAPPv2.Source.Config.Configuration configuration = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml");
Assert.IsNotNull(configuration);
string apiKey = configuration.Get("pwapiid");
Assert.IsNotNull(apiKey);
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace UnitTests
{
[TestClass]
public class PWConnectionTest
{
[TestMethod]
public void TestCheckUpdate()
{
PWAPPv2.Source.Config.Configuration practiceConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml");
PWAPPv2.Source.Config.Configuration universalConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\UniversalConfig.xml");
PWAPPv2.Source.API.PWApiConnection pwApiConnection = new PWAPPv2.Source.API.PWApiConnection(practiceConfig, universalConfig);
Assert.IsNotNull(pwApiConnection);
Assert.IsFalse(pwApiConnection.CheckForUpdate());
}
}
}

View File

@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("UnitTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UnitTests")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("164b9220-f337-4e88-b619-0c52c502b9c4")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

59
UnitTests/UnitTest1.cs Normal file
View File

@ -0,0 +1,59 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using PWAPPv2.Source.API;
using PWAPPv2.Source.DataObjects;
// System.Threading.Tasks.Task<TResult>.Result.get returned "\"1|Endo|2|Implant|3|Oral Surgery|4|Ortho|5|Pedo|6|Perio|7|Restore|8|Other \\n\"" string
namespace UnitTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestV1Get()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "testdoctor";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("http://apipatientweb.azurewebsites.net/", creds);
string res = conn.SendPostRequestAsync("api/PWReferralTypes");
Assert.AreEqual("\"1|Endo|2|Implant|3|Oral Surgery|4|Ortho|5|Pedo|6|Perio|7|Restore|8|Other \\n\"", res);
}
[TestMethod]
public void TestV2Get()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "testdoctor";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("https://localhost:44354/", creds);
string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", "");
}
[TestMethod]
[ExpectedException(typeof(RequestFailedExcpetion))]
public void TestInvalidCredentialsV2()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "badPassword";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("https://localhost:44354/", creds);
string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", "");
}
}
}

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{164B9220-F337-4E88-B619-0C52C502B9C4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UnitTests</RootNamespace>
<AssemblyName>UnitTests</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="UnitTest1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ConfigTest.cs" />
<Compile Include="PWConnectionTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" />
</Project>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="2.1.2" targetFramework="net472" />
<package id="MSTest.TestFramework" version="2.1.2" targetFramework="net472" />
</packages>