Merge pull request #22 from Crylia/feature/client-socket

Feature/client socket
This commit is contained in:
Kievits Rene
2021-10-19 03:20:30 +02:00
committed by GitHub
146 changed files with 3808 additions and 1816 deletions

Binary file not shown.

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
/// <summary>
/// Client Socket
/// </summary>
/// <typeparam name="TProtocol">The Protocol type, either JsonMessageProtocol or XmlMessageProtocol</typeparam>
/// <typeparam name="TMessageType">The message type, either JObject or XDocument</typeparam>
public class ClientChannel<TProtocol, TMessageType> : SocketChannel<TProtocol, TMessageType>
where TProtocol : Protocol<TMessageType>, new() {
/// <summary>
/// Connect to the socket async
/// </summary>
/// <param name="endpoint">An endpoint with an IP address and port</param>
/// <returns></returns>
public async Task ConnectAsync(IPEndPoint endpoint) {
//Creates a new Socket
var socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//Connects to the socket
await socket.ConnectAsync(endpoint).ConfigureAwait(false);
//Attach the socket to a network stream
Attach(socket);
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
/// <summary>
/// Generic Channel class that handles the connection and message sending / receiving
/// Inherits IDisposable to correctly cut the connection to the server
/// </summary>
/// <typeparam name="TProtocol">The Protocol type, either JsonMessageProtocol or XmlMessageProtocol</typeparam>
/// <typeparam name="TMessageType">The message type, either JObject or XDocument</typeparam>
public abstract class SocketChannel<TProtocol, TMessageType> : IDisposable
where TProtocol : Protocol<TMessageType>, new() {
protected bool isDisposable = false;
private NetworkStream networkStream;
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly TProtocol protocol = new TProtocol();
private Func<TMessageType, Task> messageCallback;
/// <summary>
/// Attaches the socket to a network stream that owns the socket
/// if the network stream goes down it takes the socket with it!
/// </summary>
/// <param name="socket">A Socket</param>
public void Attach(Socket socket) {
networkStream = new NetworkStream(socket, true);
_ = Task.Run(ReceiveLoop, cancellationTokenSource.Token);
}
/// <summary>
/// Takes a function with a message and sets the private member to the functions value
/// </summary>
/// <param name="callbackHandler"></param>
public void OnMessage(Func<TMessageType, Task> callbackHandler) => messageCallback = callbackHandler;
/// <summary>
/// Makes sure to close the socket
/// </summary>
public void Close() {
cancellationTokenSource.Cancel();
networkStream?.Close();
}
/// <summary>
/// Sends the message async
/// </summary>
/// <typeparam name="T">Anything as message, e.g. object or string</typeparam>
/// <param name="message">The message</param>
/// <returns></returns>
public async Task SendAsync<T>(T message) => await protocol.SendAsync(networkStream, message).ConfigureAwait(false);
/// <summary>
/// Checks for received messages
/// </summary>
/// <returns>received message</returns>
protected virtual async Task ReceiveLoop() {
while (!cancellationTokenSource.Token.IsCancellationRequested) {
var msg = await protocol.ReceiveAsync(networkStream).ConfigureAwait(false);
await messageCallback(msg).ConfigureAwait(false);
}
}
/// <summary>
/// Deconstructor sets Dispose to false
/// </summary>
~SocketChannel() => Dispose(false);
/// <summary>
/// Sets dispose to true
/// </summary>
public void Dispose() => Dispose(true);
/// <summary>
/// Disposes open sockets
/// </summary>
/// <param name="isDisposing">Is it currently disposing stuff?</param>
protected void Dispose(bool isDisposing) {
//If its not disposable
if (!isDisposable) {
//Set disposable to true
isDisposable = true;
//Close the socket
Close();
//If its closed, dispose it
networkStream?.Dispose();
//Wait with the garbage collection until the disposing is done
if (isDisposing)
GC.SuppressFinalize(this);
}
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.IO;
using System.Xml.Serialization;
using Server_Dashboard_Socket.Protocol;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;
namespace Server_Dashboard_Socket {
public class SocketClient {
public SocketClient() {
//Starts the echo server for testing purposes
EchoServer echoServer = new EchoServer();
echoServer.Start();
//Start the Socket test
Start();
}
private async void Start() {
//Creates a new endpoint with the IP address and port
var endpoint = new IPEndPoint(IPAddress.Loopback, 9000);
//Creates a new Channel for the Json protocol
var channel = new ClientChannel<JsonMessageProtocol, JObject>();
//Creates a new Channel for the XDocument protocol
//var channel = new ClientChannel<XmlMessageProtocol, XDocument>();
//Callback for the message
channel.OnMessage(OnMessage);
//Connect to the Socket
await channel.ConnectAsync(endpoint).ConfigureAwait(false);
//Test message
var myMessage = new MyMessage {
IntProperty = 404,
StringProperty = "Hello World!"
};
//Send the test message
await channel.SendAsync(myMessage).ConfigureAwait(false);
}
/// <summary>
/// When it receives a message it gets converted from Json back to MyMessage
/// </summary>
/// <param name="jobject">The json to be converted back</param>
/// <returns>Task completed</returns>
private static Task OnMessage(JObject jobject) {
Console.WriteLine(Convert(jobject));
return Task.CompletedTask;
}
/// <summary>
/// When it receives a message it gets converted from XDocument back to MyMessage
/// </summary>
/// <param name="xDocument">The xml to be converted back</param>
/// <returns>Task completed</returns>
private static Task OnMessage(XDocument xDocument) {
Console.WriteLine(Convert(xDocument));
return Task.CompletedTask;
}
/// <summary>
/// Converts json to MyMessage
/// </summary>
/// <param name="jObject">The json to be converted</param>
/// <returns>MyMessage object</returns>
private static MyMessage Convert(JObject jObject) => jObject.ToObject(typeof(MyMessage)) as MyMessage;
/// <summary>
/// Converts XDocument to MyMessage
/// </summary>
/// <param name="xmlDocument">The xml to be converted</param>
/// <returns>MyMessage object</returns>
private static MyMessage Convert(XDocument xmlDocument) => new XmlSerializer(typeof(MyMessage)).Deserialize(new StringReader(xmlDocument.ToString())) as MyMessage;
}
/// <summary>
/// MyMessage test class
/// Delete later when Sockets are finished
/// </summary>
public class MyMessage {
public int IntProperty { get; set; }
public string StringProperty { get; set; }
}
}

View File

@@ -4,34 +4,56 @@ using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Server_Dashboard_Socket { namespace Server_Dashboard_Socket {
/// <summary> /// <summary>
/// Basic echo server to test the socket connection /// Basic echo server to test the socket connection
/// </summary> /// </summary>
public class EchoServer { public class EchoServer {
public void Start(int port = 9565) {
/// <summary>
/// Start the socket on 127.0.0.1:9000
/// </summary>
/// <param name="port">A port that is not already in use</param>
public void Start(int port = 9000) {
//Creates a new endpoint on 127.0.0.1 and the port 9000
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, port); IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, port);
//Creates a new Socket on the given endpoint
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//Bind the endpoint to the socket
socket.Bind(endPoint); socket.Bind(endPoint);
//Define how many Clients you want to have connected max
socket.Listen(128); socket.Listen(128);
//Just run the Task forever
_ = Task.Run(() => DoEcho(socket)); _ = Task.Run(() => DoEcho(socket));
} }
/// <summary>
/// Listens for messages and sends them back asap
/// </summary>
/// <param name="socket">The socket to work with</param>
/// <returns>poop</returns>
private async Task DoEcho(Socket socket) { private async Task DoEcho(Socket socket) {
while (true) { while (true) {
//Listen for incoming connection requests and accept them
Socket clientSocket = await Task.Factory.FromAsync( Socket clientSocket = await Task.Factory.FromAsync(
new Func<AsyncCallback, object, IAsyncResult>(socket.BeginAccept), new Func<AsyncCallback, object, IAsyncResult>(socket.BeginAccept),
new Func<IAsyncResult, Socket>(socket.EndAccept), new Func<IAsyncResult, Socket>(socket.EndAccept),
null).ConfigureAwait(false); null).ConfigureAwait(false);
using(NetworkStream stream = new NetworkStream(clientSocket, true)) { //Create a network stream and make it the owner of the socket
//This will close the socket if the stream is closed and vice verca
await using NetworkStream stream = new NetworkStream(clientSocket, true);
//New buffer for the message in bytes
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
while (true) { while (true) {
//Read everything that comes in
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
//If its 0 just leave since its a obsolete connection
if (bytesRead == 0) if (bytesRead == 0)
break; break;
//Send it back to the sender
await stream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); await stream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false);
} }
} }
} }
} }
}
} }

View File

@@ -0,0 +1,54 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Server_Dashboard_Socket.Protocol {
/// <summary>
/// Json serializer class
/// </summary>
public class JsonMessageProtocol : Protocol<JObject> {
//The Json serializer and the settings
private static readonly JsonSerializer serializer;
/// <summary>
/// Settings for the Json Serializer
/// </summary>
static JsonMessageProtocol() {
//Set the settings
JsonSerializerSettings settings = new JsonSerializerSettings {
Formatting = Formatting.Indented,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
ContractResolver = new DefaultContractResolver {
NamingStrategy = new CamelCaseNamingStrategy {
ProcessDictionaryKeys = false
}
}
};
settings.PreserveReferencesHandling = PreserveReferencesHandling.None;
//Creates the serializer with the settings
serializer = JsonSerializer.Create(settings);
}
//Decode the message, to Json
protected override JObject Decode(byte[] message) => JObject.Parse(Encoding.UTF8.GetString(message));
/// <summary>
/// Encode the body from Json to bytes
/// </summary>
/// <typeparam name="T">The message type e.g. object or string</typeparam>
/// <param name="message">The message to send</param>
/// <returns>message as byte[]</returns>
protected override byte[] EncodeBody<T>(T message) {
var sb = new StringBuilder();
var sw = new StringWriter(sb);
serializer.Serialize(sw, message);
return Encoding.UTF8.GetBytes(sb.ToString());
}
}
}

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
/// <summary>
/// Generic Protocol class for Json and Xml serialization
/// </summary>
/// <typeparam name="TMessageType">JsonMessageProtocol or XmlMessageProtocol</typeparam>
public abstract class Protocol<TMessageType> {
//Header size is always 4
private const int HeaderSize = 4;
/// <summary>
/// Gets the message and checks with the header if the message is valid or not
/// important to defend against attacks with infinite long messages
/// </summary>
/// <param name="networkStream">A network stream</param>
/// <returns>MessageType e.g. Json or Xml</returns>
public async Task<TMessageType> ReceiveAsync(NetworkStream networkStream) {
//Gets the body length
int bodyLength = await ReadHeader(networkStream).ConfigureAwait(false);
//Validates the length
AssertValidMessageLength(bodyLength);
//Returns the body message type
return await ReadBody(networkStream, bodyLength).ConfigureAwait(false);
}
/// <summary>
/// Sends data Async
/// </summary>
/// <typeparam name="T">Message type e.g. object or string</typeparam>
/// <param name="networkStream">Network stream</param>
/// <param name="message">The message</param>
/// <returns></returns>
public async Task SendAsync<T>(NetworkStream networkStream, T message) {
//encodes the message to a header and body
var (header, body) = Encode(message);
//Sends the header
await networkStream.WriteAsync(header, 0, header.Length).ConfigureAwait(false);
//Sends the body
await networkStream.WriteAsync(body, 0, body.Length).ConfigureAwait(false);
}
/// <summary>
/// Reads the header and converts it to an integer
/// </summary>
/// <param name="networkStream">A network stream</param>
/// <returns>Header as Integer</returns>
private async Task<int> ReadHeader(NetworkStream networkStream) {
byte[] headerBytes = await ReadAsync(networkStream, HeaderSize).ConfigureAwait(false);
return IPAddress.HostToNetworkOrder(BitConverter.ToInt32(headerBytes));
}
/// <summary>
/// Reads the body and decodes it to a human readable string
/// </summary>
/// <param name="networkStream">A network stream</param>
/// <param name="bodyLength">Length of the body</param>
/// <returns>Decoded body</returns>
private async Task<TMessageType> ReadBody(NetworkStream networkStream, int bodyLength) {
//Reads the bytes from the stream into an array
byte[] bodyBytes = await ReadAsync(networkStream, bodyLength).ConfigureAwait(false);
//Decodes it and returns the string
return Decode(bodyBytes);
}
/// <summary>
/// Reads the network stream as long as something is readable
/// </summary>
/// <param name="networkStream">A network stream</param>
/// <param name="bytesToRead">how many bytes there are to read</param>
/// <returns>Every byte from the Stream</returns>
private async Task<byte[]> ReadAsync(NetworkStream networkStream, int bytesToRead) {
//new buffer that is as big as the content(watch out for buffer overflows)
byte[] buffer = new byte[bytesToRead];
//keep account of the bytes that are already read
int bytesRead = 0;
//White we still have something to read
while (bytesRead < bytesToRead) {
//Read it from the stream
var bytesReceived = await networkStream.ReadAsync(buffer, bytesRead, (bytesToRead - bytesRead)).ConfigureAwait(false);
//If it happens to be 0 close the socket
if (bytesReceived == 0)
throw new Exception("Socket Closed");
bytesRead += bytesReceived;
}
return buffer;
}
/// <summary>
/// Encode the message from human readable to bytes for the stream
/// </summary>
/// <typeparam name="T">The message as anything e.g. object or string</typeparam>
/// <param name="message">The message to be send</param>
/// <returns>The Header and Body as bytes[]</returns>
protected (byte[] header, byte[] body) Encode<T>(T message) {
//Creates the body bytes
var bodyBytes = EncodeBody(message);
//Creates the header bytes
var headerBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bodyBytes.Length));
return (headerBytes, bodyBytes);
}
/// <summary>
/// Decode the message with the given type, json or xml
/// </summary>
/// <param name="message">The message to decode</param>
/// <returns>Decoded message</returns>
protected abstract TMessageType Decode(byte[] message);
/// <summary>
/// Validate the message length to combat attacks
/// </summary>
/// <param name="messageLength">The message length</param>
protected virtual void AssertValidMessageLength(int messageLength) {
//If its not 0 throw an exception
if (messageLength < 1)
throw new ArgumentOutOfRangeException("Invalid message length");
}
/// <summary>
/// Encode the message so it can be send via the network stream
/// </summary>
/// <typeparam name="T">Message type e.g. object or string</typeparam>
/// <param name="message">The message to be send</param>
/// <returns></returns>
protected abstract byte[] EncodeBody<T>(T message);
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace Server_Dashboard_Socket {
/// <summary>
/// Xml serialize class
/// </summary>
public class XmlMessageProtocol : Protocol<XDocument> {
/// <summary>
/// Decodes the message from byte[] to XDocument
/// </summary>
/// <param name="message">The message to decode</param>
/// <returns>Message as XDocument</returns>
protected override XDocument Decode(byte[] message) {
//Reads the data as utf8 string
var xmlData = Encoding.UTF8.GetString(message);
//Creates a new reader
var xmlReader = XmlReader.Create(new StringReader(xmlData), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore });
//Decodes the data to XDocument format
return XDocument.Load(xmlReader);
}
/// <summary>
/// Encode the XDocument to byte[]
/// </summary>
/// <typeparam name="T">Message type e.g. object or string</typeparam>
/// <param name="message">The message to encode</param>
/// <returns>Message as byte[]</returns>
protected override byte[] EncodeBody<T>(T message) {
//new string builder
StringBuilder sb = new StringBuilder();
//New string writer with the string builder
StringWriter sw = new StringWriter(sb);
//new xml serializer with the same type as the message
XmlSerializer xs = new XmlSerializer(typeof(T));
//Serialize the message to a regular string
xs.Serialize(sw, message);
//Return as UTF8 encoded byte array
return Encoding.UTF8.GetBytes(sb.ToString());
}
}
}

View File

@@ -5,4 +5,8 @@
<RootNamespace>Server_Dashboard_Socket</RootNamespace> <RootNamespace>Server_Dashboard_Socket</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project> </Project>

View File

@@ -7,9 +7,20 @@
"targets": { "targets": {
".NETCoreApp,Version=v3.1": { ".NETCoreApp,Version=v3.1": {
"Server Dashboard Socket/1.0.0": { "Server Dashboard Socket/1.0.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1"
},
"runtime": { "runtime": {
"Server Dashboard Socket.dll": {} "Server Dashboard Socket.dll": {}
} }
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
} }
} }
}, },
@@ -18,6 +29,13 @@
"type": "project", "type": "project",
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
} }
} }
} }

View File

@@ -1 +1 @@
40cb88c995736b43b2440aaa34383fa2c95563ea 8966ab4db41ed1e711f8adec4e833a86df6a665c

View File

@@ -43,6 +43,12 @@
"frameworks": { "frameworks": {
"netcoreapp3.1": { "netcoreapp3.1": {
"targetAlias": "netcoreapp3.1", "targetAlias": "netcoreapp3.1",
"dependencies": {
"Newtonsoft.Json": {
"target": "Package",
"version": "[13.0.1, )"
}
},
"imports": [ "imports": [
"net461", "net461",
"net462", "net462",

View File

@@ -1,11 +1,51 @@
{ {
"version": 3, "version": 3,
"targets": { "targets": {
".NETCoreApp,Version=v3.1": {} ".NETCoreApp,Version=v3.1": {
"Newtonsoft.Json/13.0.1": {
"type": "package",
"compile": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {}
}
}
}
},
"libraries": {
"Newtonsoft.Json/13.0.1": {
"sha512": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"type": "package",
"path": "newtonsoft.json/13.0.1",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.md",
"lib/net20/Newtonsoft.Json.dll",
"lib/net20/Newtonsoft.Json.xml",
"lib/net35/Newtonsoft.Json.dll",
"lib/net35/Newtonsoft.Json.xml",
"lib/net40/Newtonsoft.Json.dll",
"lib/net40/Newtonsoft.Json.xml",
"lib/net45/Newtonsoft.Json.dll",
"lib/net45/Newtonsoft.Json.xml",
"lib/netstandard1.0/Newtonsoft.Json.dll",
"lib/netstandard1.0/Newtonsoft.Json.xml",
"lib/netstandard1.3/Newtonsoft.Json.dll",
"lib/netstandard1.3/Newtonsoft.Json.xml",
"lib/netstandard2.0/Newtonsoft.Json.dll",
"lib/netstandard2.0/Newtonsoft.Json.xml",
"newtonsoft.json.13.0.1.nupkg.sha512",
"newtonsoft.json.nuspec",
"packageIcon.png"
]
}
}, },
"libraries": {},
"projectFileDependencyGroups": { "projectFileDependencyGroups": {
".NETCoreApp,Version=v3.1": [] ".NETCoreApp,Version=v3.1": [
"Newtonsoft.Json >= 13.0.1"
]
}, },
"packageFolders": { "packageFolders": {
"C:\\Users\\Crylia\\.nuget\\packages\\": {}, "C:\\Users\\Crylia\\.nuget\\packages\\": {},
@@ -50,6 +90,12 @@
"frameworks": { "frameworks": {
"netcoreapp3.1": { "netcoreapp3.1": {
"targetAlias": "netcoreapp3.1", "targetAlias": "netcoreapp3.1",
"dependencies": {
"Newtonsoft.Json": {
"target": "Package",
"version": "[13.0.1, )"
}
},
"imports": [ "imports": [
"net461", "net461",
"net462", "net462",

View File

@@ -1,8 +1,10 @@
{ {
"version": 2, "version": 2,
"dgSpecHash": "TThsag+xtSY7ctBsPwAhUX7uLjuhld1ipCW1nP987HRzxMfYvczqncYfdca/U4IfbiniWP3eJFeh7yA09+/gGA==", "dgSpecHash": "l9ApM4rx/nIquK7TUSE2VVfvhwnQ4+tycTwd5vMzM9v+MhFzGIKE8eVwCEj+r8Oe9Orh3cE/LeZlJ+t9G9ZaSg==",
"success": true, "success": true,
"projectFilePath": "C:\\Users\\Crylia\\Documents\\Git\\Server Dashboard\\Server Dashboard Socket\\Server Dashboard Socket.csproj", "projectFilePath": "C:\\Users\\Crylia\\Documents\\Git\\Server Dashboard\\Server Dashboard Socket\\Server Dashboard Socket.csproj",
"expectedPackageFiles": [], "expectedPackageFiles": [
"C:\\Users\\Crylia\\.nuget\\packages\\newtonsoft.json\\13.0.1\\newtonsoft.json.13.0.1.nupkg.sha512"
],
"logs": [] "logs": []
} }

View File

@@ -4,20 +4,28 @@
xmlns:local="clr-namespace:Server_Dashboard" xmlns:local="clr-namespace:Server_Dashboard"
xmlns:views="clr-namespace:Server_Dashboard.Views.DashboardPages" xmlns:views="clr-namespace:Server_Dashboard.Views.DashboardPages"
xmlns:modulescrud="clr-namespace:Server_Dashboard.Views.DashboardPages.ModuleCRUD" xmlns:modulescrud="clr-namespace:Server_Dashboard.Views.DashboardPages.ModuleCRUD"
xmlns:dashboardviews="clr-namespace:Server_Dashboard.Views.Dashboard"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
StartupUri="LoginWindow.xaml"> StartupUri="LoginWindow.xaml">
<Application.Resources> <Application.Resources>
<!--View Templates--> <!--View Templates-->
<DataTemplate x:Key="MainDashboardView" DataType="{x:Type local:DashboardViewModel}"> <DataTemplate DataType="{x:Type local:DashboardViewModel}">
<views:MainDashboardPage/> <views:MainDashboardPage />
</DataTemplate>
<DataTemplate DataType="{x:Type local:AnalyticsViewModel}">
<dashboardviews:AnalyticsPage />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SettingsViewModel}">
<dashboardviews:SettingsPage />
</DataTemplate> </DataTemplate>
<DataTemplate x:Key="CreateModuleView" DataType="{x:Type local:DashboardViewModel}"> <DataTemplate x:Key="CreateModuleView" DataType="{x:Type local:DashboardViewModel}">
<modulescrud:CreateModulePopup/> <modulescrud:CreateModulePopup />
</DataTemplate> </DataTemplate>
<!--Visibility converter for the login inputs--> <!--Visibility converter for the login inputs-->
<BooleanToVisibilityConverter x:Key="UserNameVisibillity"/> <BooleanToVisibilityConverter x:Key="UserNameVisibillity" />
<BooleanToVisibilityConverter x:Key="PasswordVisibillity"/> <BooleanToVisibilityConverter x:Key="PasswordVisibillity" />
<!--Fonts--> <!--Fonts-->
<FontFamily x:Key="Fontstyle" >Open Sans</FontFamily> <FontFamily x:Key="Fontstyle" >Open Sans</FontFamily>
@@ -41,87 +49,94 @@
Dragged = Overlay 8% + Shadow 08dp Dragged = Overlay 8% + Shadow 08dp
--> -->
<!--Material Colors--> <!--Material Colors-->
<SolidColorBrush x:Key="BackgroundSurface_00dp" Color="#121212"/> <SolidColorBrush x:Key="BackgroundSurface_00dp" Color="#121212" />
<SolidColorBrush x:Key="BackgroundSurface_01dp" Color="#1D1D1D"/> <SolidColorBrush x:Key="BackgroundSurface_01dp" Color="#1D1D1D" />
<SolidColorBrush x:Key="BackgroundSurface_02dp" Color="#202020"/> <SolidColorBrush x:Key="BackgroundSurface_02dp" Color="#202020" />
<SolidColorBrush x:Key="BackgroundSurface_03dp" Color="#252525"/> <SolidColorBrush x:Key="BackgroundSurface_03dp" Color="#252525" />
<SolidColorBrush x:Key="BackgroundSurface_04dp" Color="#262626"/> <SolidColorBrush x:Key="BackgroundSurface_04dp" Color="#262626" />
<SolidColorBrush x:Key="BackgroundSurface_06dp" Color="#2C2C2C"/> <SolidColorBrush x:Key="BackgroundSurface_06dp" Color="#2C2C2C" />
<SolidColorBrush x:Key="BackgroundSurface_08dp" Color="#2D2D2D"/> <SolidColorBrush x:Key="BackgroundSurface_08dp" Color="#2D2D2D" />
<SolidColorBrush x:Key="BackgroundSurface_12dp" Color="#323232"/> <SolidColorBrush x:Key="BackgroundSurface_12dp" Color="#323232" />
<SolidColorBrush x:Key="BackgroundSurface_16dp" Color="#343434"/> <SolidColorBrush x:Key="BackgroundSurface_16dp" Color="#343434" />
<SolidColorBrush x:Key="BackgroundSurface_24dp" Color="#363636"/> <SolidColorBrush x:Key="BackgroundSurface_24dp" Color="#363636" />
<SolidColorBrush x:Key="OnPrimarySecondaryError" Color="#000000"/> <SolidColorBrush x:Key="OnPrimarySecondaryError" Color="#000000" />
<SolidColorBrush x:Key="White" Color="#FFFFFFFF"/><!--0%--> <SolidColorBrush x:Key="White" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="White12" Color="#1EFFFFFF"/><!--12%--> <!--0%-->
<SolidColorBrush x:Key="White38" Color="#60FFFFFF"/><!--38%--> <SolidColorBrush x:Key="White12" Color="#1EFFFFFF" />
<SolidColorBrush x:Key="White60" Color="#99FFFFFF"/><!--60%--> <!--12%-->
<SolidColorBrush x:Key="White87" Color="#DEFFFFFF"/><!--87%--> <SolidColorBrush x:Key="White38" Color="#60FFFFFF" />
<SolidColorBrush x:Key="ErrorRed" Color="#CF6679"/> <!--38%-->
<SolidColorBrush x:Key="White60" Color="#99FFFFFF" />
<!--60%-->
<SolidColorBrush x:Key="White87" Color="#DEFFFFFF" />
<!--87%-->
<SolidColorBrush x:Key="ErrorRed" Color="#CF6679" />
<!--Indigo--> <!--Indigo-->
<SolidColorBrush x:Key="Indigo_50 " Color="#E8EAF6"/> <SolidColorBrush x:Key="Indigo_50 " Color="#E8EAF6" />
<SolidColorBrush x:Key="Indigo_100" Color="#C5CAE9"/> <SolidColorBrush x:Key="Indigo_100" Color="#C5CAE9" />
<SolidColorBrush x:Key="Indigo_200" Color="#9FA8DA"/> <SolidColorBrush x:Key="Indigo_200" Color="#9FA8DA" />
<SolidColorBrush x:Key="Indigo_300" Color="#7986CB"/> <SolidColorBrush x:Key="Indigo_300" Color="#7986CB" />
<SolidColorBrush x:Key="Indigo_400" Color="#5C6BC0"/> <SolidColorBrush x:Key="Indigo_400" Color="#5C6BC0" />
<SolidColorBrush x:Key="Indigo_500" Color="#3F51B5"/> <SolidColorBrush x:Key="Indigo_500" Color="#3F51B5" />
<SolidColorBrush x:Key="Indigo_600" Color="#3949AB"/> <SolidColorBrush x:Key="Indigo_600" Color="#3949AB" />
<SolidColorBrush x:Key="Indigo_700" Color="#303F9F"/> <SolidColorBrush x:Key="Indigo_700" Color="#303F9F" />
<SolidColorBrush x:Key="Indigo_800" Color="#283593"/> <SolidColorBrush x:Key="Indigo_800" Color="#283593" />
<SolidColorBrush x:Key="Indigo_900" Color="#1A237E"/> <SolidColorBrush x:Key="Indigo_900" Color="#1A237E" />
<SolidColorBrush x:Key="Indigo_A100" Color="#8C9EFF"/> <SolidColorBrush x:Key="Indigo_A100" Color="#8C9EFF" />
<SolidColorBrush x:Key="Indigo_A200" Color="#536DFE"/> <SolidColorBrush x:Key="Indigo_A200" Color="#536DFE" />
<SolidColorBrush x:Key="Indigo_A400" Color="#3D5AFE"/> <SolidColorBrush x:Key="Indigo_A400" Color="#3D5AFE" />
<SolidColorBrush x:Key="Indigo_A700" Color="#304FFE"/> <SolidColorBrush x:Key="Indigo_A700" Color="#304FFE" />
<!--Yellow--> <!--Yellow-->
<SolidColorBrush x:Key="Yellow_50 " Color="#FFFDE7"/> <SolidColorBrush x:Key="Yellow_50 " Color="#FFFDE7" />
<SolidColorBrush x:Key="Yellow_100" Color="#FFF9C4"/> <SolidColorBrush x:Key="Yellow_100" Color="#FFF9C4" />
<SolidColorBrush x:Key="Yellow_200" Color="#FFF59D"/> <SolidColorBrush x:Key="Yellow_200" Color="#FFF59D" />
<SolidColorBrush x:Key="Yellow_300" Color="#FFF176"/> <SolidColorBrush x:Key="Yellow_300" Color="#FFF176" />
<SolidColorBrush x:Key="Yellow_400" Color="#FFEE58"/> <SolidColorBrush x:Key="Yellow_400" Color="#FFEE58" />
<SolidColorBrush x:Key="Yellow_500" Color="#FFEB3B"/> <SolidColorBrush x:Key="Yellow_500" Color="#FFEB3B" />
<SolidColorBrush x:Key="Yellow_600" Color="#FDD835"/> <SolidColorBrush x:Key="Yellow_600" Color="#FDD835" />
<SolidColorBrush x:Key="Yellow_700" Color="#FBC02D"/> <SolidColorBrush x:Key="Yellow_700" Color="#FBC02D" />
<SolidColorBrush x:Key="Yellow_800" Color="#F9A825"/> <SolidColorBrush x:Key="Yellow_800" Color="#F9A825" />
<SolidColorBrush x:Key="Yellow_900" Color="#F57F17"/> <SolidColorBrush x:Key="Yellow_900" Color="#F57F17" />
<SolidColorBrush x:Key="Yellow_A100" Color="#FFFF8D"/> <SolidColorBrush x:Key="Yellow_A100" Color="#FFFF8D" />
<SolidColorBrush x:Key="Yellow_A200" Color="#FFFF00"/> <SolidColorBrush x:Key="Yellow_A200" Color="#FFFF00" />
<SolidColorBrush x:Key="Yellow_A400" Color="#FFEA00"/> <SolidColorBrush x:Key="Yellow_A400" Color="#FFEA00" />
<SolidColorBrush x:Key="Yellow_A700" Color="#FFD600"/> <SolidColorBrush x:Key="Yellow_A700" Color="#FFD600" />
<!--Deep Purple--> <!--Deep Purple-->
<SolidColorBrush x:Key="DeepPurple_50 " Color="#EDE7F6"/> <SolidColorBrush x:Key="DeepPurple_50 " Color="#EDE7F6" />
<SolidColorBrush x:Key="DeepPurple_100" Color="#D1C4E9"/> <SolidColorBrush x:Key="DeepPurple_100" Color="#D1C4E9" />
<SolidColorBrush x:Key="DeepPurple_200" Color="#B39DDB"/><!--Primary--> <SolidColorBrush x:Key="DeepPurple_200" Color="#B39DDB" />
<SolidColorBrush x:Key="DeepPurple_300" Color="#9575CD"/> <!--Primary-->
<SolidColorBrush x:Key="DeepPurple_400" Color="#7E57C2"/> <SolidColorBrush x:Key="DeepPurple_300" Color="#9575CD" />
<SolidColorBrush x:Key="DeepPurple_500" Color="#673AB7"/><!--Primary Variant--> <SolidColorBrush x:Key="DeepPurple_400" Color="#7E57C2" />
<SolidColorBrush x:Key="DeepPurple_600" Color="#5E35B1"/> <SolidColorBrush x:Key="DeepPurple_500" Color="#673AB7" />
<SolidColorBrush x:Key="DeepPurple_700" Color="#512DA8"/> <!--Primary Variant-->
<SolidColorBrush x:Key="DeepPurple_800" Color="#4527A0"/> <SolidColorBrush x:Key="DeepPurple_600" Color="#5E35B1" />
<SolidColorBrush x:Key="DeepPurple_900" Color="#311B92"/> <SolidColorBrush x:Key="DeepPurple_700" Color="#512DA8" />
<SolidColorBrush x:Key="DeepPurple_A100" Color="#B388FF"/> <SolidColorBrush x:Key="DeepPurple_800" Color="#4527A0" />
<SolidColorBrush x:Key="DeepPurple_A200" Color="#7C4DFF"/> <SolidColorBrush x:Key="DeepPurple_900" Color="#311B92" />
<SolidColorBrush x:Key="DeepPurple_A400" Color="#651FFF"/> <SolidColorBrush x:Key="DeepPurple_A100" Color="#B388FF" />
<SolidColorBrush x:Key="DeepPurple_A700" Color="#6200EA"/> <SolidColorBrush x:Key="DeepPurple_A200" Color="#7C4DFF" />
<SolidColorBrush x:Key="DeepPurple_A400" Color="#651FFF" />
<SolidColorBrush x:Key="DeepPurple_A700" Color="#6200EA" />
<!--Deep Purple--> <!--Deep Purple-->
<SolidColorBrush x:Key="Teal_50 " Color="#E0F2F1"/> <SolidColorBrush x:Key="Teal_50 " Color="#E0F2F1" />
<SolidColorBrush x:Key="Teal_100" Color="#B2DFDB"/> <SolidColorBrush x:Key="Teal_100" Color="#B2DFDB" />
<SolidColorBrush x:Key="Teal_200" Color="#80CBC4"/> <SolidColorBrush x:Key="Teal_200" Color="#80CBC4" />
<SolidColorBrush x:Key="Teal_300" Color="#4DB6AC"/> <SolidColorBrush x:Key="Teal_300" Color="#4DB6AC" />
<SolidColorBrush x:Key="Teal_400" Color="#26A69A"/> <SolidColorBrush x:Key="Teal_400" Color="#26A69A" />
<SolidColorBrush x:Key="Teal_500" Color="#009688"/> <SolidColorBrush x:Key="Teal_500" Color="#009688" />
<SolidColorBrush x:Key="Teal_600" Color="#00897B"/> <SolidColorBrush x:Key="Teal_600" Color="#00897B" />
<SolidColorBrush x:Key="Teal_700" Color="#00796B"/> <SolidColorBrush x:Key="Teal_700" Color="#00796B" />
<SolidColorBrush x:Key="Teal_800" Color="#00695C"/> <SolidColorBrush x:Key="Teal_800" Color="#00695C" />
<SolidColorBrush x:Key="Teal_900" Color="#004D40"/> <SolidColorBrush x:Key="Teal_900" Color="#004D40" />
<SolidColorBrush x:Key="Teal_A100" Color="#A7FFEB"/> <SolidColorBrush x:Key="Teal_A100" Color="#A7FFEB" />
<SolidColorBrush x:Key="Teal_A200" Color="#64FFDA"/> <SolidColorBrush x:Key="Teal_A200" Color="#64FFDA" />
<SolidColorBrush x:Key="Teal_A400" Color="#1DE9B6"/> <SolidColorBrush x:Key="Teal_A400" Color="#1DE9B6" />
<SolidColorBrush x:Key="Teal_A700" Color="#00BFA5"/> <SolidColorBrush x:Key="Teal_A700" Color="#00BFA5" />
<!--#endregion--> <!--#endregion-->
<!--=================--> <!--=================-->
@@ -130,40 +145,40 @@
<!--Textblock default design--> <!--Textblock default design-->
<Style TargetType="{x:Type TextBlock}"> <Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="{StaticResource White}"/> <Setter Property="Foreground" Value="{StaticResource White}" />
<Setter Property="FontFamily" Value="{StaticResource Fontstyle}"/> <Setter Property="FontFamily" Value="{StaticResource Fontstyle}" />
</Style> </Style>
<!--Button default design--> <!--Button default design-->
<Style TargetType="{x:Type Button}"> <Style TargetType="{x:Type Button}">
<Setter Property="Cursor" Value="Hand"/> <Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}"/> <Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}" />
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20" />
<Setter Property="FontFamily" Value="{StaticResource Fontstyle}"/> <Setter Property="FontFamily" Value="{StaticResource Fontstyle}" />
<Setter Property="Foreground" Value="{StaticResource DeepPurple_A100}"/> <Setter Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
<Setter Property="BorderThickness" Value="2"/> <Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type Button}"> <ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> <Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}"> <Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}">
<Border.BorderBrush> <Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush> </Border.BorderBrush>
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/> <TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border> </Border>
</Border> </Border>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04"/> <SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -172,12 +187,12 @@
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12"/> <SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter TargetName="BackgroundOverlay" Property="BorderBrush"> <Setter TargetName="BackgroundOverlay" Property="BorderBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87"/> <SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -191,61 +206,60 @@
<Style TargetType="{x:Type TextBox}"> <Style TargetType="{x:Type TextBox}">
<Setter Property="CaretBrush"> <Setter Property="CaretBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{StaticResource Fontstyle}"/> <Setter Property="FontFamily" Value="{StaticResource Fontstyle}" />
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20" />
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground"> <Setter Property="Foreground">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}"/> <Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}" />
<Setter Property="BorderThickness" Value="0"/> <Setter Property="BorderThickness" Value="0" />
</Style> </Style>
<!--Passwordbox default design--> <!--Passwordbox default design-->
<Style TargetType="{x:Type PasswordBox}"> <Style TargetType="{x:Type PasswordBox}">
<Setter Property="PasswordChar" Value="*"/> <Setter Property="PasswordChar" Value="*" />
<Setter Property="CaretBrush"> <Setter Property="CaretBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Arial"/> <Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20" />
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground"> <Setter Property="Foreground">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="BorderBrush"> <Setter Property="BorderBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}"/> <Setter Property="Background" Value="{StaticResource BackgroundSurface_01dp}" />
<Setter Property="BorderThickness" Value="0"/> <Setter Property="BorderThickness" Value="0" />
</Style> </Style>
<!--Checkbox default design--> <!--Checkbox default design-->
<Style TargetType="{x:Type CheckBox}"> <Style TargetType="{x:Type CheckBox}">
<Setter Property="SnapsToDevicePixels" Value="true"/> <Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true"/> <Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="White"/> <Setter Property="Foreground" Value="White" />
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="Cursor" Value="Hand" />
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Effect"> <Setter Property="Effect">
<Setter.Value> <Setter.Value>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="Template"> <Setter Property="Template">
@@ -259,11 +273,11 @@
</Border> </Border>
</Border> </Border>
</BulletDecorator.Bullet> </BulletDecorator.Bullet>
<ContentPresenter Margin="4,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True"/> <ContentPresenter Margin="4,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True" />
</BulletDecorator> </BulletDecorator>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="false"> <Trigger Property="IsChecked" Value="false">
<Setter TargetName="CheckMark" Property="Visibility" Value="Collapsed"/> <Setter TargetName="CheckMark" Property="Visibility" Value="Collapsed" />
</Trigger> </Trigger>
<Trigger Property="IsChecked" Value="{x:Null}"> <Trigger Property="IsChecked" Value="{x:Null}">
<Setter TargetName="CheckMark" Property="Data" Value="M 0 20 L 20 0" /> <Setter TargetName="CheckMark" Property="Data" Value="M 0 20 L 20 0" />
@@ -271,18 +285,18 @@
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background"> <Setter TargetName="Border" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04"/> <SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
<Trigger Property="IsEnabled" Value="false"> <Trigger Property="IsEnabled" Value="false">
<Setter TargetName="CheckMark" Property="Stroke" Value="#FF6C6C6C"/> <Setter TargetName="CheckMark" Property="Stroke" Value="#FF6C6C6C" />
<Setter Property="Foreground" Value="Gray"/> <Setter Property="Foreground" Value="Gray" />
</Trigger> </Trigger>
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background"> <Setter TargetName="Border" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12"/> <SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -294,18 +308,18 @@
<!--Hyperlink default design--> <!--Hyperlink default design-->
<Style TargetType="{x:Type Hyperlink}"> <Style TargetType="{x:Type Hyperlink}">
<Setter Property="TextDecorations" Value="None"/> <Setter Property="TextDecorations" Value="None" />
<Setter Property="Cursor" Value="Hand"/> <Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground"> <Setter Property="Foreground">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#64FFDA" Opacity="0.64"/> <SolidColorBrush Color="#64FFDA" Opacity="0.64" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Style.Triggers> <Style.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground"> <Setter Property="Foreground">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#64FFDA" Opacity="0.87"/> <SolidColorBrush Color="#64FFDA" Opacity="0.87" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -314,14 +328,14 @@
<!--Border default design (Makes text rendering in it crystal clear)--> <!--Border default design (Makes text rendering in it crystal clear)-->
<Style TargetType="Border"> <Style TargetType="Border">
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="UseLayoutRounding" Value="True"/> <Setter Property="UseLayoutRounding" Value="True" />
</Style> </Style>
<!--Grid default design (Makes text rendering in it crystal clear)--> <!--Grid default design (Makes text rendering in it crystal clear)-->
<Style TargetType="Grid"> <Style TargetType="Grid">
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="UseLayoutRounding" Value="True"/> <Setter Property="UseLayoutRounding" Value="True" />
</Style> </Style>
<!--================--> <!--================-->
@@ -330,26 +344,26 @@
<!--Close button design--> <!--Close button design-->
<Style x:Key="CloseButton" TargetType="{x:Type Button}"> <Style x:Key="CloseButton" TargetType="{x:Type Button}">
<Setter Property="Cursor" Value="Hand"/> <Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground"> <Setter Property="Foreground">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter Property="BorderThickness" Value="0"/> <Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type Button}"> <ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center"/> <TextBlock TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border> </Border>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/> <Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="{StaticResource BackgroundSurface_00dp}"/> <Setter Property="Foreground" Value="{StaticResource BackgroundSurface_00dp}" />
</Trigger> </Trigger>
</ControlTemplate.Triggers> </ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -1,11 +0,0 @@
<svg width="48.00000000000001" height="48.00000000000001" xmlns="http://www.w3.org/2000/svg">
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="402" width="582" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<path fill="#ffffff" id="svg_1" fill-rule="evenodd" d="m37,47l-26,0c-2.209,0 -4,-1.791 -4,-4l0,-38c0,-2.209 1.791,-4 4,-4l18.973,0c0.002,0 0.005,0 0.007,0l0.02,0l0,0c0.32,0 0.593,0.161 0.776,0.395l9.829,9.829c0.235,0.183 0.395,0.456 0.395,0.776l0,0l0,0.021c0,0.002 0,0.003 0,0.005l0,30.974c0,2.209 -1.791,4 -4,4zm-6,-42.619l0,6.619l6.619,0l-6.619,-6.619zm8,8.619l-9,0c-0.553,0 -1,-0.448 -1,-1l0,-9l-18,0c-1.104,0 -2,0.896 -2,2l0,38c0,1.104 0.896,2 2,2l26,0c1.104,0 2,-0.896 2,-2l0,-30zm-6,26l-18,0c-0.553,0 -1,-0.447 -1,-1c0,-0.552 0.447,-1 1,-1l18,0c0.553,0 1,0.448 1,1c0,0.553 -0.447,1 -1,1zm0,-8l-18,0c-0.553,0 -1,-0.447 -1,-1c0,-0.552 0.447,-1 1,-1l18,0c0.553,0 1,0.448 1,1c0,0.553 -0.447,1 -1,1zm0,-8l-18,0c-0.553,0 -1,-0.447 -1,-1c0,-0.552 0.447,-1 1,-1l18,0c0.553,0 1,0.448 1,1c0,0.553 -0.447,1 -1,1z" clip-rule="evenodd"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -1,483 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
xml:space="preserve"
width="707.96399"
height="735.98132"
viewBox="0 0 707.96399 735.98132"
sodipodi:docname="GitHub-Mark.ai"><metadata
id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs6"><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath20"><path
d="M 0,551.986 H 530.973 V 0 H 0 Z"
id="path18" /></clipPath></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview4" /><g
id="g10"
inkscape:groupmode="layer"
inkscape:label="GitHub-Mark"
transform="matrix(1.3333333,0,0,-1.3333333,0,735.98133)"><path
d="M 0,0 H 530.973 V 275.986 H 0 Z"
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path12" /><g
id="g14"><g
id="g16"
clip-path="url(#clipPath20)"><g
id="g22"
transform="translate(152.6083,444.5454)"><path
d="m 0,0 c -8.995,0 -16.288,-7.293 -16.288,-16.29 0,-7.197 4.667,-13.302 11.14,-15.457 0.815,-0.149 1.112,0.354 1.112,0.786 0,0.386 -0.014,1.411 -0.022,2.77 -4.531,-0.984 -5.487,2.184 -5.487,2.184 -0.741,1.881 -1.809,2.382 -1.809,2.382 -1.479,1.011 0.112,0.991 0.112,0.991 1.635,-0.116 2.495,-1.679 2.495,-1.679 1.453,-2.489 3.813,-1.77 4.741,-1.354 0.148,1.053 0.568,1.771 1.034,2.178 -3.617,0.411 -7.42,1.809 -7.42,8.051 0,1.778 0.635,3.232 1.677,4.371 -0.168,0.412 -0.727,2.068 0.159,4.311 0,0 1.368,0.438 4.48,-1.67 1.299,0.361 2.693,0.542 4.078,0.548 1.383,-0.006 2.777,-0.187 4.078,-0.548 3.11,2.108 4.475,1.67 4.475,1.67 0.889,-2.243 0.33,-3.899 0.162,-4.311 1.044,-1.139 1.675,-2.593 1.675,-4.371 0,-6.258 -3.809,-7.635 -7.438,-8.038 0.585,-0.503 1.106,-1.497 1.106,-3.017 0,-2.177 -0.02,-3.934 -0.02,-4.468 0,-0.436 0.293,-0.943 1.12,-0.784 6.468,2.159 11.131,8.26 11.131,15.455 C 16.291,-7.293 8.997,0 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path24" /></g><g
id="g26"
transform="translate(350.6088,493.5547)"><path
d="m 0,0 c -33.347,0 -60.388,-27.035 -60.388,-60.388 0,-26.68 17.303,-49.316 41.297,-57.301 3.018,-0.559 4.126,1.31 4.126,2.905 0,1.439 -0.056,6.197 -0.082,11.243 -16.8,-3.653 -20.345,7.125 -20.345,7.125 -2.747,6.979 -6.705,8.836 -6.705,8.836 -5.479,3.748 0.413,3.671 0.413,3.671 6.064,-0.426 9.257,-6.224 9.257,-6.224 5.386,-9.231 14.127,-6.562 17.573,-5.019 0.543,3.902 2.107,6.567 3.834,8.075 -13.413,1.526 -27.513,6.705 -27.513,29.844 0,6.592 2.359,11.98 6.222,16.209 -0.627,1.521 -2.694,7.663 0.586,15.981 0,0 5.071,1.622 16.61,-6.191 4.817,1.338 9.983,2.009 15.115,2.033 5.132,-0.024 10.302,-0.695 15.128,-2.033 11.526,7.813 16.59,6.191 16.59,6.191 3.287,-8.318 1.22,-14.46 0.593,-15.981 3.872,-4.229 6.214,-9.617 6.214,-16.209 0,-23.195 -14.127,-28.301 -27.574,-29.796 2.166,-1.874 4.096,-5.549 4.096,-11.183 0,-8.08 -0.069,-14.583 -0.069,-16.572 0,-1.608 1.086,-3.49 4.147,-2.898 23.982,7.994 41.263,30.622 41.263,57.294 C 60.388,-27.035 33.351,0 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path28" /></g><g
id="g30"
transform="translate(313.0932,406.8515)"><path
d="m 0,0 c -0.133,-0.301 -0.605,-0.391 -1.035,-0.185 -0.439,0.198 -0.684,0.607 -0.542,0.908 0.13,0.308 0.602,0.394 1.04,0.188 C -0.099,0.714 0.151,0.301 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path32" /></g><g
id="g34"
transform="translate(315.5395,404.123)"><path
d="M 0,0 C -0.288,-0.267 -0.852,-0.143 -1.233,0.279 -1.629,0.7 -1.702,1.264 -1.41,1.534 -1.113,1.801 -0.567,1.676 -0.172,1.255 0.224,0.829 0.301,0.271 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path36" /></g><g
id="g38"
transform="translate(317.9204,400.6455)"><path
d="M 0,0 C -0.37,-0.258 -0.976,-0.017 -1.35,0.52 -1.72,1.058 -1.72,1.702 -1.341,1.96 -0.967,2.218 -0.37,1.985 0.009,1.453 0.378,0.907 0.378,0.263 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path40" /></g><g
id="g42"
transform="translate(321.1821,397.2851)"><path
d="M 0,0 C -0.331,-0.365 -1.036,-0.267 -1.552,0.232 -2.08,0.718 -2.227,1.409 -1.896,1.774 -1.56,2.14 -0.851,2.037 -0.331,1.543 0.193,1.057 0.352,0.361 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path44" /></g><g
id="g46"
transform="translate(325.6821,395.334)"><path
d="m 0,0 c -0.147,-0.473 -0.825,-0.687 -1.509,-0.486 -0.683,0.207 -1.13,0.76 -0.992,1.238 0.142,0.476 0.824,0.7 1.513,0.485 C -0.306,1.031 0.142,0.481 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path48" /></g><g
id="g50"
transform="translate(330.6245,394.9726)"><path
d="m 0,0 c 0.017,-0.498 -0.563,-0.911 -1.281,-0.92 -0.722,-0.016 -1.307,0.387 -1.315,0.877 0,0.503 0.568,0.911 1.289,0.924 C -0.589,0.895 0,0.494 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path52" /></g><g
id="g54"
transform="translate(335.2231,395.7549)"><path
d="m 0,0 c 0.086,-0.485 -0.413,-0.984 -1.126,-1.117 -0.701,-0.129 -1.35,0.172 -1.439,0.653 -0.087,0.498 0.42,0.997 1.121,1.126 C -0.73,0.786 -0.091,0.494 0,0"
style="fill:#1b1817;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path56" /></g><g
id="g58"
transform="translate(224.8979,499.4882)"><path
d="M 0,0 V -0.5"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path60" /></g><g
id="g62"
transform="translate(224.8979,496.9882)"><path
d="M 0,0 V -133.993"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1"
id="path64" /></g><g
id="g66"
transform="translate(224.8979,361.9951)"><path
d="M 0,0 V -0.5"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path68" /></g><g
id="g70"
transform="translate(133.2758,347.4795)"><path
d="m 0,0 c -0.38,0.276 -0.866,0.414 -1.458,0.414 -0.24,0 -0.476,-0.024 -0.708,-0.071 -0.232,-0.049 -0.438,-0.129 -0.618,-0.24 -0.18,-0.114 -0.324,-0.263 -0.432,-0.452 -0.108,-0.187 -0.162,-0.421 -0.162,-0.701 0,-0.264 0.078,-0.478 0.234,-0.642 0.156,-0.165 0.364,-0.298 0.624,-0.402 0.26,-0.104 0.554,-0.19 0.882,-0.259 0.328,-0.067 0.662,-0.141 1.002,-0.22 0.34,-0.08 0.674,-0.175 1.002,-0.284 C 0.694,-2.964 0.988,-3.11 1.248,-3.294 1.508,-3.478 1.716,-3.71 1.872,-3.989 2.028,-4.27 2.106,-4.622 2.106,-5.046 2.106,-5.502 2.004,-5.892 1.8,-6.216 1.596,-6.54 1.334,-6.804 1.014,-7.008 0.694,-7.212 0.336,-7.36 -0.06,-7.452 -0.456,-7.544 -0.85,-7.59 -1.242,-7.59 c -0.48,0 -0.934,0.06 -1.362,0.18 -0.428,0.12 -0.804,0.302 -1.128,0.546 -0.324,0.244 -0.58,0.556 -0.768,0.936 -0.188,0.38 -0.282,0.829 -0.282,1.35 h 1.08 c 0,-0.361 0.07,-0.67 0.21,-0.93 0.14,-0.261 0.324,-0.474 0.552,-0.642 0.228,-0.167 0.494,-0.292 0.798,-0.372 0.304,-0.081 0.616,-0.12 0.936,-0.12 0.256,0 0.514,0.024 0.774,0.073 0.26,0.047 0.494,0.129 0.702,0.246 0.208,0.115 0.376,0.273 0.504,0.472 0.128,0.201 0.192,0.457 0.192,0.769 0,0.296 -0.078,0.536 -0.234,0.72 -0.156,0.183 -0.364,0.334 -0.624,0.45 -0.26,0.116 -0.554,0.21 -0.882,0.282 -0.328,0.072 -0.662,0.147 -1.002,0.223 -0.34,0.075 -0.674,0.163 -1.002,0.263 -0.328,0.1 -0.622,0.232 -0.882,0.396 -0.26,0.164 -0.468,0.376 -0.624,0.636 -0.156,0.259 -0.234,0.586 -0.234,0.978 0,0.432 0.088,0.806 0.264,1.122 0.176,0.316 0.41,0.575 0.702,0.78 0.292,0.204 0.624,0.356 0.996,0.456 0.372,0.1 0.754,0.15 1.146,0.15 0.44,0 0.848,-0.053 1.224,-0.156 C 0.19,1.114 0.52,0.95 0.804,0.725 1.088,0.502 1.312,0.22 1.476,-0.12 1.64,-0.46 1.73,-0.866 1.746,-1.338 H 0.666 C 0.602,-0.722 0.38,-0.276 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path72" /></g><g
id="g74"
transform="translate(137.5537,346.2851)"><path
d="m 0,0 v -0.912 h 0.024 c 0.464,0.705 1.132,1.057 2.004,1.057 0.384,0 0.732,-0.08 1.044,-0.241 0.312,-0.16 0.532,-0.431 0.66,-0.816 0.208,0.336 0.482,0.596 0.822,0.78 0.34,0.185 0.714,0.277 1.122,0.277 0.312,0 0.594,-0.035 0.846,-0.102 0.252,-0.068 0.468,-0.175 0.648,-0.318 0.18,-0.145 0.32,-0.33 0.42,-0.559 0.1,-0.227 0.15,-0.502 0.15,-0.822 V -6.203 H 6.72 v 4.067 c 0,0.193 -0.016,0.372 -0.048,0.54 -0.032,0.168 -0.092,0.315 -0.18,0.438 -0.088,0.125 -0.21,0.223 -0.366,0.295 -0.156,0.072 -0.358,0.107 -0.606,0.107 -0.504,0 -0.9,-0.143 -1.188,-0.431 C 4.044,-1.476 3.9,-1.859 3.9,-2.34 V -6.203 H 2.88 v 4.067 c 0,0.201 -0.018,0.384 -0.054,0.552 -0.036,0.168 -0.098,0.314 -0.186,0.438 -0.088,0.125 -0.206,0.22 -0.354,0.289 -0.148,0.068 -0.338,0.101 -0.57,0.101 -0.296,0 -0.55,-0.059 -0.762,-0.179 C 0.742,-1.056 0.57,-1.199 0.438,-1.367 0.306,-1.535 0.21,-1.709 0.15,-1.89 0.09,-2.07 0.06,-2.22 0.06,-2.34 V -6.203 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path76" /></g><g
id="g78"
transform="translate(150.1655,343.0761)"><path
d="m 0,0 c -0.208,-0.045 -0.426,-0.08 -0.654,-0.108 -0.228,-0.029 -0.458,-0.06 -0.69,-0.097 -0.232,-0.035 -0.44,-0.094 -0.624,-0.174 -0.184,-0.08 -0.334,-0.193 -0.45,-0.342 -0.116,-0.148 -0.174,-0.349 -0.174,-0.605 0,-0.168 0.034,-0.311 0.102,-0.426 0.068,-0.117 0.156,-0.211 0.264,-0.283 0.108,-0.071 0.236,-0.123 0.384,-0.155 0.148,-0.033 0.298,-0.048 0.45,-0.048 0.336,0 0.624,0.045 0.864,0.137 0.24,0.092 0.436,0.208 0.588,0.349 0.152,0.139 0.264,0.291 0.336,0.455 0.072,0.164 0.108,0.318 0.108,0.463 V 0.209 C 0.376,0.113 0.208,0.043 0,0 m 1.428,-3.127 c -0.264,0 -0.474,0.074 -0.63,0.223 -0.156,0.147 -0.234,0.389 -0.234,0.725 -0.28,-0.336 -0.606,-0.578 -0.978,-0.725 -0.372,-0.149 -0.774,-0.223 -1.206,-0.223 -0.28,0 -0.544,0.03 -0.792,0.09 -0.248,0.06 -0.466,0.16 -0.654,0.301 -0.188,0.139 -0.336,0.319 -0.444,0.539 -0.108,0.22 -0.162,0.486 -0.162,0.799 0,0.351 0.06,0.639 0.18,0.863 0.12,0.224 0.278,0.406 0.474,0.547 0.196,0.139 0.42,0.246 0.672,0.318 0.252,0.071 0.51,0.131 0.774,0.18 0.28,0.055 0.546,0.097 0.798,0.125 0.252,0.028 0.474,0.068 0.666,0.121 0.192,0.051 0.344,0.127 0.456,0.227 0.112,0.101 0.168,0.246 0.168,0.439 0,0.223 -0.042,0.403 -0.126,0.539 -0.084,0.137 -0.192,0.24 -0.324,0.312 -0.132,0.073 -0.28,0.121 -0.444,0.145 -0.164,0.023 -0.326,0.035 -0.486,0.035 -0.432,0 -0.792,-0.082 -1.08,-0.246 -0.288,-0.164 -0.444,-0.474 -0.468,-0.93 h -1.02 c 0.016,0.384 0.096,0.708 0.24,0.973 0.144,0.264 0.336,0.478 0.576,0.642 0.24,0.163 0.516,0.282 0.828,0.354 0.312,0.071 0.64,0.108 0.984,0.108 0.28,0 0.558,-0.02 0.834,-0.061 C 0.306,3.254 0.556,3.172 0.78,3.047 1.004,2.924 1.184,2.749 1.32,2.525 1.456,2.301 1.524,2.01 1.524,1.649 v -3.192 c 0,-0.24 0.014,-0.416 0.042,-0.527 0.028,-0.113 0.122,-0.168 0.282,-0.168 0.088,0 0.192,0.019 0.312,0.059 V -2.971 C 1.984,-3.074 1.74,-3.127 1.428,-3.127"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path80" /></g><path
d="m 154.354,340.082 h -1.02 v 8.567 h 1.02 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path82" /><path
d="m 157.017,340.082 h -1.02 v 8.567 h 1.02 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path84" /><g
id="g86"
transform="translate(101.854,330.9863)"><path
d="m 0,0 v 0.899 h 1.044 v 0.924 c 0,0.504 0.146,0.886 0.438,1.146 0.292,0.26 0.718,0.39 1.278,0.39 0.096,0 0.206,-0.007 0.33,-0.023 C 3.214,3.319 3.324,3.295 3.42,3.264 V 2.375 C 3.332,2.407 3.236,2.43 3.132,2.441 3.028,2.453 2.932,2.459 2.844,2.459 2.596,2.459 2.404,2.411 2.268,2.315 2.132,2.219 2.064,2.035 2.064,1.764 V 0.899 h 1.2 V 0 h -1.2 V -5.305 H 1.044 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path88" /></g><g
id="g90"
transform="translate(106.9238,327.7754)"><path
d="m 0,0 c 0.1,-0.292 0.238,-0.535 0.414,-0.732 0.176,-0.196 0.382,-0.346 0.618,-0.45 0.236,-0.103 0.486,-0.156 0.75,-0.156 0.264,0 0.514,0.053 0.75,0.156 0.236,0.104 0.442,0.254 0.618,0.45 0.176,0.197 0.314,0.44 0.414,0.732 0.1,0.292 0.15,0.626 0.15,1.002 0,0.377 -0.05,0.71 -0.15,1.002 C 3.464,2.297 3.326,2.542 3.15,2.742 2.974,2.941 2.768,3.094 2.532,3.198 2.296,3.303 2.046,3.355 1.782,3.355 1.518,3.355 1.268,3.303 1.032,3.198 0.796,3.094 0.59,2.941 0.414,2.742 0.238,2.542 0.1,2.297 0,2.004 -0.1,1.712 -0.15,1.379 -0.15,1.002 -0.15,0.626 -0.1,0.292 0,0 m -1.038,2.28 c 0.128,0.396 0.32,0.74 0.576,1.033 0.256,0.291 0.572,0.521 0.948,0.689 0.376,0.168 0.808,0.252 1.296,0.252 0.496,0 0.93,-0.084 1.302,-0.252 C 3.456,3.834 3.77,3.604 4.026,3.313 4.282,3.02 4.474,2.676 4.602,2.28 4.73,1.885 4.794,1.458 4.794,1.002 4.794,0.547 4.73,0.122 4.602,-0.27 4.474,-0.662 4.282,-1.004 4.026,-1.296 3.77,-1.588 3.456,-1.816 3.084,-1.98 2.712,-2.144 2.278,-2.226 1.782,-2.226 c -0.488,0 -0.92,0.082 -1.296,0.246 -0.376,0.164 -0.692,0.392 -0.948,0.684 -0.256,0.292 -0.448,0.634 -0.576,1.026 -0.128,0.392 -0.192,0.817 -0.192,1.272 0,0.456 0.064,0.883 0.192,1.278"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path92" /></g><g
id="g94"
transform="translate(113.8417,331.8857)"><path
d="m 0,0 v -1.308 h 0.024 c 0.248,0.504 0.552,0.875 0.912,1.116 0.36,0.24 0.816,0.351 1.368,0.336 V -0.937 C 1.896,-0.937 1.548,-0.992 1.26,-1.105 0.972,-1.216 0.74,-1.38 0.564,-1.597 0.388,-1.812 0.26,-2.074 0.18,-2.382 0.1,-2.69 0.06,-3.044 0.06,-3.444 v -2.76 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path96" /></g><g
id="g98"
transform="translate(122.7333,325.6816)"><path
d="m 0,0 v 6.096 h -2.208 v 0.816 c 0.288,0 0.568,0.022 0.84,0.066 0.272,0.043 0.518,0.125 0.738,0.247 0.22,0.119 0.406,0.283 0.558,0.491 C 0.08,7.924 0.184,8.188 0.24,8.508 H 1.02 L 1.02,0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path100" /></g><g
id="g102"
transform="translate(128.8295,330.1035)"><path
d="m 0,0 c -0.216,-0.1 -0.4,-0.236 -0.552,-0.408 -0.152,-0.172 -0.266,-0.376 -0.341,-0.611 -0.077,-0.237 -0.115,-0.487 -0.115,-0.75 0,-0.264 0.04,-0.512 0.12,-0.745 0.08,-0.232 0.194,-0.431 0.342,-0.599 0.148,-0.168 0.332,-0.303 0.552,-0.403 0.22,-0.1 0.47,-0.15 0.75,-0.15 0.28,0 0.526,0.05 0.738,0.15 0.212,0.1 0.39,0.239 0.534,0.414 0.144,0.176 0.254,0.378 0.33,0.606 0.076,0.228 0.114,0.467 0.114,0.715 0,0.263 -0.034,0.513 -0.102,0.75 C 2.302,-0.796 2.196,-0.592 2.052,-0.42 1.908,-0.248 1.728,-0.109 1.512,-0.006 1.296,0.098 1.044,0.15 0.756,0.15 0.468,0.15 0.216,0.1 0,0 M 1.848,2.838 C 1.6,3.07 1.272,3.186 0.864,3.186 0.432,3.186 0.084,3.08 -0.18,2.868 -0.444,2.656 -0.65,2.389 -0.798,2.064 -0.946,1.74 -1.048,1.391 -1.104,1.014 -1.16,0.639 -1.192,0.286 -1.2,-0.042 l 0.024,-0.024 c 0.24,0.392 0.538,0.675 0.894,0.852 0.356,0.176 0.766,0.265 1.23,0.265 0.408,0 0.774,-0.07 1.098,-0.211 C 2.37,0.7 2.642,0.506 2.862,0.258 3.082,0.01 3.253,-0.281 3.372,-0.617 3.492,-0.954 3.552,-1.318 3.552,-1.71 3.552,-2.021 3.504,-2.346 3.408,-2.682 3.312,-3.018 3.154,-3.324 2.934,-3.6 2.714,-3.876 2.422,-4.103 2.058,-4.283 1.694,-4.464 1.244,-4.554 0.708,-4.554 c -0.632,0 -1.14,0.128 -1.524,0.384 -0.384,0.256 -0.68,0.584 -0.888,0.984 -0.208,0.4 -0.346,0.84 -0.414,1.321 -0.068,0.479 -0.102,0.943 -0.102,1.391 0,0.583 0.05,1.15 0.15,1.699 0.1,0.547 0.27,1.033 0.511,1.457 C -1.32,3.106 -1,3.445 -0.6,3.702 -0.2,3.958 0.304,4.086 0.912,4.086 1.616,4.086 2.176,3.9 2.592,3.528 3.008,3.156 3.248,2.618 3.312,1.914 H 2.292 C 2.244,2.299 2.096,2.606 1.848,2.838"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path104" /></g><g
id="g106"
transform="translate(138.3159,329.6836)"><path
d="m 0,0 c -0.076,0.275 -0.192,0.521 -0.348,0.738 -0.156,0.216 -0.356,0.388 -0.6,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.876,-0.204 -0.24,-0.137 -0.436,-0.314 -0.588,-0.534 -0.152,-0.22 -0.262,-0.47 -0.33,-0.75 -0.069,-0.28 -0.102,-0.563 -0.102,-0.853 0,-0.303 0.036,-0.597 0.108,-0.88 0.071,-0.286 0.186,-0.536 0.341,-0.75 0.157,-0.217 0.358,-0.391 0.607,-0.523 0.247,-0.132 0.548,-0.198 0.9,-0.198 0.351,0 0.646,0.068 0.882,0.204 0.236,0.136 0.425,0.315 0.569,0.54 0.145,0.224 0.249,0.481 0.312,0.768 0.064,0.289 0.097,0.584 0.097,0.888 C 0.114,-0.559 0.076,-0.275 0,0 M -3.666,2.202 V 1.361 h 0.024 c 0.168,0.345 0.431,0.595 0.792,0.75 0.36,0.157 0.756,0.235 1.188,0.235 0.48,0 0.898,-0.088 1.254,-0.264 C -0.052,1.906 0.244,1.668 0.48,1.368 0.716,1.068 0.893,0.722 1.014,0.33 c 0.12,-0.392 0.18,-0.809 0.18,-1.248 0,-0.439 -0.058,-0.855 -0.175,-1.248 C 0.904,-2.559 0.727,-2.9 0.492,-3.191 0.256,-3.484 -0.041,-3.714 -0.396,-3.882 -0.753,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.153,0 -0.323,0.017 -0.511,0.048 -0.188,0.032 -0.374,0.084 -0.557,0.156 -0.184,0.073 -0.359,0.17 -0.522,0.294 -0.164,0.124 -0.302,0.279 -0.414,0.462 h -0.024 v -3.191 h -1.02 v 8.567 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path108" /></g><g
id="g110"
transform="translate(140.2172,331.8857)"><path
d="M 0,0 H 1.308 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.856 2.4,-3.348 H 4.524 L 2.796,-3.636 1.068,-6.204 H -0.168 L 2.16,-2.94 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path112" /></g><path
d="m 150.225,328.537 h -3.468 v 0.961 h 3.468 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path114" /><g
id="g116"
transform="translate(154.0771,325.6816)"><path
d="m 0,0 v 6.096 h -2.208 v 0.816 c 0.288,0 0.568,0.022 0.84,0.066 0.272,0.043 0.518,0.125 0.738,0.247 0.22,0.119 0.406,0.283 0.558,0.491 C 0.08,7.924 0.184,8.188 0.24,8.508 H 1.02 L 1.02,0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path118" /></g><g
id="g120"
transform="translate(158.1572,332.3769)"><path
d="m 0,0 c 0.112,0.369 0.286,0.686 0.522,0.955 0.236,0.268 0.53,0.478 0.882,0.629 0.352,0.152 0.752,0.228 1.2,0.228 0.368,0 0.714,-0.053 1.038,-0.162 C 3.966,1.543 4.248,1.387 4.488,1.183 4.728,0.979 4.918,0.725 5.058,0.421 5.198,0.117 5.268,-0.235 5.268,-0.635 5.268,-1.012 5.21,-1.344 5.094,-1.631 4.977,-1.92 4.824,-2.178 4.632,-2.405 4.44,-2.633 4.22,-2.84 3.972,-3.023 3.724,-3.207 3.468,-3.383 3.204,-3.551 2.94,-3.711 2.676,-3.869 2.412,-4.025 2.148,-4.182 1.906,-4.348 1.686,-4.523 1.466,-4.699 1.278,-4.889 1.122,-5.094 0.966,-5.297 0.864,-5.531 0.816,-5.795 h 4.368 v -0.9 h -5.556 c 0.04,0.504 0.13,0.933 0.27,1.29 0.14,0.356 0.318,0.666 0.534,0.93 0.216,0.264 0.46,0.496 0.732,0.696 0.272,0.199 0.556,0.387 0.852,0.564 0.36,0.224 0.676,0.43 0.948,0.617 0.272,0.188 0.498,0.379 0.678,0.571 0.18,0.191 0.316,0.4 0.408,0.624 0.092,0.223 0.138,0.483 0.138,0.78 0,0.231 -0.045,0.441 -0.132,0.63 C 3.968,0.194 3.85,0.357 3.702,0.492 3.554,0.629 3.38,0.732 3.18,0.805 2.98,0.877 2.768,0.912 2.544,0.912 2.247,0.912 1.994,0.851 1.782,0.727 1.57,0.603 1.396,0.441 1.26,0.24 1.124,0.041 1.026,-0.185 0.966,-0.437 0.906,-0.689 0.88,-0.943 0.888,-1.199 h -1.02 C -0.156,-0.768 -0.112,-0.367 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path122" /></g><g
id="g124"
transform="translate(165.7832,328.7949)"><path
d="m 0,0 c 0.02,-0.395 0.084,-0.768 0.192,-1.115 0.108,-0.348 0.282,-0.643 0.522,-0.882 0.24,-0.24 0.576,-0.36 1.008,-0.36 0.432,0 0.768,0.12 1.008,0.36 0.24,0.239 0.414,0.534 0.522,0.882 0.108,0.347 0.172,0.72 0.192,1.115 0.02,0.397 0.03,0.755 0.03,1.074 0,0.209 -0.002,0.439 -0.006,0.691 C 3.464,2.017 3.444,2.268 3.408,2.521 3.372,2.773 3.32,3.018 3.252,3.259 3.184,3.498 3.084,3.709 2.952,3.889 2.82,4.068 2.654,4.215 2.454,4.326 2.254,4.439 2.01,4.494 1.722,4.494 1.434,4.494 1.19,4.439 0.99,4.326 0.79,4.215 0.624,4.068 0.492,3.889 0.36,3.709 0.26,3.498 0.192,3.259 0.124,3.018 0.072,2.773 0.036,2.521 0,2.268 -0.02,2.017 -0.024,1.765 -0.028,1.513 -0.03,1.283 -0.03,1.074 -0.03,0.755 -0.02,0.397 0,0 m -1.086,2.035 c 0.016,0.336 0.056,0.664 0.12,0.983 0.064,0.32 0.156,0.625 0.276,0.913 0.12,0.288 0.284,0.54 0.492,0.756 C 0.01,4.902 0.272,5.074 0.588,5.203 0.904,5.33 1.282,5.395 1.722,5.395 2.162,5.395 2.54,5.33 2.856,5.203 3.172,5.074 3.434,4.902 3.642,4.687 3.85,4.471 4.014,4.219 4.134,3.931 4.254,3.643 4.346,3.338 4.41,3.018 4.474,2.699 4.514,2.371 4.53,2.035 4.546,1.699 4.554,1.375 4.554,1.062 4.554,0.75 4.546,0.427 4.53,0.091 4.514,-0.245 4.474,-0.573 4.41,-0.893 4.346,-1.213 4.254,-1.516 4.134,-1.799 4.014,-2.084 3.85,-2.334 3.642,-2.549 3.434,-2.766 3.174,-2.936 2.862,-3.059 2.55,-3.184 2.17,-3.245 1.722,-3.245 c -0.44,0 -0.818,0.061 -1.134,0.186 -0.316,0.123 -0.578,0.293 -0.786,0.51 -0.208,0.215 -0.372,0.465 -0.492,0.75 -0.12,0.283 -0.212,0.586 -0.276,0.906 -0.064,0.32 -0.104,0.648 -0.12,0.984 -0.016,0.336 -0.024,0.659 -0.024,0.971 0,0.313 0.008,0.637 0.024,0.973"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path126" /></g><g
id="g128"
transform="translate(176.3315,329.6836)"><path
d="m 0,0 c -0.076,0.275 -0.192,0.521 -0.348,0.738 -0.156,0.216 -0.356,0.388 -0.6,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.876,-0.204 -0.24,-0.137 -0.436,-0.314 -0.588,-0.534 -0.152,-0.22 -0.262,-0.47 -0.33,-0.75 -0.069,-0.28 -0.102,-0.563 -0.102,-0.853 0,-0.303 0.036,-0.597 0.108,-0.88 0.071,-0.286 0.186,-0.536 0.342,-0.75 0.156,-0.217 0.357,-0.391 0.606,-0.523 0.248,-0.132 0.548,-0.198 0.9,-0.198 0.351,0 0.646,0.068 0.882,0.204 0.236,0.136 0.425,0.315 0.57,0.54 0.144,0.224 0.248,0.481 0.312,0.768 0.063,0.289 0.096,0.584 0.096,0.888 C 0.114,-0.559 0.076,-0.275 0,0 M -3.666,2.202 V 1.361 h 0.024 c 0.168,0.345 0.431,0.595 0.792,0.75 0.36,0.157 0.756,0.235 1.188,0.235 0.48,0 0.898,-0.088 1.254,-0.264 C -0.052,1.906 0.244,1.668 0.48,1.368 0.716,1.068 0.893,0.722 1.014,0.33 1.134,-0.062 1.194,-0.479 1.194,-0.918 1.194,-1.357 1.136,-1.773 1.02,-2.166 0.904,-2.559 0.727,-2.9 0.492,-3.191 0.256,-3.484 -0.04,-3.714 -0.396,-3.882 -0.752,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.152,0 -0.323,0.017 -0.51,0.048 -0.188,0.032 -0.375,0.084 -0.558,0.156 -0.184,0.073 -0.358,0.17 -0.522,0.294 -0.164,0.124 -0.302,0.279 -0.414,0.462 h -0.024 v -3.191 h -1.02 v 8.567 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path130" /></g><g
id="g132"
transform="translate(178.2329,331.8857)"><path
d="M 0,0 H 1.308 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.856 2.4,-3.348 H 4.524 L 2.796,-3.636 1.068,-6.204 H -0.168 L 2.16,-2.94 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path134" /></g><g
id="g136"
transform="translate(335.6333,348.6504)"><path
d="M 0,0 V -7.607 H 4.536 V -8.568 H -1.14 l 0,8.568 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path138" /></g><g
id="g140"
transform="translate(344.3334,343.0761)"><path
d="m 0,0 c -0.209,-0.044 -0.426,-0.08 -0.654,-0.107 -0.229,-0.029 -0.459,-0.061 -0.691,-0.096 -0.231,-0.037 -0.44,-0.095 -0.624,-0.174 -0.183,-0.08 -0.334,-0.195 -0.449,-0.343 -0.117,-0.147 -0.174,-0.35 -0.174,-0.606 0,-0.168 0.034,-0.31 0.102,-0.426 0.067,-0.115 0.156,-0.209 0.264,-0.281 0.107,-0.072 0.236,-0.125 0.384,-0.156 0.148,-0.033 0.297,-0.049 0.45,-0.049 0.335,0 0.624,0.047 0.864,0.138 0.239,0.092 0.435,0.208 0.588,0.348 0.151,0.141 0.264,0.293 0.336,0.457 0.071,0.163 0.108,0.317 0.108,0.461 V 0.211 C 0.375,0.114 0.207,0.045 0,0 m 1.428,-3.125 c -0.264,0 -0.475,0.073 -0.631,0.221 -0.155,0.148 -0.233,0.39 -0.233,0.726 -0.281,-0.336 -0.607,-0.578 -0.978,-0.726 -0.373,-0.148 -0.774,-0.221 -1.207,-0.221 -0.279,0 -0.543,0.029 -0.791,0.09 -0.248,0.059 -0.467,0.16 -0.654,0.299 -0.188,0.14 -0.336,0.32 -0.444,0.541 -0.109,0.219 -0.162,0.486 -0.162,0.798 0,0.351 0.06,0.639 0.18,0.864 0.119,0.223 0.277,0.405 0.474,0.545 0.196,0.14 0.419,0.246 0.671,0.318 0.252,0.072 0.511,0.133 0.775,0.18 0.279,0.056 0.546,0.098 0.798,0.127 0.252,0.027 0.473,0.067 0.666,0.119 0.192,0.053 0.343,0.129 0.456,0.228 0.111,0.1 0.168,0.246 0.168,0.438 0,0.224 -0.042,0.404 -0.126,0.541 C 0.306,2.098 0.197,2.202 0.066,2.274 -0.066,2.346 -0.215,2.395 -0.379,2.418 -0.543,2.442 -0.705,2.455 -0.864,2.455 -1.297,2.455 -1.656,2.372 -1.944,2.209 -2.232,2.045 -2.389,1.734 -2.412,1.278 h -1.021 c 0.017,0.384 0.097,0.708 0.241,0.972 0.143,0.264 0.336,0.479 0.575,0.643 0.24,0.164 0.517,0.281 0.828,0.353 0.313,0.072 0.641,0.108 0.984,0.108 0.281,0 0.559,-0.02 0.834,-0.059 C 0.306,3.254 0.556,3.172 0.779,3.049 1.004,2.924 1.184,2.75 1.319,2.526 1.455,2.303 1.524,2.01 1.524,1.65 v -3.191 c 0,-0.24 0.013,-0.416 0.042,-0.529 0.028,-0.112 0.122,-0.168 0.282,-0.168 0.088,0 0.191,0.02 0.312,0.06 V -2.97 C 1.983,-3.074 1.74,-3.125 1.428,-3.125"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path142" /></g><g
id="g144"
transform="translate(348.3647,346.2871)"><path
d="m 0,0 v -1.309 h 0.023 c 0.249,0.504 0.553,0.876 0.913,1.117 0.36,0.239 0.816,0.351 1.369,0.335 v -1.08 C 1.897,-0.937 1.549,-0.992 1.26,-1.105 0.973,-1.217 0.74,-1.381 0.565,-1.597 0.389,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.691 0.061,-3.045 0.061,-3.445 v -2.76 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path146" /></g><g
id="g148"
transform="translate(354.4545,341.1211)"><path
d="M 0,0 C 0.236,0.139 0.426,0.323 0.57,0.551 0.715,0.779 0.82,1.037 0.889,1.325 0.956,1.613 0.99,1.901 0.99,2.189 0.99,2.461 0.959,2.729 0.895,2.994 0.83,3.258 0.729,3.496 0.588,3.707 0.448,3.92 0.266,4.09 0.043,4.217 -0.182,4.346 -0.453,4.41 -0.773,4.41 -1.102,4.41 -1.382,4.348 -1.613,4.224 -1.846,4.1 -2.035,3.934 -2.184,3.725 -2.332,3.518 -2.439,3.277 -2.508,3.006 -2.576,2.733 -2.609,2.449 -2.609,2.153 c 0,-0.28 0.027,-0.559 0.084,-0.84 0.055,-0.28 0.152,-0.534 0.287,-0.762 0.136,-0.228 0.316,-0.412 0.541,-0.551 0.223,-0.141 0.504,-0.211 0.84,-0.211 0.336,0 0.621,0.07 0.857,0.211 M 1.303,-2.791 C 0.838,-3.295 0.11,-3.547 -0.881,-3.547 c -0.289,0 -0.582,0.032 -0.883,0.096 -0.299,0.064 -0.572,0.168 -0.816,0.312 -0.244,0.145 -0.445,0.332 -0.606,0.565 -0.16,0.232 -0.248,0.515 -0.263,0.851 h 1.019 c 0.008,-0.183 0.067,-0.34 0.174,-0.467 0.109,-0.128 0.24,-0.232 0.397,-0.312 0.156,-0.08 0.326,-0.139 0.509,-0.175 0.184,-0.036 0.36,-0.053 0.528,-0.053 0.337,0 0.621,0.058 0.852,0.173 0.232,0.117 0.425,0.276 0.576,0.481 0.152,0.203 0.262,0.449 0.331,0.738 0.067,0.287 0.102,0.604 0.102,0.947 V 0.018 H 1.015 C 0.838,-0.367 0.572,-0.648 0.217,-0.828 -0.14,-1.009 -0.518,-1.099 -0.918,-1.099 c -0.464,0 -0.867,0.084 -1.211,0.252 -0.345,0.168 -0.633,0.394 -0.865,0.679 -0.231,0.283 -0.406,0.615 -0.522,0.996 -0.116,0.379 -0.173,0.781 -0.173,1.205 0,0.368 0.047,0.746 0.144,1.135 0.096,0.387 0.256,0.739 0.48,1.056 0.223,0.315 0.52,0.575 0.887,0.78 0.368,0.203 0.821,0.306 1.356,0.306 0.392,0 0.752,-0.087 1.08,-0.259 0.328,-0.172 0.584,-0.43 0.768,-0.774 h 0.013 v 0.889 h 0.959 v -5.677 c 0,-1.015 -0.232,-1.776 -0.695,-2.28"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path150" /></g><g
id="g152"
transform="translate(362.1342,344.4629)"><path
d="M 0,0 C -0.092,0.216 -0.215,0.402 -0.371,0.558 -0.527,0.714 -0.712,0.838 -0.924,0.93 -1.136,1.021 -1.369,1.068 -1.625,1.068 -1.89,1.068 -2.128,1.021 -2.34,0.93 -2.552,0.838 -2.734,0.711 -2.886,0.552 -3.037,0.392 -3.158,0.205 -3.246,-0.006 -3.334,-0.219 -3.386,-0.444 -3.401,-0.685 H 0.162 C 0.147,-0.444 0.092,-0.217 0,0 m 0.246,-3.984 c -0.464,-0.352 -1.048,-0.528 -1.752,-0.528 -0.496,0 -0.926,0.08 -1.289,0.24 -0.365,0.16 -0.671,0.383 -0.918,0.671 -0.248,0.288 -0.434,0.632 -0.558,1.033 -0.125,0.4 -0.195,0.836 -0.21,1.308 0,0.471 0.071,0.904 0.215,1.295 0.145,0.393 0.346,0.733 0.606,1.021 0.26,0.288 0.568,0.511 0.925,0.672 0.355,0.16 0.745,0.24 1.17,0.24 0.551,0 1.009,-0.114 1.374,-0.343 C 0.172,1.397 0.465,1.107 0.685,0.756 0.904,0.403 1.057,0.02 1.141,-0.396 1.225,-0.812 1.258,-1.209 1.242,-1.584 h -4.643 c -0.009,-0.272 0.024,-0.53 0.095,-0.774 0.073,-0.245 0.189,-0.46 0.349,-0.648 0.159,-0.188 0.363,-0.338 0.611,-0.451 0.248,-0.111 0.54,-0.168 0.876,-0.168 0.433,0 0.786,0.1 1.062,0.301 0.277,0.199 0.459,0.504 0.547,0.912 H 1.147 C 1.01,-3.108 0.711,-3.633 0.246,-3.984"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path154" /></g><g
id="g156"
transform="translate(365.3569,346.2871)"><path
d="m 0,0 v -1.309 h 0.023 c 0.248,0.504 0.553,0.876 0.912,1.117 0.36,0.239 0.817,0.351 1.369,0.335 v -1.08 C 1.895,-0.937 1.548,-0.992 1.26,-1.105 0.972,-1.217 0.739,-1.381 0.563,-1.597 0.388,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.691 0.06,-3.045 0.06,-3.445 v -2.76 H -0.961 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path158" /></g><g
id="g160"
transform="translate(318.2573,330.9863)"><path
d="m 0,0 v 0.9 h 1.044 v 0.924 c 0,0.504 0.145,0.887 0.438,1.147 C 1.773,3.23 2.199,3.36 2.76,3.36 2.855,3.36 2.966,3.352 3.09,3.336 3.214,3.32 3.324,3.297 3.42,3.264 V 2.377 C 3.332,2.408 3.236,2.43 3.132,2.442 3.027,2.454 2.932,2.461 2.844,2.461 2.596,2.461 2.404,2.412 2.268,2.316 2.132,2.221 2.064,2.036 2.064,1.764 V 0.9 h 1.2 V 0 h -1.2 V -5.304 H 1.044 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path162" /></g><g
id="g164"
transform="translate(323.3276,327.7773)"><path
d="m 0,0 c 0.1,-0.293 0.237,-0.537 0.414,-0.732 0.176,-0.197 0.381,-0.346 0.617,-0.451 0.237,-0.104 0.487,-0.156 0.75,-0.156 0.264,0 0.514,0.052 0.75,0.156 0.237,0.105 0.442,0.254 0.618,0.451 0.176,0.195 0.314,0.439 0.415,0.732 0.1,0.291 0.149,0.625 0.149,1.002 0,0.375 -0.049,0.709 -0.149,1.002 C 3.463,2.295 3.325,2.541 3.149,2.741 2.973,2.941 2.768,3.094 2.531,3.197 2.295,3.301 2.045,3.353 1.781,3.353 1.518,3.353 1.268,3.301 1.031,3.197 0.795,3.094 0.59,2.941 0.414,2.741 0.237,2.541 0.1,2.295 0,2.004 -0.101,1.711 -0.15,1.377 -0.15,1.002 -0.15,0.625 -0.101,0.291 0,0 m -1.039,2.279 c 0.129,0.397 0.32,0.741 0.576,1.032 0.256,0.292 0.572,0.523 0.948,0.691 0.376,0.168 0.808,0.252 1.296,0.252 0.496,0 0.93,-0.084 1.303,-0.252 C 3.455,3.834 3.77,3.603 4.025,3.311 4.281,3.02 4.473,2.676 4.602,2.279 4.73,1.883 4.793,1.457 4.793,1.002 4.793,0.545 4.73,0.121 4.602,-0.271 4.473,-0.662 4.281,-1.005 4.025,-1.297 3.77,-1.589 3.455,-1.816 3.084,-1.98 2.711,-2.145 2.277,-2.227 1.781,-2.227 c -0.488,0 -0.92,0.082 -1.296,0.247 -0.376,0.164 -0.692,0.391 -0.948,0.683 -0.256,0.292 -0.447,0.635 -0.576,1.026 -0.127,0.392 -0.191,0.816 -0.191,1.273 0,0.455 0.064,0.881 0.191,1.277"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path166" /></g><g
id="g168"
transform="translate(330.2456,331.8867)"><path
d="m 0,0 v -1.309 h 0.023 c 0.248,0.504 0.553,0.877 0.913,1.118 0.359,0.239 0.816,0.351 1.368,0.336 V -0.936 C 1.896,-0.936 1.548,-0.992 1.26,-1.103 0.972,-1.217 0.739,-1.38 0.563,-1.596 0.388,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.689 0.06,-3.044 0.06,-3.444 v -2.76 H -0.961 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path170" /></g><g
id="g172"
transform="translate(339.1362,325.6826)"><path
d="m 0,0 v 6.097 h -2.207 v 0.815 c 0.287,0 0.567,0.023 0.84,0.066 0.271,0.044 0.517,0.127 0.738,0.246 0.219,0.121 0.405,0.284 0.558,0.492 C 0.08,7.924 0.185,8.189 0.24,8.508 H 1.02 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path174" /></g><g
id="g176"
transform="translate(343.2172,332.3789)"><path
d="M 0,0 C 0.112,0.367 0.286,0.685 0.522,0.953 0.758,1.222 1.052,1.432 1.403,1.584 1.756,1.735 2.155,1.811 2.604,1.811 2.972,1.811 3.317,1.758 3.642,1.65 3.966,1.541 4.248,1.386 4.487,1.182 4.728,0.978 4.918,0.724 5.058,0.42 5.198,0.115 5.269,-0.236 5.269,-0.637 5.269,-1.012 5.21,-1.344 5.094,-1.633 4.978,-1.92 4.823,-2.178 4.632,-2.406 4.44,-2.635 4.22,-2.84 3.972,-3.024 3.724,-3.209 3.468,-3.385 3.204,-3.553 2.94,-3.713 2.676,-3.87 2.411,-4.026 2.147,-4.182 1.905,-4.349 1.687,-4.524 1.466,-4.7 1.278,-4.891 1.122,-5.094 0.966,-5.299 0.864,-5.532 0.815,-5.797 h 4.37 v -0.899 h -5.557 c 0.04,0.504 0.13,0.934 0.269,1.29 0.141,0.355 0.319,0.666 0.535,0.929 0.215,0.264 0.46,0.497 0.732,0.697 0.272,0.2 0.556,0.387 0.852,0.563 0.36,0.225 0.676,0.431 0.948,0.619 0.271,0.188 0.498,0.377 0.678,0.57 0.179,0.192 0.316,0.399 0.408,0.624 0.092,0.224 0.139,0.484 0.139,0.779 0,0.232 -0.045,0.443 -0.133,0.631 C 3.968,0.193 3.85,0.355 3.702,0.492 3.554,0.627 3.38,0.732 3.18,0.804 2.979,0.875 2.768,0.912 2.544,0.912 2.247,0.912 1.993,0.85 1.782,0.726 1.569,0.602 1.396,0.439 1.26,0.24 1.124,0.039 1.026,-0.186 0.966,-0.439 0.905,-0.691 0.88,-0.944 0.888,-1.2 h -1.02 C -0.156,-0.768 -0.112,-0.368 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path178" /></g><g
id="g180"
transform="translate(350.8432,328.7968)"><path
d="m 0,0 c 0.02,-0.396 0.084,-0.768 0.191,-1.116 0.109,-0.349 0.283,-0.642 0.523,-0.882 0.239,-0.24 0.575,-0.36 1.008,-0.36 0.432,0 0.768,0.12 1.008,0.36 0.24,0.24 0.414,0.533 0.522,0.882 0.107,0.348 0.172,0.72 0.191,1.116 0.02,0.396 0.031,0.754 0.031,1.074 0,0.207 -0.002,0.438 -0.006,0.69 C 3.463,2.016 3.443,2.268 3.408,2.52 3.371,2.771 3.32,3.018 3.252,3.258 3.184,3.498 3.084,3.707 2.951,3.888 2.82,4.068 2.654,4.213 2.453,4.326 2.254,4.437 2.01,4.494 1.722,4.494 1.434,4.494 1.189,4.437 0.99,4.326 0.789,4.213 0.623,4.068 0.492,3.888 0.359,3.707 0.26,3.498 0.191,3.258 0.123,3.018 0.072,2.771 0.035,2.52 0,2.268 -0.021,2.016 -0.024,1.764 -0.028,1.512 -0.03,1.281 -0.03,1.074 -0.03,0.754 -0.021,0.396 0,0 m -1.086,2.033 c 0.016,0.336 0.056,0.664 0.119,0.985 0.065,0.32 0.156,0.624 0.277,0.912 0.12,0.288 0.284,0.54 0.492,0.756 C 0.01,4.902 0.271,5.074 0.588,5.201 0.904,5.33 1.281,5.394 1.722,5.394 2.162,5.394 2.539,5.33 2.855,5.201 3.172,5.074 3.434,4.902 3.642,4.686 3.85,4.47 4.014,4.218 4.134,3.93 4.254,3.642 4.346,3.338 4.41,3.018 4.474,2.697 4.514,2.369 4.529,2.033 4.546,1.697 4.554,1.373 4.554,1.062 4.554,0.75 4.546,0.426 4.529,0.09 4.514,-0.246 4.474,-0.574 4.41,-0.895 4.346,-1.215 4.254,-1.517 4.134,-1.801 4.014,-2.084 3.85,-2.334 3.642,-2.551 3.434,-2.766 3.174,-2.937 2.861,-3.061 2.55,-3.184 2.17,-3.246 1.722,-3.246 c -0.441,0 -0.818,0.062 -1.134,0.185 -0.317,0.124 -0.578,0.295 -0.786,0.51 -0.208,0.217 -0.372,0.467 -0.492,0.75 -0.121,0.284 -0.212,0.586 -0.277,0.906 -0.063,0.321 -0.103,0.649 -0.119,0.985 -0.017,0.336 -0.024,0.66 -0.024,0.972 0,0.311 0.007,0.635 0.024,0.971"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path182" /></g><g
id="g184"
transform="translate(361.3911,329.6845)"><path
d="m 0,0 c -0.076,0.276 -0.192,0.522 -0.349,0.738 -0.156,0.216 -0.355,0.388 -0.599,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.877,-0.204 -0.24,-0.136 -0.435,-0.313 -0.588,-0.534 -0.152,-0.221 -0.261,-0.471 -0.33,-0.75 -0.068,-0.28 -0.101,-0.564 -0.101,-0.852 0,-0.304 0.036,-0.598 0.107,-0.882 0.073,-0.284 0.187,-0.534 0.342,-0.75 0.156,-0.216 0.358,-0.39 0.607,-0.522 0.248,-0.133 0.547,-0.198 0.9,-0.198 0.351,0 0.645,0.067 0.882,0.204 0.236,0.136 0.425,0.317 0.57,0.54 0.144,0.224 0.248,0.48 0.312,0.769 0.063,0.287 0.096,0.584 0.096,0.886 C 0.114,-0.558 0.075,-0.276 0,0 m -3.666,2.202 v -0.84 h 0.024 c 0.168,0.344 0.432,0.594 0.791,0.75 0.361,0.157 0.756,0.235 1.189,0.235 0.479,0 0.897,-0.089 1.254,-0.265 C -0.052,1.905 0.243,1.668 0.479,1.368 0.716,1.067 0.893,0.722 1.014,0.33 c 0.12,-0.392 0.18,-0.808 0.18,-1.248 0,-0.44 -0.058,-0.856 -0.174,-1.248 C 0.903,-2.558 0.728,-2.899 0.491,-3.192 0.256,-3.483 -0.04,-3.714 -0.396,-3.882 -0.753,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.152,0 -0.322,0.016 -0.51,0.048 -0.189,0.032 -0.374,0.084 -0.558,0.155 -0.184,0.073 -0.358,0.17 -0.522,0.295 -0.164,0.123 -0.302,0.278 -0.414,0.462 h -0.024 v -3.192 h -1.021 v 8.568 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path186" /></g><g
id="g188"
transform="translate(363.2924,331.8867)"><path
d="M 0,0 H 1.309 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.855 2.4,-3.349 H 4.523 L 2.796,-3.637 1.068,-6.204 h -1.236 l 2.328,3.265 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path190" /></g><g
id="g192"
transform="translate(379.1928,329.1269)"><path
d="m 0,0 v -0.816 h -2.616 v -2.628 h -0.816 v 2.628 H -6.048 V 0 h 2.616 v 2.627 h 0.816 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path194" /></g><g
id="g196"
transform="translate(152.6083,168.5454)"><path
d="m 0,0 c -8.995,0 -16.288,-7.293 -16.288,-16.29 0,-7.197 4.667,-13.302 11.14,-15.457 0.815,-0.149 1.112,0.354 1.112,0.786 0,0.386 -0.014,1.411 -0.022,2.77 -4.531,-0.984 -5.487,2.184 -5.487,2.184 -0.741,1.882 -1.809,2.383 -1.809,2.383 -1.479,1.01 0.112,0.99 0.112,0.99 1.635,-0.115 2.495,-1.679 2.495,-1.679 1.453,-2.489 3.813,-1.77 4.741,-1.353 0.148,1.052 0.568,1.77 1.034,2.177 -3.617,0.411 -7.42,1.809 -7.42,8.051 0,1.778 0.635,3.232 1.677,4.371 -0.168,0.412 -0.727,2.068 0.159,4.311 0,0 1.368,0.438 4.48,-1.67 1.299,0.362 2.693,0.542 4.078,0.548 1.383,-0.006 2.777,-0.186 4.078,-0.548 3.11,2.108 4.475,1.67 4.475,1.67 0.889,-2.243 0.33,-3.899 0.162,-4.311 1.044,-1.139 1.675,-2.593 1.675,-4.371 0,-6.258 -3.809,-7.635 -7.438,-8.038 0.585,-0.503 1.106,-1.497 1.106,-3.017 0,-2.177 -0.02,-3.934 -0.02,-4.468 0,-0.436 0.293,-0.943 1.12,-0.784 6.468,2.159 11.131,8.26 11.131,15.455 C 16.291,-7.293 8.997,0 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path198" /></g><g
id="g200"
transform="translate(350.6088,217.5547)"><path
d="m 0,0 c -33.347,0 -60.388,-27.035 -60.388,-60.388 0,-26.68 17.303,-49.316 41.297,-57.301 3.018,-0.559 4.126,1.31 4.126,2.905 0,1.439 -0.056,6.197 -0.082,11.243 -16.8,-3.653 -20.345,7.125 -20.345,7.125 -2.747,6.979 -6.705,8.836 -6.705,8.836 -5.479,3.748 0.413,3.671 0.413,3.671 6.064,-0.426 9.257,-6.224 9.257,-6.224 5.386,-9.231 14.127,-6.562 17.573,-5.019 0.543,3.902 2.107,6.567 3.834,8.075 -13.413,1.526 -27.513,6.705 -27.513,29.844 0,6.592 2.359,11.979 6.222,16.208 -0.627,1.522 -2.694,7.664 0.586,15.982 0,0 5.071,1.622 16.61,-6.191 4.817,1.338 9.983,2.009 15.115,2.033 5.132,-0.024 10.302,-0.695 15.128,-2.033 11.526,7.813 16.59,6.191 16.59,6.191 3.287,-8.318 1.22,-14.46 0.593,-15.982 3.872,-4.229 6.214,-9.616 6.214,-16.208 0,-23.195 -14.127,-28.301 -27.574,-29.796 2.166,-1.874 4.096,-5.549 4.096,-11.183 0,-8.08 -0.069,-14.583 -0.069,-16.572 0,-1.608 1.086,-3.491 4.147,-2.898 23.982,7.994 41.263,30.622 41.263,57.294 C 60.388,-27.035 33.351,0 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path202" /></g><g
id="g204"
transform="translate(313.0932,130.8515)"><path
d="m 0,0 c -0.133,-0.301 -0.605,-0.391 -1.035,-0.184 -0.439,0.197 -0.684,0.606 -0.542,0.907 0.13,0.308 0.602,0.394 1.04,0.188 C -0.099,0.714 0.151,0.301 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path206" /></g><g
id="g208"
transform="translate(315.5395,128.123)"><path
d="M 0,0 C -0.288,-0.267 -0.852,-0.143 -1.233,0.279 -1.629,0.7 -1.702,1.264 -1.41,1.534 -1.113,1.801 -0.567,1.676 -0.172,1.255 0.224,0.829 0.301,0.27 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path210" /></g><g
id="g212"
transform="translate(317.9204,124.6455)"><path
d="M 0,0 C -0.37,-0.258 -0.976,-0.017 -1.35,0.52 -1.72,1.058 -1.72,1.702 -1.341,1.96 -0.967,2.218 -0.37,1.985 0.009,1.453 0.378,0.907 0.378,0.263 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path214" /></g><g
id="g216"
transform="translate(321.1821,121.2851)"><path
d="M 0,0 C -0.331,-0.365 -1.036,-0.267 -1.552,0.231 -2.08,0.718 -2.227,1.409 -1.896,1.774 -1.56,2.14 -0.851,2.037 -0.331,1.543 0.193,1.057 0.352,0.361 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path218" /></g><g
id="g220"
transform="translate(325.6821,119.334)"><path
d="m 0,0 c -0.147,-0.473 -0.825,-0.687 -1.509,-0.486 -0.683,0.207 -1.13,0.76 -0.992,1.238 0.142,0.477 0.824,0.7 1.513,0.485 C -0.306,1.031 0.142,0.481 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path222" /></g><g
id="g224"
transform="translate(330.6245,118.9726)"><path
d="m 0,0 c 0.017,-0.498 -0.563,-0.911 -1.281,-0.92 -0.722,-0.017 -1.307,0.387 -1.315,0.877 0,0.503 0.568,0.911 1.289,0.924 C -0.589,0.895 0,0.494 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path226" /></g><g
id="g228"
transform="translate(335.2231,119.7549)"><path
d="m 0,0 c 0.086,-0.485 -0.413,-0.984 -1.126,-1.117 -0.701,-0.129 -1.35,0.172 -1.439,0.653 -0.087,0.498 0.42,0.997 1.121,1.126 C -0.73,0.786 -0.091,0.494 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path230" /></g><g
id="g232"
transform="translate(224.8979,223.4882)"><path
d="M 0,0 V -0.5"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path234" /></g><g
id="g236"
transform="translate(224.8979,220.9882)"><path
d="M 0,0 V -133.993"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1"
id="path238" /></g><g
id="g240"
transform="translate(224.8979,85.9951)"><path
d="M 0,0 V -0.5"
style="fill:none;stroke:#3a7fc3;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path242" /></g><g
id="g244"
transform="translate(133.2758,71.4795)"><path
d="m 0,0 c -0.38,0.276 -0.866,0.414 -1.458,0.414 -0.24,0 -0.476,-0.024 -0.708,-0.071 -0.232,-0.049 -0.438,-0.129 -0.618,-0.241 -0.18,-0.113 -0.324,-0.262 -0.432,-0.451 -0.108,-0.187 -0.162,-0.422 -0.162,-0.701 0,-0.264 0.078,-0.478 0.234,-0.642 0.156,-0.165 0.364,-0.298 0.624,-0.402 0.26,-0.104 0.554,-0.19 0.882,-0.259 0.328,-0.067 0.662,-0.141 1.002,-0.22 0.34,-0.08 0.674,-0.175 1.002,-0.284 C 0.694,-2.964 0.988,-3.11 1.248,-3.294 1.508,-3.478 1.716,-3.71 1.872,-3.989 2.028,-4.271 2.106,-4.622 2.106,-5.046 2.106,-5.502 2.004,-5.892 1.8,-6.216 1.596,-6.54 1.334,-6.804 1.014,-7.008 0.694,-7.212 0.336,-7.36 -0.06,-7.452 -0.456,-7.544 -0.85,-7.59 -1.242,-7.59 c -0.48,0 -0.934,0.06 -1.362,0.18 -0.428,0.12 -0.804,0.302 -1.128,0.546 -0.324,0.244 -0.58,0.556 -0.768,0.936 -0.188,0.38 -0.282,0.829 -0.282,1.35 h 1.08 c 0,-0.361 0.07,-0.67 0.21,-0.93 0.14,-0.261 0.324,-0.474 0.552,-0.642 0.228,-0.167 0.494,-0.292 0.798,-0.373 0.304,-0.08 0.616,-0.119 0.936,-0.119 0.256,0 0.514,0.024 0.774,0.073 0.26,0.046 0.494,0.128 0.702,0.246 0.208,0.115 0.376,0.273 0.504,0.472 0.128,0.201 0.192,0.457 0.192,0.769 0,0.296 -0.078,0.536 -0.234,0.72 -0.156,0.183 -0.364,0.334 -0.624,0.45 -0.26,0.116 -0.554,0.21 -0.882,0.282 -0.328,0.072 -0.662,0.147 -1.002,0.223 -0.34,0.075 -0.674,0.163 -1.002,0.263 -0.328,0.1 -0.622,0.232 -0.882,0.396 -0.26,0.164 -0.468,0.376 -0.624,0.636 -0.156,0.259 -0.234,0.586 -0.234,0.978 0,0.432 0.088,0.806 0.264,1.122 0.176,0.316 0.41,0.575 0.702,0.78 0.292,0.204 0.624,0.356 0.996,0.456 0.372,0.1 0.754,0.15 1.146,0.15 0.44,0 0.848,-0.053 1.224,-0.156 C 0.19,1.114 0.52,0.95 0.804,0.725 1.088,0.502 1.312,0.22 1.476,-0.12 1.64,-0.46 1.73,-0.866 1.746,-1.338 H 0.666 C 0.602,-0.722 0.38,-0.276 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path246" /></g><g
id="g248"
transform="translate(137.5537,70.2851)"><path
d="m 0,0 v -0.912 h 0.024 c 0.464,0.705 1.132,1.057 2.004,1.057 0.384,0 0.732,-0.081 1.044,-0.241 0.312,-0.16 0.532,-0.431 0.66,-0.816 0.208,0.336 0.482,0.596 0.822,0.78 0.34,0.185 0.714,0.277 1.122,0.277 0.312,0 0.594,-0.035 0.846,-0.102 0.252,-0.068 0.468,-0.175 0.648,-0.318 0.18,-0.145 0.32,-0.33 0.42,-0.559 0.1,-0.228 0.15,-0.502 0.15,-0.822 V -6.203 H 6.72 v 4.067 c 0,0.193 -0.016,0.372 -0.048,0.54 -0.032,0.168 -0.092,0.315 -0.18,0.438 -0.088,0.125 -0.21,0.222 -0.366,0.295 -0.156,0.072 -0.358,0.107 -0.606,0.107 -0.504,0 -0.9,-0.143 -1.188,-0.431 C 4.044,-1.476 3.9,-1.859 3.9,-2.34 V -6.203 H 2.88 v 4.067 c 0,0.2 -0.018,0.384 -0.054,0.552 -0.036,0.168 -0.098,0.314 -0.186,0.438 -0.088,0.125 -0.206,0.22 -0.354,0.289 -0.148,0.068 -0.338,0.101 -0.57,0.101 -0.296,0 -0.55,-0.059 -0.762,-0.18 C 0.742,-1.056 0.57,-1.199 0.438,-1.367 0.306,-1.535 0.21,-1.709 0.15,-1.89 0.09,-2.07 0.06,-2.22 0.06,-2.34 V -6.203 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path250" /></g><g
id="g252"
transform="translate(150.1655,67.0761)"><path
d="m 0,0 c -0.208,-0.045 -0.426,-0.08 -0.654,-0.108 -0.228,-0.029 -0.458,-0.06 -0.69,-0.097 -0.232,-0.035 -0.44,-0.094 -0.624,-0.174 -0.184,-0.08 -0.334,-0.193 -0.45,-0.342 -0.116,-0.148 -0.174,-0.349 -0.174,-0.605 0,-0.168 0.034,-0.311 0.102,-0.426 0.068,-0.117 0.156,-0.211 0.264,-0.283 0.108,-0.071 0.236,-0.123 0.384,-0.155 0.148,-0.033 0.298,-0.048 0.45,-0.048 0.336,0 0.624,0.045 0.864,0.137 0.24,0.092 0.436,0.208 0.588,0.349 0.152,0.139 0.264,0.291 0.336,0.455 0.072,0.164 0.108,0.318 0.108,0.463 V 0.209 C 0.376,0.113 0.208,0.043 0,0 m 1.428,-3.127 c -0.264,0 -0.474,0.074 -0.63,0.223 -0.156,0.147 -0.234,0.389 -0.234,0.725 -0.28,-0.336 -0.606,-0.578 -0.978,-0.725 -0.372,-0.149 -0.774,-0.223 -1.206,-0.223 -0.28,0 -0.544,0.03 -0.792,0.09 -0.248,0.06 -0.466,0.16 -0.654,0.301 -0.188,0.139 -0.336,0.319 -0.444,0.539 -0.108,0.22 -0.162,0.486 -0.162,0.799 0,0.351 0.06,0.639 0.18,0.863 0.12,0.224 0.278,0.406 0.474,0.547 0.196,0.139 0.42,0.246 0.672,0.318 0.252,0.071 0.51,0.131 0.774,0.18 0.28,0.055 0.546,0.097 0.798,0.125 0.252,0.028 0.474,0.068 0.666,0.121 0.192,0.051 0.344,0.127 0.456,0.227 0.112,0.101 0.168,0.246 0.168,0.439 0,0.223 -0.042,0.403 -0.126,0.539 -0.084,0.137 -0.192,0.24 -0.324,0.312 -0.132,0.073 -0.28,0.121 -0.444,0.145 -0.164,0.023 -0.326,0.035 -0.486,0.035 -0.432,0 -0.792,-0.082 -1.08,-0.246 -0.288,-0.164 -0.444,-0.474 -0.468,-0.93 h -1.02 c 0.016,0.384 0.096,0.708 0.24,0.973 0.144,0.264 0.336,0.478 0.576,0.642 0.24,0.163 0.516,0.282 0.828,0.354 0.312,0.071 0.64,0.108 0.984,0.108 0.28,0 0.558,-0.02 0.834,-0.061 C 0.306,3.254 0.556,3.172 0.78,3.047 1.004,2.924 1.184,2.749 1.32,2.525 1.456,2.301 1.524,2.01 1.524,1.649 v -3.192 c 0,-0.24 0.014,-0.416 0.042,-0.527 0.028,-0.113 0.122,-0.168 0.282,-0.168 0.088,0 0.192,0.019 0.312,0.059 V -2.971 C 1.984,-3.074 1.74,-3.127 1.428,-3.127"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path254" /></g><path
d="m 154.354,64.082 h -1.02 v 8.567 h 1.02 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path256" /><path
d="m 157.017,64.082 h -1.02 v 8.567 h 1.02 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path258" /><g
id="g260"
transform="translate(101.854,54.9863)"><path
d="m 0,0 v 0.899 h 1.044 v 0.924 c 0,0.504 0.146,0.886 0.438,1.146 0.292,0.26 0.718,0.39 1.278,0.39 0.096,0 0.206,-0.007 0.33,-0.023 C 3.214,3.319 3.324,3.295 3.42,3.264 V 2.375 C 3.332,2.407 3.236,2.43 3.132,2.441 3.028,2.453 2.932,2.459 2.844,2.459 2.596,2.459 2.404,2.411 2.268,2.315 2.132,2.219 2.064,2.035 2.064,1.764 V 0.899 h 1.2 V 0 h -1.2 V -5.305 H 1.044 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path262" /></g><g
id="g264"
transform="translate(106.9238,51.7754)"><path
d="m 0,0 c 0.1,-0.292 0.238,-0.535 0.414,-0.732 0.176,-0.196 0.382,-0.346 0.618,-0.45 0.236,-0.103 0.486,-0.156 0.75,-0.156 0.264,0 0.514,0.053 0.75,0.156 0.236,0.104 0.442,0.254 0.618,0.45 0.176,0.197 0.314,0.44 0.414,0.732 0.1,0.292 0.15,0.626 0.15,1.002 0,0.377 -0.05,0.71 -0.15,1.002 C 3.464,2.297 3.326,2.542 3.15,2.742 2.974,2.941 2.768,3.094 2.532,3.198 2.296,3.303 2.046,3.354 1.782,3.354 1.518,3.354 1.268,3.303 1.032,3.198 0.796,3.094 0.59,2.941 0.414,2.742 0.238,2.542 0.1,2.297 0,2.004 -0.1,1.712 -0.15,1.379 -0.15,1.002 -0.15,0.626 -0.1,0.292 0,0 m -1.038,2.28 c 0.128,0.396 0.32,0.74 0.576,1.033 0.256,0.291 0.572,0.521 0.948,0.689 0.376,0.168 0.808,0.252 1.296,0.252 0.496,0 0.93,-0.084 1.302,-0.252 C 3.456,3.834 3.77,3.604 4.026,3.313 4.282,3.02 4.474,2.676 4.602,2.28 4.73,1.885 4.794,1.458 4.794,1.002 4.794,0.547 4.73,0.122 4.602,-0.27 4.474,-0.662 4.282,-1.004 4.026,-1.296 3.77,-1.588 3.456,-1.816 3.084,-1.98 2.712,-2.144 2.278,-2.226 1.782,-2.226 c -0.488,0 -0.92,0.082 -1.296,0.246 -0.376,0.164 -0.692,0.392 -0.948,0.684 -0.256,0.292 -0.448,0.634 -0.576,1.026 -0.128,0.392 -0.192,0.817 -0.192,1.272 0,0.456 0.064,0.883 0.192,1.278"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path266" /></g><g
id="g268"
transform="translate(113.8417,55.8857)"><path
d="m 0,0 v -1.308 h 0.024 c 0.248,0.504 0.552,0.875 0.912,1.116 0.36,0.24 0.816,0.351 1.368,0.336 v -1.08 C 1.896,-0.936 1.548,-0.992 1.26,-1.104 0.972,-1.216 0.74,-1.38 0.564,-1.597 0.388,-1.811 0.26,-2.074 0.18,-2.382 0.1,-2.69 0.06,-3.044 0.06,-3.444 v -2.76 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path270" /></g><g
id="g272"
transform="translate(122.7333,49.6816)"><path
d="m 0,0 v 6.096 h -2.208 v 0.816 c 0.288,0 0.568,0.022 0.84,0.067 0.272,0.042 0.518,0.125 0.738,0.246 0.22,0.119 0.406,0.283 0.558,0.491 C 0.08,7.924 0.184,8.188 0.24,8.508 H 1.02 L 1.02,0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path274" /></g><g
id="g276"
transform="translate(128.8295,54.1035)"><path
d="M 0,0 C -0.216,-0.1 -0.4,-0.236 -0.552,-0.408 -0.704,-0.58 -0.818,-0.784 -0.893,-1.02 -0.97,-1.256 -1.008,-1.506 -1.008,-1.77 c 0,-0.263 0.04,-0.511 0.12,-0.744 0.08,-0.232 0.194,-0.431 0.342,-0.599 0.148,-0.168 0.332,-0.303 0.552,-0.403 0.22,-0.1 0.47,-0.15 0.75,-0.15 0.28,0 0.526,0.05 0.738,0.15 0.212,0.1 0.39,0.239 0.534,0.414 0.144,0.176 0.254,0.378 0.33,0.606 0.076,0.228 0.114,0.467 0.114,0.715 0,0.263 -0.034,0.513 -0.102,0.75 C 2.302,-0.796 2.196,-0.592 2.052,-0.42 1.908,-0.248 1.728,-0.109 1.512,-0.006 1.296,0.098 1.044,0.15 0.756,0.15 0.468,0.15 0.216,0.1 0,0 M 1.848,2.838 C 1.6,3.07 1.272,3.186 0.864,3.186 0.432,3.186 0.084,3.08 -0.18,2.868 -0.444,2.656 -0.65,2.389 -0.798,2.064 -0.946,1.74 -1.048,1.391 -1.104,1.014 -1.16,0.639 -1.192,0.286 -1.2,-0.042 l 0.024,-0.024 c 0.24,0.392 0.538,0.675 0.894,0.852 0.356,0.176 0.766,0.265 1.23,0.265 C 1.356,1.051 1.722,0.98 2.046,0.84 2.37,0.7 2.642,0.506 2.862,0.258 3.082,0.01 3.253,-0.281 3.372,-0.617 3.492,-0.954 3.552,-1.318 3.552,-1.71 3.552,-2.021 3.504,-2.346 3.408,-2.682 3.312,-3.018 3.154,-3.324 2.934,-3.6 2.714,-3.876 2.422,-4.104 2.058,-4.283 1.694,-4.464 1.244,-4.554 0.708,-4.554 c -0.632,0 -1.14,0.128 -1.524,0.384 -0.384,0.256 -0.68,0.584 -0.888,0.984 -0.208,0.4 -0.346,0.84 -0.414,1.321 -0.068,0.479 -0.102,0.943 -0.102,1.391 0,0.583 0.05,1.15 0.15,1.699 0.1,0.546 0.27,1.033 0.511,1.457 C -1.32,3.105 -1,3.445 -0.6,3.702 -0.2,3.958 0.304,4.086 0.912,4.086 1.616,4.086 2.176,3.9 2.592,3.528 3.008,3.156 3.248,2.618 3.312,1.914 H 2.292 C 2.244,2.299 2.096,2.605 1.848,2.838"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path278" /></g><g
id="g280"
transform="translate(138.3159,53.6836)"><path
d="m 0,0 c -0.076,0.275 -0.192,0.521 -0.348,0.738 -0.156,0.216 -0.356,0.388 -0.6,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.876,-0.204 -0.24,-0.137 -0.436,-0.314 -0.588,-0.534 -0.152,-0.22 -0.262,-0.47 -0.33,-0.75 -0.069,-0.28 -0.102,-0.564 -0.102,-0.853 0,-0.303 0.036,-0.597 0.108,-0.88 0.071,-0.286 0.186,-0.536 0.341,-0.75 0.157,-0.217 0.358,-0.391 0.607,-0.523 0.247,-0.132 0.548,-0.198 0.9,-0.198 0.351,0 0.646,0.068 0.882,0.204 0.236,0.136 0.425,0.315 0.569,0.54 0.145,0.224 0.249,0.481 0.312,0.768 0.064,0.289 0.097,0.584 0.097,0.888 C 0.114,-0.559 0.076,-0.275 0,0 M -3.666,2.202 V 1.361 h 0.024 c 0.168,0.345 0.431,0.595 0.792,0.75 0.36,0.156 0.756,0.235 1.188,0.235 0.48,0 0.898,-0.088 1.254,-0.264 C -0.052,1.906 0.244,1.668 0.48,1.368 0.716,1.068 0.893,0.722 1.014,0.33 c 0.12,-0.392 0.18,-0.809 0.18,-1.248 0,-0.44 -0.058,-0.856 -0.175,-1.248 C 0.904,-2.559 0.727,-2.9 0.492,-3.191 0.256,-3.484 -0.041,-3.714 -0.396,-3.882 -0.753,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.153,0 -0.323,0.017 -0.511,0.048 -0.188,0.032 -0.374,0.084 -0.557,0.156 -0.184,0.072 -0.359,0.17 -0.522,0.294 -0.164,0.124 -0.302,0.278 -0.414,0.462 h -0.024 v -3.191 h -1.02 v 8.567 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path282" /></g><g
id="g284"
transform="translate(140.2172,55.8857)"><path
d="M 0,0 H 1.308 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.856 2.4,-3.348 H 4.524 L 2.796,-3.636 1.068,-6.204 H -0.168 L 2.16,-2.94 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path286" /></g><path
d="m 150.225,52.537 h -3.468 v 0.961 h 3.468 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path288" /><g
id="g290"
transform="translate(154.0771,49.6816)"><path
d="m 0,0 v 6.096 h -2.208 v 0.816 c 0.288,0 0.568,0.022 0.84,0.067 0.272,0.042 0.518,0.125 0.738,0.246 0.22,0.119 0.406,0.283 0.558,0.491 C 0.08,7.924 0.184,8.188 0.24,8.508 H 1.02 L 1.02,0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path292" /></g><g
id="g294"
transform="translate(158.1572,56.3769)"><path
d="m 0,0 c 0.112,0.369 0.286,0.686 0.522,0.955 0.236,0.268 0.53,0.478 0.882,0.629 0.352,0.152 0.752,0.228 1.2,0.228 0.368,0 0.714,-0.053 1.038,-0.162 C 3.966,1.543 4.248,1.387 4.488,1.183 4.728,0.979 4.918,0.725 5.058,0.421 5.198,0.117 5.268,-0.235 5.268,-0.635 5.268,-1.012 5.21,-1.344 5.094,-1.631 4.977,-1.92 4.824,-2.178 4.632,-2.405 4.44,-2.633 4.22,-2.84 3.972,-3.023 3.724,-3.207 3.468,-3.383 3.204,-3.551 2.94,-3.711 2.676,-3.869 2.412,-4.025 2.148,-4.182 1.906,-4.348 1.686,-4.523 1.466,-4.699 1.278,-4.889 1.122,-5.094 0.966,-5.297 0.864,-5.531 0.816,-5.795 h 4.368 v -0.9 h -5.556 c 0.04,0.504 0.13,0.933 0.27,1.29 0.14,0.356 0.318,0.666 0.534,0.93 0.216,0.264 0.46,0.495 0.732,0.696 0.272,0.199 0.556,0.387 0.852,0.564 0.36,0.224 0.676,0.43 0.948,0.617 0.272,0.188 0.498,0.379 0.678,0.571 0.18,0.191 0.316,0.4 0.408,0.624 0.092,0.223 0.138,0.483 0.138,0.78 0,0.231 -0.045,0.441 -0.132,0.63 C 3.968,0.194 3.85,0.356 3.702,0.492 3.554,0.629 3.38,0.732 3.18,0.805 2.98,0.877 2.768,0.912 2.544,0.912 2.247,0.912 1.994,0.851 1.782,0.727 1.57,0.603 1.396,0.44 1.26,0.24 1.124,0.041 1.026,-0.186 0.966,-0.437 0.906,-0.689 0.88,-0.943 0.888,-1.199 h -1.02 C -0.156,-0.768 -0.112,-0.367 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path296" /></g><g
id="g298"
transform="translate(165.7832,52.7949)"><path
d="m 0,0 c 0.02,-0.396 0.084,-0.768 0.192,-1.115 0.108,-0.348 0.282,-0.643 0.522,-0.882 0.24,-0.24 0.576,-0.36 1.008,-0.36 0.432,0 0.768,0.12 1.008,0.36 0.24,0.239 0.414,0.534 0.522,0.882 0.108,0.347 0.172,0.719 0.192,1.115 0.02,0.396 0.03,0.755 0.03,1.074 0,0.209 -0.002,0.439 -0.006,0.691 C 3.464,2.017 3.444,2.268 3.408,2.52 3.372,2.773 3.32,3.018 3.252,3.259 3.184,3.498 3.084,3.709 2.952,3.889 2.82,4.068 2.654,4.215 2.454,4.326 2.254,4.438 2.01,4.494 1.722,4.494 1.434,4.494 1.19,4.438 0.99,4.326 0.79,4.215 0.624,4.068 0.492,3.889 0.36,3.709 0.26,3.498 0.192,3.259 0.124,3.018 0.072,2.773 0.036,2.52 0,2.268 -0.02,2.017 -0.024,1.765 -0.028,1.513 -0.03,1.283 -0.03,1.074 -0.03,0.755 -0.02,0.396 0,0 m -1.086,2.035 c 0.016,0.336 0.056,0.664 0.12,0.983 0.064,0.32 0.156,0.625 0.276,0.913 0.12,0.288 0.284,0.54 0.492,0.755 C 0.01,4.902 0.272,5.074 0.588,5.203 0.904,5.33 1.282,5.395 1.722,5.395 2.162,5.395 2.54,5.33 2.856,5.203 3.172,5.074 3.434,4.902 3.642,4.686 3.85,4.471 4.014,4.219 4.134,3.931 4.254,3.643 4.346,3.338 4.41,3.018 4.474,2.699 4.514,2.371 4.53,2.035 4.546,1.699 4.554,1.375 4.554,1.062 4.554,0.75 4.546,0.427 4.53,0.091 4.514,-0.245 4.474,-0.573 4.41,-0.893 4.346,-1.213 4.254,-1.516 4.134,-1.799 4.014,-2.084 3.85,-2.334 3.642,-2.549 3.434,-2.766 3.174,-2.936 2.862,-3.059 2.55,-3.184 2.17,-3.245 1.722,-3.245 c -0.44,0 -0.818,0.061 -1.134,0.186 -0.316,0.123 -0.578,0.293 -0.786,0.51 -0.208,0.215 -0.372,0.465 -0.492,0.75 -0.12,0.283 -0.212,0.586 -0.276,0.906 -0.064,0.32 -0.104,0.648 -0.12,0.984 -0.016,0.336 -0.024,0.659 -0.024,0.971 0,0.313 0.008,0.637 0.024,0.973"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path300" /></g><g
id="g302"
transform="translate(176.3315,53.6836)"><path
d="m 0,0 c -0.076,0.275 -0.192,0.521 -0.348,0.738 -0.156,0.216 -0.356,0.388 -0.6,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.876,-0.204 -0.24,-0.137 -0.436,-0.314 -0.588,-0.534 -0.152,-0.22 -0.262,-0.47 -0.33,-0.75 -0.069,-0.28 -0.102,-0.564 -0.102,-0.853 0,-0.303 0.036,-0.597 0.108,-0.88 0.071,-0.286 0.186,-0.536 0.342,-0.75 0.156,-0.217 0.357,-0.391 0.606,-0.523 0.248,-0.132 0.548,-0.198 0.9,-0.198 0.351,0 0.646,0.068 0.882,0.204 0.236,0.136 0.425,0.315 0.57,0.54 0.144,0.224 0.248,0.481 0.312,0.768 0.063,0.289 0.096,0.584 0.096,0.888 C 0.114,-0.559 0.076,-0.275 0,0 M -3.666,2.202 V 1.361 h 0.024 c 0.168,0.345 0.431,0.595 0.792,0.75 0.36,0.156 0.756,0.235 1.188,0.235 0.48,0 0.898,-0.088 1.254,-0.264 C -0.052,1.906 0.244,1.668 0.48,1.368 0.716,1.068 0.893,0.722 1.014,0.33 c 0.12,-0.392 0.18,-0.809 0.18,-1.248 0,-0.44 -0.058,-0.856 -0.174,-1.248 C 0.904,-2.559 0.727,-2.9 0.492,-3.191 0.256,-3.484 -0.04,-3.714 -0.396,-3.882 -0.752,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.152,0 -0.323,0.017 -0.51,0.048 -0.188,0.032 -0.375,0.084 -0.558,0.156 -0.184,0.072 -0.358,0.17 -0.522,0.294 -0.164,0.124 -0.302,0.278 -0.414,0.462 h -0.024 v -3.191 h -1.02 v 8.567 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path304" /></g><g
id="g306"
transform="translate(178.2329,55.8857)"><path
d="M 0,0 H 1.308 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.856 2.4,-3.348 H 4.524 L 2.796,-3.636 1.068,-6.204 H -0.168 L 2.16,-2.94 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path308" /></g><g
id="g310"
transform="translate(335.6333,72.6504)"><path
d="M 0,0 V -7.607 H 4.536 V -8.568 H -1.14 l 0,8.568 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path312" /></g><g
id="g314"
transform="translate(344.3334,67.0761)"><path
d="m 0,0 c -0.209,-0.044 -0.426,-0.08 -0.654,-0.107 -0.229,-0.029 -0.459,-0.061 -0.691,-0.096 -0.231,-0.037 -0.44,-0.095 -0.624,-0.174 -0.183,-0.08 -0.334,-0.195 -0.449,-0.343 -0.117,-0.147 -0.174,-0.35 -0.174,-0.606 0,-0.168 0.034,-0.31 0.102,-0.426 0.067,-0.115 0.156,-0.209 0.264,-0.281 0.107,-0.072 0.236,-0.125 0.384,-0.156 0.148,-0.033 0.297,-0.049 0.45,-0.049 0.335,0 0.624,0.047 0.864,0.138 0.239,0.092 0.435,0.208 0.588,0.348 0.151,0.141 0.264,0.293 0.336,0.457 0.071,0.163 0.108,0.317 0.108,0.461 V 0.211 C 0.375,0.114 0.207,0.045 0,0 m 1.428,-3.125 c -0.264,0 -0.475,0.073 -0.631,0.221 -0.155,0.148 -0.233,0.39 -0.233,0.726 -0.281,-0.336 -0.607,-0.578 -0.978,-0.726 -0.373,-0.148 -0.774,-0.221 -1.207,-0.221 -0.279,0 -0.543,0.029 -0.791,0.09 -0.248,0.059 -0.467,0.16 -0.654,0.299 -0.188,0.14 -0.336,0.32 -0.444,0.541 -0.109,0.219 -0.162,0.486 -0.162,0.798 0,0.351 0.06,0.639 0.18,0.864 0.119,0.223 0.277,0.405 0.474,0.545 0.196,0.14 0.419,0.246 0.671,0.318 0.252,0.072 0.511,0.133 0.775,0.18 0.279,0.056 0.546,0.098 0.798,0.127 0.252,0.027 0.473,0.067 0.666,0.119 0.192,0.053 0.343,0.129 0.456,0.228 0.111,0.1 0.168,0.246 0.168,0.438 0,0.224 -0.042,0.404 -0.126,0.541 C 0.306,2.098 0.197,2.202 0.066,2.274 -0.066,2.346 -0.215,2.395 -0.379,2.418 -0.543,2.442 -0.705,2.455 -0.864,2.455 -1.297,2.455 -1.656,2.372 -1.944,2.209 -2.232,2.045 -2.389,1.734 -2.412,1.278 h -1.021 c 0.017,0.384 0.097,0.708 0.241,0.972 0.143,0.264 0.336,0.479 0.575,0.643 0.24,0.164 0.517,0.281 0.828,0.353 0.313,0.072 0.641,0.108 0.984,0.108 0.281,0 0.559,-0.02 0.834,-0.059 C 0.306,3.254 0.556,3.172 0.779,3.049 1.004,2.924 1.184,2.75 1.319,2.526 1.455,2.303 1.524,2.01 1.524,1.65 v -3.191 c 0,-0.24 0.013,-0.416 0.042,-0.529 0.028,-0.112 0.122,-0.168 0.282,-0.168 0.088,0 0.191,0.02 0.312,0.06 V -2.97 C 1.983,-3.074 1.74,-3.125 1.428,-3.125"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path316" /></g><g
id="g318"
transform="translate(348.3647,70.2871)"><path
d="m 0,0 v -1.309 h 0.023 c 0.249,0.504 0.553,0.876 0.913,1.117 0.36,0.239 0.816,0.351 1.369,0.335 v -1.08 C 1.897,-0.937 1.549,-0.992 1.26,-1.105 0.973,-1.217 0.74,-1.381 0.565,-1.597 0.389,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.691 0.061,-3.045 0.061,-3.445 v -2.76 H -0.96 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path320" /></g><g
id="g322"
transform="translate(354.4545,65.1211)"><path
d="M 0,0 C 0.236,0.139 0.426,0.323 0.57,0.551 0.715,0.779 0.82,1.037 0.889,1.325 0.956,1.613 0.99,1.901 0.99,2.189 0.99,2.461 0.959,2.729 0.895,2.994 0.83,3.258 0.729,3.496 0.588,3.707 0.448,3.92 0.266,4.09 0.043,4.217 -0.182,4.346 -0.453,4.41 -0.773,4.41 -1.102,4.41 -1.382,4.348 -1.613,4.224 -1.846,4.1 -2.035,3.934 -2.184,3.725 -2.332,3.518 -2.439,3.277 -2.508,3.006 -2.576,2.733 -2.609,2.449 -2.609,2.153 c 0,-0.28 0.027,-0.559 0.084,-0.84 0.055,-0.28 0.152,-0.534 0.287,-0.762 0.136,-0.228 0.316,-0.412 0.541,-0.551 0.223,-0.141 0.504,-0.211 0.84,-0.211 0.336,0 0.621,0.07 0.857,0.211 M 1.303,-2.791 C 0.838,-3.295 0.11,-3.547 -0.881,-3.547 c -0.289,0 -0.582,0.032 -0.883,0.096 -0.299,0.064 -0.572,0.168 -0.816,0.312 -0.244,0.145 -0.445,0.332 -0.606,0.565 -0.16,0.232 -0.248,0.515 -0.263,0.851 h 1.019 c 0.008,-0.183 0.067,-0.34 0.174,-0.468 0.109,-0.127 0.24,-0.231 0.397,-0.311 0.156,-0.08 0.326,-0.139 0.509,-0.175 0.184,-0.036 0.36,-0.054 0.528,-0.054 0.337,0 0.621,0.059 0.852,0.174 0.232,0.116 0.425,0.276 0.576,0.481 0.152,0.203 0.262,0.449 0.331,0.738 0.067,0.287 0.102,0.604 0.102,0.947 V 0.018 H 1.015 C 0.838,-0.367 0.572,-0.648 0.217,-0.828 -0.14,-1.009 -0.518,-1.099 -0.918,-1.099 c -0.464,0 -0.867,0.084 -1.211,0.252 -0.345,0.168 -0.633,0.394 -0.865,0.679 -0.231,0.283 -0.406,0.615 -0.522,0.996 -0.116,0.379 -0.173,0.781 -0.173,1.205 0,0.368 0.047,0.746 0.144,1.135 0.096,0.387 0.256,0.739 0.48,1.056 0.223,0.315 0.52,0.575 0.887,0.78 0.368,0.203 0.821,0.305 1.356,0.305 0.392,0 0.752,-0.086 1.08,-0.258 0.328,-0.172 0.584,-0.43 0.768,-0.774 h 0.013 v 0.889 h 0.959 v -5.677 c 0,-1.015 -0.232,-1.776 -0.695,-2.28"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path324" /></g><g
id="g326"
transform="translate(362.1342,68.4629)"><path
d="M 0,0 C -0.092,0.216 -0.215,0.402 -0.371,0.558 -0.527,0.714 -0.712,0.838 -0.924,0.93 -1.136,1.021 -1.369,1.068 -1.625,1.068 -1.89,1.068 -2.128,1.021 -2.34,0.93 -2.552,0.838 -2.734,0.711 -2.886,0.552 -3.037,0.392 -3.158,0.205 -3.246,-0.006 -3.334,-0.219 -3.386,-0.444 -3.401,-0.685 H 0.162 C 0.147,-0.444 0.092,-0.217 0,0 m 0.246,-3.984 c -0.464,-0.352 -1.048,-0.528 -1.752,-0.528 -0.496,0 -0.926,0.08 -1.289,0.239 -0.365,0.161 -0.671,0.384 -0.918,0.672 -0.248,0.288 -0.434,0.632 -0.558,1.033 -0.125,0.4 -0.195,0.836 -0.21,1.308 0,0.471 0.071,0.903 0.215,1.295 0.145,0.393 0.346,0.733 0.606,1.021 0.26,0.288 0.568,0.511 0.925,0.671 0.355,0.161 0.745,0.241 1.17,0.241 0.551,0 1.009,-0.114 1.374,-0.343 C 0.172,1.397 0.465,1.107 0.685,0.756 0.904,0.403 1.057,0.02 1.141,-0.396 1.225,-0.812 1.258,-1.209 1.242,-1.584 h -4.643 c -0.009,-0.273 0.024,-0.53 0.095,-0.774 0.073,-0.245 0.189,-0.46 0.349,-0.648 0.159,-0.188 0.363,-0.338 0.611,-0.451 0.248,-0.111 0.54,-0.168 0.876,-0.168 0.433,0 0.786,0.1 1.062,0.301 0.277,0.199 0.459,0.504 0.547,0.912 H 1.147 C 1.01,-3.108 0.711,-3.633 0.246,-3.984"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path328" /></g><g
id="g330"
transform="translate(365.3569,70.2871)"><path
d="m 0,0 v -1.309 h 0.023 c 0.248,0.504 0.553,0.876 0.912,1.117 0.36,0.239 0.817,0.351 1.369,0.335 v -1.08 C 1.895,-0.937 1.548,-0.992 1.26,-1.105 0.972,-1.217 0.739,-1.381 0.563,-1.597 0.388,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.691 0.06,-3.045 0.06,-3.445 v -2.76 H -0.961 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path332" /></g><g
id="g334"
transform="translate(318.2573,54.9863)"><path
d="m 0,0 v 0.9 h 1.044 v 0.924 c 0,0.504 0.145,0.887 0.438,1.147 C 1.773,3.23 2.199,3.36 2.76,3.36 2.855,3.36 2.966,3.352 3.09,3.336 3.214,3.32 3.324,3.297 3.42,3.264 V 2.377 C 3.332,2.408 3.236,2.43 3.132,2.442 3.027,2.454 2.932,2.461 2.844,2.461 2.596,2.461 2.404,2.412 2.268,2.316 2.132,2.221 2.064,2.036 2.064,1.764 V 0.9 h 1.2 V 0 h -1.2 V -5.304 H 1.044 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path336" /></g><g
id="g338"
transform="translate(323.3276,51.7773)"><path
d="m 0,0 c 0.1,-0.293 0.237,-0.537 0.414,-0.732 0.176,-0.197 0.381,-0.346 0.617,-0.451 0.237,-0.104 0.487,-0.156 0.75,-0.156 0.264,0 0.514,0.052 0.75,0.156 0.237,0.105 0.442,0.254 0.618,0.451 0.176,0.195 0.314,0.439 0.415,0.732 0.1,0.291 0.149,0.625 0.149,1.002 0,0.375 -0.049,0.709 -0.149,1.002 C 3.463,2.295 3.325,2.541 3.149,2.741 2.973,2.941 2.768,3.094 2.531,3.197 2.295,3.301 2.045,3.354 1.781,3.354 1.518,3.354 1.268,3.301 1.031,3.197 0.795,3.094 0.59,2.941 0.414,2.741 0.237,2.541 0.1,2.295 0,2.004 -0.101,1.711 -0.15,1.377 -0.15,1.002 -0.15,0.625 -0.101,0.291 0,0 m -1.039,2.279 c 0.129,0.397 0.32,0.741 0.576,1.032 0.256,0.293 0.572,0.523 0.948,0.691 0.376,0.168 0.808,0.252 1.296,0.252 0.496,0 0.93,-0.084 1.303,-0.252 C 3.455,3.834 3.77,3.604 4.025,3.311 4.281,3.02 4.473,2.676 4.602,2.279 4.73,1.883 4.793,1.457 4.793,1.002 4.793,0.545 4.73,0.121 4.602,-0.27 4.473,-0.662 4.281,-1.005 4.025,-1.297 3.77,-1.589 3.455,-1.816 3.084,-1.98 2.711,-2.145 2.277,-2.227 1.781,-2.227 c -0.488,0 -0.92,0.082 -1.296,0.247 -0.376,0.164 -0.692,0.391 -0.948,0.683 -0.256,0.292 -0.447,0.635 -0.576,1.027 -0.127,0.391 -0.191,0.815 -0.191,1.272 0,0.455 0.064,0.881 0.191,1.277"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path340" /></g><g
id="g342"
transform="translate(330.2456,55.8867)"><path
d="m 0,0 v -1.309 h 0.023 c 0.248,0.504 0.553,0.877 0.913,1.118 0.359,0.239 0.816,0.351 1.368,0.336 V -0.936 C 1.896,-0.936 1.548,-0.992 1.26,-1.104 0.972,-1.217 0.739,-1.38 0.563,-1.596 0.388,-1.812 0.26,-2.074 0.18,-2.383 0.1,-2.689 0.06,-3.044 0.06,-3.444 v -2.76 H -0.961 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path344" /></g><g
id="g346"
transform="translate(339.1362,49.6826)"><path
d="m 0,0 v 6.097 h -2.207 v 0.815 c 0.287,0 0.567,0.023 0.84,0.065 0.271,0.045 0.517,0.128 0.738,0.247 0.219,0.121 0.405,0.284 0.558,0.492 C 0.08,7.924 0.185,8.189 0.24,8.508 H 1.02 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path348" /></g><g
id="g350"
transform="translate(343.2172,56.3789)"><path
d="M 0,0 C 0.112,0.367 0.286,0.686 0.522,0.953 0.758,1.222 1.052,1.432 1.403,1.584 1.756,1.735 2.155,1.811 2.604,1.811 2.972,1.811 3.317,1.758 3.642,1.65 3.966,1.541 4.248,1.386 4.487,1.182 4.728,0.977 4.918,0.724 5.058,0.42 5.198,0.115 5.269,-0.236 5.269,-0.637 5.269,-1.012 5.21,-1.344 5.094,-1.633 4.978,-1.92 4.823,-2.178 4.632,-2.406 4.44,-2.635 4.22,-2.84 3.972,-3.024 3.724,-3.209 3.468,-3.385 3.204,-3.553 2.94,-3.713 2.676,-3.87 2.411,-4.026 2.147,-4.182 1.905,-4.349 1.687,-4.524 1.466,-4.7 1.278,-4.891 1.122,-5.094 0.966,-5.299 0.864,-5.532 0.815,-5.797 h 4.37 v -0.899 h -5.557 c 0.04,0.504 0.13,0.934 0.269,1.29 0.141,0.355 0.319,0.666 0.535,0.929 0.215,0.264 0.46,0.497 0.732,0.697 0.272,0.2 0.556,0.387 0.852,0.563 0.36,0.225 0.676,0.431 0.948,0.619 0.271,0.188 0.498,0.377 0.678,0.57 0.179,0.192 0.316,0.399 0.408,0.624 0.092,0.224 0.139,0.484 0.139,0.779 0,0.232 -0.045,0.443 -0.133,0.631 C 3.968,0.193 3.85,0.355 3.702,0.492 3.554,0.627 3.38,0.732 3.18,0.804 2.979,0.875 2.768,0.912 2.544,0.912 2.247,0.912 1.993,0.85 1.782,0.726 1.569,0.602 1.396,0.439 1.26,0.24 1.124,0.039 1.026,-0.187 0.966,-0.439 0.905,-0.691 0.88,-0.944 0.888,-1.2 h -1.02 C -0.156,-0.768 -0.112,-0.368 0,0"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path352" /></g><g
id="g354"
transform="translate(350.8432,52.7968)"><path
d="m 0,0 c 0.02,-0.396 0.084,-0.768 0.191,-1.116 0.109,-0.349 0.283,-0.642 0.523,-0.882 0.239,-0.24 0.575,-0.36 1.008,-0.36 0.432,0 0.768,0.12 1.008,0.36 0.24,0.24 0.414,0.533 0.522,0.882 0.107,0.348 0.172,0.72 0.191,1.116 0.02,0.396 0.031,0.754 0.031,1.074 0,0.207 -0.002,0.438 -0.006,0.69 C 3.463,2.016 3.443,2.268 3.408,2.52 3.371,2.771 3.32,3.018 3.252,3.258 3.184,3.498 3.084,3.707 2.951,3.888 2.82,4.068 2.654,4.213 2.453,4.326 2.254,4.437 2.01,4.494 1.722,4.494 1.434,4.494 1.189,4.437 0.99,4.326 0.789,4.213 0.623,4.068 0.492,3.888 0.359,3.707 0.26,3.498 0.191,3.258 0.123,3.018 0.072,2.771 0.035,2.52 0,2.268 -0.021,2.016 -0.024,1.764 -0.028,1.512 -0.03,1.281 -0.03,1.074 -0.03,0.754 -0.021,0.396 0,0 m -1.086,2.033 c 0.016,0.336 0.056,0.664 0.119,0.985 0.065,0.32 0.156,0.624 0.277,0.912 0.12,0.288 0.284,0.54 0.492,0.756 C 0.01,4.902 0.271,5.074 0.588,5.201 0.904,5.33 1.281,5.394 1.722,5.394 2.162,5.394 2.539,5.33 2.855,5.201 3.172,5.074 3.434,4.902 3.642,4.686 3.85,4.47 4.014,4.218 4.134,3.93 4.254,3.642 4.346,3.338 4.41,3.018 4.474,2.697 4.514,2.369 4.529,2.033 4.546,1.697 4.554,1.373 4.554,1.062 4.554,0.75 4.546,0.426 4.529,0.09 4.514,-0.246 4.474,-0.574 4.41,-0.895 4.346,-1.215 4.254,-1.517 4.134,-1.801 4.014,-2.084 3.85,-2.334 3.642,-2.551 3.434,-2.766 3.174,-2.936 2.861,-3.061 2.55,-3.184 2.17,-3.246 1.722,-3.246 c -0.441,0 -0.818,0.062 -1.134,0.185 -0.317,0.125 -0.578,0.295 -0.786,0.51 -0.208,0.217 -0.372,0.467 -0.492,0.75 -0.121,0.284 -0.212,0.586 -0.277,0.906 -0.063,0.321 -0.103,0.649 -0.119,0.985 -0.017,0.336 -0.024,0.66 -0.024,0.972 0,0.311 0.007,0.635 0.024,0.971"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path356" /></g><g
id="g358"
transform="translate(361.3911,53.6845)"><path
d="m 0,0 c -0.076,0.276 -0.192,0.522 -0.349,0.738 -0.156,0.216 -0.355,0.388 -0.599,0.516 -0.244,0.128 -0.531,0.192 -0.858,0.192 -0.344,0 -0.636,-0.068 -0.877,-0.204 -0.24,-0.136 -0.435,-0.313 -0.588,-0.534 -0.152,-0.221 -0.261,-0.471 -0.33,-0.75 -0.068,-0.28 -0.101,-0.564 -0.101,-0.852 0,-0.304 0.036,-0.598 0.107,-0.882 0.073,-0.284 0.187,-0.534 0.342,-0.75 0.156,-0.216 0.358,-0.39 0.607,-0.522 0.248,-0.133 0.547,-0.198 0.9,-0.198 0.351,0 0.645,0.067 0.882,0.204 0.236,0.136 0.425,0.316 0.57,0.54 0.144,0.224 0.248,0.48 0.312,0.769 0.063,0.287 0.096,0.584 0.096,0.886 C 0.114,-0.558 0.075,-0.276 0,0 m -3.666,2.202 v -0.84 h 0.024 c 0.168,0.344 0.432,0.594 0.791,0.75 0.361,0.157 0.756,0.235 1.189,0.235 0.479,0 0.897,-0.089 1.254,-0.265 C -0.052,1.905 0.243,1.668 0.479,1.368 0.716,1.067 0.893,0.722 1.014,0.33 c 0.12,-0.392 0.18,-0.808 0.18,-1.248 0,-0.44 -0.058,-0.856 -0.174,-1.248 C 0.903,-2.558 0.728,-2.899 0.491,-3.192 0.256,-3.483 -0.04,-3.714 -0.396,-3.882 -0.753,-4.05 -1.167,-4.134 -1.638,-4.134 c -0.152,0 -0.322,0.016 -0.51,0.048 -0.189,0.032 -0.374,0.084 -0.558,0.155 -0.184,0.073 -0.358,0.17 -0.522,0.295 -0.164,0.123 -0.302,0.278 -0.414,0.462 h -0.024 v -3.192 h -1.021 v 8.568 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path360" /></g><g
id="g362"
transform="translate(363.2924,55.8867)"><path
d="M 0,0 H 1.309 L 2.796,-2.172 4.344,0 h 1.224 l -2.136,-2.855 2.4,-3.349 H 4.523 L 2.796,-3.637 1.068,-6.204 h -1.236 l 2.328,3.265 z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path364" /></g><g
id="g366"
transform="translate(379.1928,53.1269)"><path
d="m 0,0 v -0.816 h -2.616 v -2.628 h -0.816 v 2.628 H -6.048 V 0 h 2.616 v 2.627 h 0.816 V 0 Z"
style="fill:#176fc1;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path368" /></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,13 +0,0 @@
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg">
<title/>
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="402" width="582" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<path fill="#ffffff" id="svg_1" d="m293.9,450l-60.37,0a15,15 0 0 1 -14.92,-13.42l-4.47,-42.09a152.77,152.77 0 0 1 -18.25,-7.56l-32.89,26.6a15,15 0 0 1 -20,-1.06l-42.69,-42.69a15,15 0 0 1 -1.06,-20l26.61,-32.93a152.15,152.15 0 0 1 -7.57,-18.25l-42.16,-4.5a15,15 0 0 1 -13.42,-14.91l0,-60.38a15,15 0 0 1 13.42,-14.91l42.09,-4.47a152.15,152.15 0 0 1 7.57,-18.25l-26.61,-32.93a15,15 0 0 1 1.06,-20l42.69,-42.69a15,15 0 0 1 20,-1.06l32.93,26.6a152.77,152.77 0 0 1 18.25,-7.56l4.47,-42.09a15,15 0 0 1 14.95,-13.45l60.37,0a15,15 0 0 1 14.92,13.42l4.46,42.09a152.91,152.91 0 0 1 18.26,7.56l32.92,-26.6a15,15 0 0 1 20,1.06l42.69,42.69a15,15 0 0 1 1.06,20l-26.61,32.93a153.8,153.8 0 0 1 7.57,18.25l42.09,4.47a15,15 0 0 1 13.41,14.91l0,60.38a15,15 0 0 1 -13.37,14.94l-42.09,4.47a153.8,153.8 0 0 1 -7.57,18.25l26.61,32.93a15,15 0 0 1 -1.06,20l-42.69,42.72a15,15 0 0 1 -20,1.06l-32.92,-26.6a152.91,152.91 0 0 1 -18.26,7.56l-4.46,42.09a15,15 0 0 1 -14.96,13.42zm-46.9,-30l33.39,0l4.09,-38.56a15,15 0 0 1 11.06,-12.91a123,123 0 0 0 30.16,-12.53a15,15 0 0 1 17,1.31l30.16,24.37l23.61,-23.61l-24.41,-30.07a15,15 0 0 1 -1.31,-17a122.63,122.63 0 0 0 12.49,-30.14a15,15 0 0 1 12.92,-11.06l38.55,-4.1l0,-33.39l-38.55,-4.1a15,15 0 0 1 -12.92,-11.06a122.63,122.63 0 0 0 -12.49,-30.15a15,15 0 0 1 1.31,-17l24.37,-30.16l-23.61,-23.61l-30.16,24.37a15,15 0 0 1 -17,1.31a123,123 0 0 0 -30.14,-12.49a15,15 0 0 1 -11.06,-12.91l-4.05,-38.51l-33.41,0l-4.09,38.56a15,15 0 0 1 -11.07,12.91a122.79,122.79 0 0 0 -30.11,12.53a15,15 0 0 1 -17,-1.31l-30.13,-24.41l-23.6,23.61l24.38,30.16a15,15 0 0 1 1.3,17a123.41,123.41 0 0 0 -12.49,30.14a15,15 0 0 1 -12.91,11.06l-38.56,4.1l0,33.38l38.56,4.1a15,15 0 0 1 12.91,11.06a123.41,123.41 0 0 0 12.48,30.11a15,15 0 0 1 -1.3,17l-24.37,30.11l23.61,23.61l30.17,-24.37a15,15 0 0 1 17,-1.31a122.79,122.79 0 0 0 30.13,12.49a15,15 0 0 1 11.07,12.91l4.02,38.56zm202.71,-140.81l0,0z"/>
<path fill="#ffffff" id="svg_2" d="m263.71,340.36a91.36,91.36 0 1 1 91.37,-91.36a91.46,91.46 0 0 1 -91.37,91.36zm0,-152.72a61.36,61.36 0 1 0 61.37,61.36a61.43,61.43 0 0 0 -61.37,-61.36z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,12 +0,0 @@
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="402" width="582" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<circle id="svg_1" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke="#ffffff" r="24" fill="none" cy="25" cx="25"/>
<path id="svg_3" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke="#ffffff" fill="none" d="m29.933,35.528c-0.146,-1.612 -0.09,-2.737 -0.09,-4.21c0.73,-0.383 2.038,-2.825 2.259,-4.888c0.574,-0.047 1.479,-0.607 1.744,-2.818c0.143,-1.187 -0.425,-1.855 -0.771,-2.065c0.934,-2.809 2.874,-11.499 -3.588,-12.397c-0.665,-1.168 -2.368,-1.759 -4.581,-1.759c-8.854,0.163 -9.922,6.686 -7.981,14.156c-0.345,0.21 -0.913,0.878 -0.771,2.065c0.266,2.211 1.17,2.771 1.744,2.818c0.22,2.062 1.58,4.505 2.312,4.888c0,1.473 0.055,2.598 -0.091,4.21c-1.261,3.39 -7.737,3.655 -11.473,6.924c3.906,3.933 10.236,6.746 16.916,6.746s14.532,-5.274 15.839,-6.713c-3.713,-3.299 -10.204,-3.555 -11.468,-6.957z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -4,22 +4,30 @@ using System.Text;
using System.Windows; using System.Windows;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Attached property base class /// Attached property base class
/// </summary> /// </summary>
/// <typeparam name="Parent"></typeparam> /// <typeparam name="TParent"></typeparam>
/// <typeparam name="Property"></typeparam> /// <typeparam name="TProperty"></typeparam>
public abstract class BaseAttachedProperty<Parent, Property> public abstract class BaseAttachedProperty<TParent, TProperty>
where Parent : BaseAttachedProperty<Parent, Property>, new() { where TParent : BaseAttachedProperty<TParent, TProperty>, new() {
public event Action<DependencyObject, DependencyPropertyChangedEventArgs> ValueChanged = (sender, e) => { }; public event Action<DependencyObject, DependencyPropertyChangedEventArgs> ValueChanged = (sender, e) => { };
public static Parent Instance { get; private set; } = new Parent();
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(Property), typeof(BaseAttachedProperty<Parent, Property>), new PropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged))); public static TParent Instance { get; private set; } = new TParent();
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(TProperty), typeof(BaseAttachedProperty<TParent, TProperty>), new PropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged)));
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
Instance.OnValueChanged(d, e); Instance.OnValueChanged(d, e);
Instance.ValueChanged(d, e); Instance.ValueChanged(d, e);
} }
public static Property GetValue(DependencyObject d) => (Property)d.GetValue(ValueProperty);
public static void SetValue(DependencyObject d, Property value) => d.SetValue(ValueProperty, value); public static TProperty GetValue(DependencyObject d) => (TProperty)d.GetValue(ValueProperty);
public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }
public static void SetValue(DependencyObject d, TProperty value) => d.SetValue(ValueProperty, value);
public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
}
} }
} }

View File

@@ -6,7 +6,9 @@ using System.Windows;
using System.Windows.Documents; using System.Windows.Documents;
namespace Server_Dashboard { namespace Server_Dashboard {
public static class HyperlinkExtensions { public static class HyperlinkExtensions {
public static bool GetIsExternal(DependencyObject obj) { public static bool GetIsExternal(DependencyObject obj) {
return (bool)obj.GetValue(IsExternalProperty); return (bool)obj.GetValue(IsExternalProperty);
} }
@@ -14,22 +16,24 @@ namespace Server_Dashboard {
public static void SetIsExternal(DependencyObject obj, bool value) { public static void SetIsExternal(DependencyObject obj, bool value) {
obj.SetValue(IsExternalProperty, value); obj.SetValue(IsExternalProperty, value);
} }
public static readonly DependencyProperty IsExternalProperty = public static readonly DependencyProperty IsExternalProperty =
DependencyProperty.RegisterAttached("IsExternal", typeof(bool), typeof(HyperlinkExtensions), new UIPropertyMetadata(false, OnIsExternalChanged)); DependencyProperty.RegisterAttached("IsExternal", typeof(bool), typeof(HyperlinkExtensions), new UIPropertyMetadata(false, OnIsExternalChanged));
private static void OnIsExternalChanged(object sender, DependencyPropertyChangedEventArgs args) { private static void OnIsExternalChanged(object sender, DependencyPropertyChangedEventArgs args) {
var hyperlink = sender as Hyperlink; var hyperlink = sender as Hyperlink;
if ((bool)args.NewValue) if ((bool)args.NewValue) {
if (hyperlink != null)
hyperlink.RequestNavigate += Hyperlink_RequestNavigate; hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
else } else if (hyperlink != null)
hyperlink.RequestNavigate -= Hyperlink_RequestNavigate; hyperlink.RequestNavigate -= Hyperlink_RequestNavigate;
} }
private static void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) { private static void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) {
try { try {
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true }); Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
} catch { } } catch (Exception) { }
e.Handled = true; e.Handled = true;
} }
} }

View File

@@ -2,18 +2,19 @@
using System.Windows.Controls; using System.Windows.Controls;
namespace Server_Dashboard { namespace Server_Dashboard {
public class MonitorPasswordProperty : BaseAttachedProperty<MonitorPasswordProperty, bool> { public class MonitorPasswordProperty : BaseAttachedProperty<MonitorPasswordProperty, bool> {
public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
var passwordBox = sender as PasswordBox; if (!(sender is PasswordBox passwordBox))
if (passwordBox == null)
return; return;
passwordBox.PasswordChanged -= PasswordBox_PasswordChanged; passwordBox.PasswordChanged -= PasswordBox_PasswordChanged;
if ((bool)e.NewValue) { if (!(bool)e.NewValue)
return;
HasTextProperty.SetValue(passwordBox); HasTextProperty.SetValue(passwordBox);
passwordBox.PasswordChanged += PasswordBox_PasswordChanged; passwordBox.PasswordChanged += PasswordBox_PasswordChanged;
} }
}
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e) { private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e) {
HasTextProperty.SetValue((PasswordBox)sender); HasTextProperty.SetValue((PasswordBox)sender);
@@ -21,6 +22,7 @@ namespace Server_Dashboard {
} }
public class HasTextProperty : BaseAttachedProperty<HasTextProperty, bool> { public class HasTextProperty : BaseAttachedProperty<HasTextProperty, bool> {
public static void SetValue(DependencyObject sender) { public static void SetValue(DependencyObject sender) {
SetValue(sender, ((PasswordBox)sender).SecurePassword.Length < 1); SetValue(sender, ((PasswordBox)sender).SecurePassword.Length < 1);
} }

View File

@@ -1,7 +1,9 @@
using System.Windows; using System.Windows;
namespace Server_Dashboard { namespace Server_Dashboard {
public class CloseProperty : BaseAttachedProperty<CloseProperty, bool> { public class CloseProperty : BaseAttachedProperty<CloseProperty, bool> {
public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
if (sender is Window window) { if (sender is Window window) {
window.Loaded += (s, e) => { window.Loaded += (s, e) => {

View File

@@ -1,168 +0,0 @@
<Window x:Class="Server_Dashboard.Views.DashboardPages.ModuleCRUD.CreateModulePopup"
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:Server_Dashboard.Views.DashboardPages.ModuleCRUD"
xmlns:root="clr-namespace:Server_Dashboard" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
d:DataContext="{d:DesignInstance Type=root:DashboardModuleViewModel}"
mc:Ignorable="d" ResizeMode="NoResize" Height="700" Width="500" d:WindowStyle="None">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0"/>
</WindowChrome.WindowChrome>
<!--Create new Server Form-->
<Border Width="500" Height="700">
<Border.Background>
<SolidColorBrush Color="#2D2D2D" Opacity="1"/>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Title Bar-->
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Create a new Server" Margin="5 0 0 0" Foreground="{StaticResource DeepPurple_A100}" VerticalAlignment="Center"/>
<Button Style="{StaticResource CloseButton}" Grid.Column="2" Content="✕" Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="1" Margin="20">
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--Server Name-->
<StackPanel VerticalAlignment="Center" Grid.Row="0" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Server Name" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/>
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="*" Foreground="{StaticResource ErrorRed}" FontSize="20"/>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<TextBox Text="{Binding ServerName}" Grid.Column="1" Height="40" FontSize="20" x:Name="ServerName"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="My Awesome Server" FontSize="20" Visibility="{Binding ElementName=ServerName, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Password-->
<StackPanel VerticalAlignment="Center" Grid.Row="1" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Password" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/>
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="*" Foreground="{StaticResource ErrorRed}" FontSize="20"/>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<PasswordBox Width="420" VerticalAlignment="Center" HorizontalAlignment="Left" root:MonitorPasswordProperty.Value="True" Grid.Column="1" FontSize="20" x:Name="Password" Height="40">
</PasswordBox>
<TextBlock Visibility="{Binding ElementName=Password, Path=(root:HasTextProperty.Value), Converter={StaticResource UserNameVisibillity}}" x:Name="PasswordHint" Text="********" Grid.Column="1" IsHitTestVisible="False" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5 0 0 0" FontSize="20">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Username-->
<StackPanel VerticalAlignment="Center" Grid.Row="2" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Username" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/>
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="*" Foreground="{StaticResource ErrorRed}" FontSize="16"/>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<TextBox Text="{Binding Username}" Grid.Column="1" Height="40" FontSize="20" x:Name="UserName"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="Name" FontSize="20" Visibility="{Binding ElementName=UserName, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--IP Adress-->
<StackPanel VerticalAlignment="Center" Grid.Row="3" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="IP Adress" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/>
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="*" Foreground="{StaticResource ErrorRed}" FontSize="16"/>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<TextBox Text="{Binding IPAdress}" Grid.Column="1" Height="40" FontSize="20" x:Name="IPAdress"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="sample.ssh.com" FontSize="20" Visibility="{Binding ElementName=IPAdress, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Port-->
<StackPanel VerticalAlignment="Center" Grid.Row="4" Margin="20 0 20 0">
<TextBlock Text="Port" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/>
</TextBlock.Foreground>
</TextBlock>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0"/>
</Grid.Effect>
<TextBox Text="{Binding Port}" Grid.Column="1" Height="40" FontSize="20" x:Name="Port"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="22" FontSize="20" Visibility="{Binding ElementName=Port, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Create Module button-->
<Button Height="60" Width="350" Command="{Binding CreateModuleCommand}" CommandParameter="{Binding ElementName=CREATE_MODULE}" Grid.Row="5" Content="CREATE MODULE" Grid.ColumnSpan="2"/>
</Grid>
</Grid>
</Border>
</Window>

View File

@@ -10,15 +10,15 @@
x:Name="_this" x:Name="_this"
d:DesignHeight="50" d:DesignWidth="50"> d:DesignHeight="50" d:DesignWidth="50">
<UserControl.Resources> <UserControl.Resources>
<root:ValueToAngleConverter x:Key="valueToAngle"/> <root:ValueToAngleConverter x:Key="valueToAngle" />
</UserControl.Resources> </UserControl.Resources>
<!--Circular Prograss bar--> <!--Circular Progress bar-->
<Grid> <Grid>
<Ellipse x:Name="Background" Fill="{Binding ElementName=_this, Path=BackgroundBrush}" Margin="0" Stroke="{Binding ElementName=_this, Path=BackgroundBrush}"/> <Ellipse x:Name="Background" Fill="{Binding ElementName=_this, Path=BackgroundBrush}" Margin="0" Stroke="{Binding ElementName=_this, Path=BackgroundBrush}" />
<ed:Arc ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=ValueRead}" Fill="{Binding ElementName=_this, Path=ReadIndicatorBrush}" Stretch="None" StartAngle="0"/> <ed:Arc ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=ValueRead}" Fill="{Binding ElementName=_this, Path=ReadIndicatorBrush}" Stretch="None" StartAngle="0" />
<Ellipse x:Name="Seperator" Fill="Transparent" Margin="7" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" Panel.ZIndex="1"/> <Ellipse x:Name="Seperator" Fill="Transparent" Margin="7" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" Panel.ZIndex="1" />
<Ellipse x:Name="Seperator2" Fill="Transparent" Margin="8" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" Panel.ZIndex="1"/> <Ellipse x:Name="Seperator2" Fill="Transparent" Margin="8" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" Panel.ZIndex="1" />
<ed:Arc Margin="8" ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=ValueWrite}" Fill="{Binding ElementName=_this, Path=WriteIndicatorBrush}" Stretch="None" StartAngle="0"/> <ed:Arc Margin="8" ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=ValueWrite}" Fill="{Binding ElementName=_this, Path=WriteIndicatorBrush}" Stretch="None" StartAngle="0" />
<Ellipse x:Name="Border" Fill="{Binding ElementName=_this, Path=ProgressBorderBrush}" Margin="16" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}"/> <Ellipse x:Name="Border" Fill="{Binding ElementName=_this, Path=ProgressBorderBrush}" Margin="16" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" />
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -1,63 +1,60 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Server_Dashboard.Controls.DoubleRoundProgressBar { namespace Server_Dashboard.Controls.DoubleRoundProgressBar {
/// <summary> /// <summary>
/// DependencyProperties /// DependencyProperties
/// </summary> /// </summary>
public partial class DoubleRoundProgressBar : UserControl { public partial class DoubleRoundProgressBar : UserControl {
//Property for the ReadIndicatorBrush //Property for the ReadIndicatorBrush
public static DependencyProperty ReadIndicatorBrushProperty = DependencyProperty.Register("ReadIndicatorBrush", typeof(Brush), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty ReadIndicatorBrushProperty = DependencyProperty.Register("ReadIndicatorBrush", typeof(Brush), typeof(DoubleRoundProgressBar));
public Brush ReadIndicatorBrush { public Brush ReadIndicatorBrush {
get { return (Brush)GetValue(ReadIndicatorBrushProperty); } get => (Brush)GetValue(ReadIndicatorBrushProperty);
set { SetValue(ReadIndicatorBrushProperty, value); } set => SetValue(ReadIndicatorBrushProperty, value);
} }
//Property for the WriteIndicatorBrush //Property for the WriteIndicatorBrush
public static DependencyProperty WriteIndicatorBrushProperty = DependencyProperty.Register("WriteIndicatorBrush", typeof(Brush), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty WriteIndicatorBrushProperty = DependencyProperty.Register("WriteIndicatorBrush", typeof(Brush), typeof(DoubleRoundProgressBar));
public Brush WriteIndicatorBrush { public Brush WriteIndicatorBrush {
get { return (Brush)GetValue(WriteIndicatorBrushProperty); } get => (Brush)GetValue(WriteIndicatorBrushProperty);
set { SetValue(WriteIndicatorBrushProperty, value); } set => SetValue(WriteIndicatorBrushProperty, value);
} }
//Property for the BackgroundBrush //Property for the BackgroundBrush
public static DependencyProperty BackgroundBrushProperty = DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty BackgroundBrushProperty = DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(DoubleRoundProgressBar));
public Brush BackgroundBrush { public Brush BackgroundBrush {
get { return (Brush)GetValue(BackgroundBrushProperty); } get => (Brush)GetValue(BackgroundBrushProperty);
set { SetValue(BackgroundBrushProperty, value); } set => SetValue(BackgroundBrushProperty, value);
} }
//Property for the ProgressBorderBrush //Property for the ProgressBorderBrush
public static DependencyProperty ProgressBorderBrushProperty = DependencyProperty.Register("ProgressBorderBrush", typeof(Brush), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty ProgressBorderBrushProperty = DependencyProperty.Register("ProgressBorderBrush", typeof(Brush), typeof(DoubleRoundProgressBar));
public Brush ProgressBorderBrush { public Brush ProgressBorderBrush {
get { return (Brush)GetValue(ProgressBorderBrushProperty); } get => (Brush)GetValue(ProgressBorderBrushProperty);
set { SetValue(ProgressBorderBrushProperty, value); } set => SetValue(ProgressBorderBrushProperty, value);
} }
//Property for the Value Write //Property for the Value Write
public static DependencyProperty ValueWriteProperty = DependencyProperty.Register("ValueWrite", typeof(int), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty ValueWriteProperty = DependencyProperty.Register("ValueWrite", typeof(int), typeof(DoubleRoundProgressBar));
public int ValueWrite { public int ValueWrite {
get { return (int)GetValue(ValueWriteProperty); } get => (int)GetValue(ValueWriteProperty);
set { SetValue(ValueWriteProperty, value); } set => SetValue(ValueWriteProperty, value);
} }
//Property for the Value Read //Property for the Value Read
public static DependencyProperty ValueReadProperty = DependencyProperty.Register("ValueRead", typeof(int), typeof(DoubleRoundProgressBar)); public static readonly DependencyProperty ValueReadProperty = DependencyProperty.Register("ValueRead", typeof(int), typeof(DoubleRoundProgressBar));
public int ValueRead { public int ValueRead {
get { return (int)GetValue(ValueReadProperty); } get => (int)GetValue(ValueReadProperty);
set { SetValue(ValueReadProperty, value); } set => SetValue(ValueReadProperty, value);
} }
public DoubleRoundProgressBar() { public DoubleRoundProgressBar() {

View File

@@ -8,12 +8,12 @@
xmlns:root="clr-namespace:Server_Dashboard" xmlns:root="clr-namespace:Server_Dashboard"
mc:Ignorable="d" x:Name="_this" d:DesignHeight="50" d:DesignWidth="50"> mc:Ignorable="d" x:Name="_this" d:DesignHeight="50" d:DesignWidth="50">
<UserControl.Resources> <UserControl.Resources>
<root:ValueToAngleConverter x:Key="valueToAngle"/> <root:ValueToAngleConverter x:Key="valueToAngle" />
</UserControl.Resources> </UserControl.Resources>
<!--Progress bar but just half round--> <!--Progress bar but just half round-->
<Grid> <Grid>
<Ellipse x:Name="Background" Fill="{Binding ElementName=_this, Path=BackgroundBrush}" Margin="0" Stroke="{Binding ElementName=_this, Path=BackgroundBrush}"/> <Ellipse x:Name="Background" Fill="{Binding ElementName=_this, Path=BackgroundBrush}" Margin="0" Stroke="{Binding ElementName=_this, Path=BackgroundBrush}" />
<ed:Arc ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=Value}" Fill="{Binding ElementName=_this, Path=IndicatorBrush}" Stretch="None" StartAngle="0"/> <ed:Arc ArcThickness="8" ArcThicknessUnit="Pixel" EndAngle="{Binding Converter={StaticResource valueToAngle}, ElementName=_this, Path=Value}" Fill="{Binding ElementName=_this, Path=IndicatorBrush}" Stretch="None" StartAngle="0" />
<Ellipse x:Name="Border" Fill="{Binding ElementName=_this, Path=ProgressBorderBrush}" Margin="8" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}"/> <Ellipse x:Name="Border" Fill="{Binding ElementName=_this, Path=ProgressBorderBrush}" Margin="8" Stroke="{Binding ElementName=_this, Path=ProgressBorderBrush}" />
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -1,49 +1,44 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Server_Dashboard.Controls.HalfRoundProgressBar { namespace Server_Dashboard.Controls.HalfRoundProgressBar {
/// <summary> /// <summary>
/// Dependency Properties /// Dependency Properties
/// </summary> /// </summary>
public partial class HalfRoundProgressBar : UserControl { public partial class HalfRoundProgressBar : UserControl {
//Indicator Brush Property //Indicator Brush Property
public static DependencyProperty IndicatorBrushProperty = DependencyProperty.Register("IndicatorBrush", typeof(Brush), typeof(HalfRoundProgressBar)); public static readonly DependencyProperty IndicatorBrushProperty = DependencyProperty.Register("IndicatorBrush", typeof(Brush), typeof(HalfRoundProgressBar));
public Brush IndicatorBrush { public Brush IndicatorBrush {
get { return (Brush)GetValue(IndicatorBrushProperty); } get => (Brush)GetValue(IndicatorBrushProperty);
set { SetValue(IndicatorBrushProperty, value); } set => SetValue(IndicatorBrushProperty, value);
} }
//Background Brush Property //Background Brush Property
public static DependencyProperty BackgroundBrushProperty = DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(HalfRoundProgressBar)); public static readonly DependencyProperty BackgroundBrushProperty = DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(HalfRoundProgressBar));
public Brush BackgroundBrush { public Brush BackgroundBrush {
get { return (Brush)GetValue(BackgroundBrushProperty); } get => (Brush)GetValue(BackgroundBrushProperty);
set { SetValue(BackgroundBrushProperty, value); } set => SetValue(BackgroundBrushProperty, value);
} }
//ProgressBorder Property //ProgressBorder Property
public static DependencyProperty ProgressBorderBrushProperty = DependencyProperty.Register("ProgressBorderBrush", typeof(Brush), typeof(HalfRoundProgressBar)); public static readonly DependencyProperty ProgressBorderBrushProperty = DependencyProperty.Register("ProgressBorderBrush", typeof(Brush), typeof(HalfRoundProgressBar));
public Brush ProgressBorderBrush { public Brush ProgressBorderBrush {
get { return (Brush)GetValue(ProgressBorderBrushProperty); } get => (Brush)GetValue(ProgressBorderBrushProperty);
set { SetValue(ProgressBorderBrushProperty, value); } set => SetValue(ProgressBorderBrushProperty, value);
} }
//Value //Value
public static DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(HalfRoundProgressBar)); public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(HalfRoundProgressBar));
public int Value { public int Value {
get { return (int)GetValue(ValueProperty); } get => (int)GetValue(ValueProperty);
set { SetValue(ValueProperty, value); } set => SetValue(ValueProperty, value);
} }
public HalfRoundProgressBar() { public HalfRoundProgressBar() {

View File

@@ -10,33 +10,33 @@
<Grid DataContext="{Binding RelativeSource={RelativeSource Self}}"> <Grid DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Path Stroke="Transparent" StrokeThickness=".5" RenderTransformOrigin=".5,.5" Width="60" Height="60"> <Path Stroke="Transparent" StrokeThickness=".5" RenderTransformOrigin=".5,.5" Width="60" Height="60">
<Path.Effect> <Path.Effect>
<DropShadowEffect BlurRadius="5" ShadowDepth="0" Opacity="1" Color="#B388FF"/> <DropShadowEffect BlurRadius="5" ShadowDepth="0" Opacity="1" Color="#B388FF" />
</Path.Effect> </Path.Effect>
<Path.Data> <Path.Data>
<CombinedGeometry GeometryCombineMode="Xor"> <CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1> <CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="30" RadiusY="30" Center="30,30"/> <EllipseGeometry RadiusX="30" RadiusY="30" Center="30,30" />
</CombinedGeometry.Geometry1> </CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2> <CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="24" RadiusY="24" Center="30,30"/> <EllipseGeometry RadiusX="24" RadiusY="24" Center="30,30" />
</CombinedGeometry.Geometry2> </CombinedGeometry.Geometry2>
</CombinedGeometry> </CombinedGeometry>
</Path.Data> </Path.Data>
<Path.Fill> <Path.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#B388FF" Offset="0"/> <GradientStop Color="#B388FF" Offset="0" />
<GradientStop Color="#A7FFEB" Offset="1"/> <GradientStop Color="#A7FFEB" Offset="1" />
</LinearGradientBrush> </LinearGradientBrush>
</Path.Fill> </Path.Fill>
<Path.RenderTransform> <Path.RenderTransform>
<RotateTransform/> <RotateTransform />
<!--This is necessary for the animation not to stop--> <!--This is necessary for the animation not to stop-->
</Path.RenderTransform> </Path.RenderTransform>
<Path.Triggers> <Path.Triggers>
<EventTrigger RoutedEvent="Loaded"> <EventTrigger RoutedEvent="Loaded">
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:.8" RepeatBehavior="Forever"/> <DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:.8" RepeatBehavior="Forever" />
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</EventTrigger> </EventTrigger>

View File

@@ -12,10 +12,12 @@ using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace Server_Dashboard.Controls { namespace Server_Dashboard.Controls {
/// <summary> /// <summary>
/// Interaction logic for LoadingIndicator.xaml /// Interaction logic for LoadingIndicator.xaml
/// </summary> /// </summary>
public partial class LoadingIndicator : UserControl { public partial class LoadingIndicator : UserControl {
public LoadingIndicator() { public LoadingIndicator() {
InitializeComponent(); InitializeComponent();
} }

View File

@@ -7,165 +7,264 @@
xmlns:halfroundprogressbar="clr-namespace:Server_Dashboard.Controls.HalfRoundProgressBar" xmlns:halfroundprogressbar="clr-namespace:Server_Dashboard.Controls.HalfRoundProgressBar"
xmlns:doubleroundprogressbar="clr-namespace:Server_Dashboard.Controls.DoubleRoundProgressBar" mc:Ignorable="d"> xmlns:doubleroundprogressbar="clr-namespace:Server_Dashboard.Controls.DoubleRoundProgressBar" mc:Ignorable="d">
<!--Module--> <!--Module-->
<Border Background="{StaticResource BackgroundSurface_02dp}" MinHeight="100" MinWidth="300" Width="Auto" Height="Auto" Margin="10" CornerRadius="5"> <Button Cursor="Hand">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Border" Background="{StaticResource BackgroundSurface_02dp}" BorderThickness="2" MinHeight="300" MinWidth="400" Width="Auto" Height="Auto" Margin="10" CornerRadius="5">
<Border.Effect> <Border.Effect>
<DropShadowEffect BlurRadius="5" ShadowDepth="0"/> <DropShadowEffect BlurRadius="5" ShadowDepth="0" />
</Border.Effect> </Border.Effect>
<Border x:Name="BorderBackground" Background="{StaticResource BackgroundSurface_02dp}" CornerRadius="5">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="40"/> <RowDefinition Height="40" />
<RowDefinition Height="*"/> <RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--Top Bar--> <!--Top Bar-->
<Border CornerRadius="5 5 0 0" Grid.Row="0" Background="{StaticResource BackgroundSurface_08dp}" > <Border CornerRadius="4 4 0 0" Grid.Row="0" Background="{StaticResource BackgroundSurface_08dp}">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Grid.Column="0" Margin="7.5 0 7.5 0" Height="25" Width="25" Source="{Binding ModuleIcon}"/> <Image Grid.Column="0" Margin="7.5 0 7.5 0" Height="25" Width="25" Source="{Binding ModuleIcon}" />
<TextBlock Foreground="{StaticResource DeepPurple_A100}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding ModulName}"/> <TextBlock Foreground="{StaticResource DeepPurple_A100}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding ModuleName}" />
<Border CornerRadius="0 5 0 0" Background="{Binding StatusIndicator}" Grid.Column="3"> <Border CornerRadius="0 5 0 0" Background="{Binding StatusIndicator}" Grid.Column="3">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition />
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Margin="7 0 30 0" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Column="0" FontSize="24" Text="Status"> <TextBlock Margin="7 0 30 0" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Column="0" FontSize="24" Text="Status">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87"/> <SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<Border CornerRadius="0 5 0 0" Grid.Column="1" HorizontalAlignment="Right" Background="{Binding StatusIndicatorBG}" Padding="6"> <Border CornerRadius="0 4 0 0" Grid.Column="1" HorizontalAlignment="Right" Background="{Binding StatusIndicatorBG}" Padding="6">
<Ellipse Fill="{Binding StatusIndicator}" StrokeThickness="0" Width="25" Height="25"/> <Ellipse Fill="{Binding StatusIndicator}" StrokeThickness="0" Width="25" Height="25" />
</Border> </Border>
</Grid> </Grid>
</Border> </Border>
</Grid> </Grid>
</Border> </Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Server" FontSize="20" Margin="10 5 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
<TextBlock Grid.Column="1" Text="{Binding ServerInformation.ServerName}" FontSize="20" Margin="10 5 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
<!--Main Content--> <!--Main Content-->
<Grid Grid.Row="2" Margin="20" Width="Auto"> <Grid Grid.Row="2" Margin="20" Width="Auto">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1.5*"/> <ColumnDefinition Width="1.5*" />
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!--Information pannel, left--> <!--Information panel, left-->
<Grid Grid.Row="1" Margin="0 0 25 0"> <Grid Margin="0 0 25 0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock Text="Servername" FontSize="16" Margin="2 2 5 10"> <Border BorderThickness="0 0 0 1" Padding="0 0 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="User" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="User" FontSize="16" Margin="2 2 5 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="Public IP" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="Public IP" FontSize="16" Margin="2 2 5 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="Private IP" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="Private IP" FontSize="16" Margin="2 2 5 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="Uptime" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="Uptime" FontSize="16" Margin="2 2 5 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="Creation Date" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="Creation Date" FontSize="16" Margin="2 2 5 10"> </Border>
<Border BorderThickness="0 1 0 0" Padding="0 5 0 0">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="Creator" FontSize="16">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="Creator" FontSize="16" Margin="2 2 5 10">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/>
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Border>
</StackPanel> </StackPanel>
<StackPanel Grid.Column="1"> <StackPanel Grid.Column="1">
<TextBlock Text="{Binding ServerInfo.ServerName}" FontSize="16" Margin="5 2 2 10"> <Border BorderThickness="0 0 0 1" Padding="0 0 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding ServerInformation.OsUserName}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="{Binding ServerInfo.OSUserName}" FontSize="16" Margin="5 2 2 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding ServerInformation.PublicIpAddress}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="{Binding ServerInfo.PublicIpAdress}" FontSize="16" Margin="5 2 2 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding ServerInformation.PrivateIpAddress}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="{Binding ServerInfo.PrivateIpAdress}" FontSize="16" Margin="5 2 2 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding ServerInformation.Uptime}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="{Binding ServerInfo.Uptime}" FontSize="16" Margin="5 2 2 10"> </Border>
<Border BorderThickness="0 1 0 1" Padding="0 5 0 5">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding CreationDate}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="{Binding CreationDate}" FontSize="16" Margin="5 2 2 10"> </Border>
<Border BorderThickness="0 1 0 0" Padding="0 5 0 0">
<Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush>
<TextBlock Text="{Binding Creator}" FontSize="16" Padding="15 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/> <SolidColorBrush Color="White" Opacity="0.60" />
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="{Binding Creator}" FontSize="16" Margin="5 2 2 10">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.60"/>
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Border>
</StackPanel> </StackPanel>
</Grid> </Grid>
<!--Graphical Indicators Right--> <!--Graphical Indicators Right-->
<Grid Grid.Row="1" Grid.Column="1"> <Grid Grid.Column="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition />
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid Grid.Column="0"> <Grid Grid.Column="0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition/> <RowDefinition />
<RowDefinition/> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<halfroundprogressbar:HalfRoundProgressBar Margin="5" Grid.Row="0" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" Value="{Binding ServerInfo.CpuUsage}" IndicatorBrush="{StaticResource Teal_A100}"/> <halfroundprogressbar:HalfRoundProgressBar Margin="5" Grid.Row="0" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" Value="{Binding ServerInfo.CpuUsage}" IndicatorBrush="{StaticResource Teal_A100}" />
<TextBlock Foreground="{StaticResource Teal_A100}" Grid.Row="0" Text="CPU" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18"/> <TextBlock Foreground="{StaticResource Teal_A100}" Grid.Row="0" Text="CPU" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" />
<halfroundprogressbar:HalfRoundProgressBar Margin="5" Grid.Row="1" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" Value="{Binding ServerInfo.GpuUsage}" IndicatorBrush="{StaticResource Teal_A100}"/> <halfroundprogressbar:HalfRoundProgressBar Margin="5" Grid.Row="1" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" Value="{Binding ServerInfo.GpuUsage}" IndicatorBrush="{StaticResource Teal_A100}" />
<TextBlock Foreground="{StaticResource Teal_A100}" Grid.Row="1" Text="GPU" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18"/> <TextBlock Foreground="{StaticResource Teal_A100}" Grid.Row="1" Text="GPU" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition/> <RowDefinition />
<RowDefinition/> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<doubleroundprogressbar:DoubleRoundProgressBar ValueRead="70" ValueWrite="60" ReadIndicatorBrush="{StaticResource DeepPurple_A100}" WriteIndicatorBrush="{StaticResource Teal_A100}" Margin="5" Grid.Row="0" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100"/> <doubleroundprogressbar:DoubleRoundProgressBar ValueRead="70" ValueWrite="60" ReadIndicatorBrush="{StaticResource DeepPurple_A100}" WriteIndicatorBrush="{StaticResource Teal_A100}" Margin="5" Grid.Row="0" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" />
<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center"> <StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="Read" Foreground="{StaticResource DeepPurple_A100}"/> <TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="Read" Foreground="{StaticResource DeepPurple_A100}" />
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="Write" Foreground="{StaticResource Teal_A100}"/> <TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="Write" Foreground="{StaticResource Teal_A100}" />
</StackPanel> </StackPanel>
<doubleroundprogressbar:DoubleRoundProgressBar ValueRead="70" ValueWrite="60" ReadIndicatorBrush="{StaticResource DeepPurple_A100}" WriteIndicatorBrush="{StaticResource Teal_A100}" Margin="5" Grid.Row="1" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100"/> <doubleroundprogressbar:DoubleRoundProgressBar ValueRead="70" ValueWrite="60" ReadIndicatorBrush="{StaticResource DeepPurple_A100}" WriteIndicatorBrush="{StaticResource Teal_A100}" Margin="5" Grid.Row="1" ProgressBorderBrush="{StaticResource BackgroundSurface_02dp}" BackgroundBrush="{StaticResource BackgroundSurface_08dp}" Height="100" Width="100" />
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center"> <StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="UP" Foreground="{StaticResource DeepPurple_A100}"/> <TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="UP" Foreground="{StaticResource DeepPurple_A100}" />
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="DOWN" Foreground="{StaticResource Teal_A100}"/> <TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" TextAlignment="Center" Text="DOWN" Foreground="{StaticResource Teal_A100}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
</Border> </Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".37" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsFocused" Value="True">
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</UserControl> </UserControl>

View File

@@ -12,10 +12,12 @@ using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace Server_Dashboard.Controls.ServerModules { namespace Server_Dashboard.Controls.ServerModules {
/// <summary> /// <summary>
/// Interaktionslogik für ServerModule.xaml /// Interaktionslogik für ServerModule.xaml
/// </summary> /// </summary>
public partial class ServerModule : UserControl { public partial class ServerModule : UserControl {
public ServerModule() { public ServerModule() {
InitializeComponent(); InitializeComponent();
} }

View File

@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard.DashboardModules {
/// <summary>
/// The Information the user puts into the CreateNewModule form
/// </summary>
class NewModuleInformation {
//The Name of the Module
public string ModuleName { get; set; }
//The Name of the Server
public string ServerName { get; set; }
//The Username
public string Username { get; set; }
//IPv4 Adress
public string IPAdress { get; set; }
//Port, defaults to 22
public int Port { get; set; }
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// Server information class, this will probably scale pretty big later on
/// This will hold all the information the socket will gather
/// </summary>
class ServerInformation {
//The ServerName
public string ServerName { get; set; }
//The unix or windows username
public string OSUserName { get; set; }
//Cpu Temp in C
public string CpuTemp { get; set; }
//Gpu Temp in C
public string GpuTemp { get; set; }
//Server uptime
public string Uptime { get; set; }
//When the server was first deployed
public string DeployDate { get; set; }
//Public IPv4 Adress
public string PublicIpAdress { get; set; }
//Private IP adress from the servers network
public string PrivateIpAdress { get; set; }
//GPU usage in %
public string GpuUsage { get; set; }
//CPU usage in %
public string CpuUsage { get; set; }
}
}

View File

@@ -1,17 +1,17 @@
using Microsoft.Win32; using System;
using System;
using System.Collections.Generic;
using System.Configuration; using System.Configuration;
using System.Data; using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Reflection;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Database class to access the database /// Database class to access the database
/// </summary> /// </summary>
public static class DatabaseHandler { public static class DatabaseHandler {
#region Public Methods #region Public Methods
/// <summary> /// <summary>
/// Checks the user credentials /// Checks the user credentials
/// </summary> /// </summary>
@@ -20,25 +20,25 @@ namespace Server_Dashboard {
/// <returns>[0] is false, [1] is true, [2] connection error</returns> /// <returns>[0] is false, [1] is true, [2] connection error</returns>
public static int CheckLogin(string uname, string passwd) { public static int CheckLogin(string uname, string passwd) {
//Creates the database connection //Creates the database connection
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try { try {
//Open the connection //Open the connection
con.Open(); con.Open();
//SQL Query //SQL Query
string query = "EXEC ValidateUserLogin @Username = @uname, @Password = @passwd, @Valid = @valid OUTPUT"; string query = "EXEC ValidateUserLogin @Username = @uname, @Password = @passwd, @Valid = @valid OUTPUT";
//Creates a new command //Creates a new command
using (SqlCommand com = new SqlCommand(query, con)) { using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function
//For security reasons the values are added with this function
//this will avoid SQL Injections //this will avoid SQL Injections
com.Parameters.AddWithValue("@uname", uname); com.Parameters.AddWithValue("@uname", uname);
com.Parameters.AddWithValue("@passwd", passwd); com.Parameters.AddWithValue("@passwd", passwd);
com.Parameters.Add("@valid", SqlDbType.NVarChar, 250); com.Parameters.Add("@valid", SqlDbType.NVarChar, 250);
com.Parameters["@valid"].Direction = ParameterDirection.Output; com.Parameters["@valid"].Direction = ParameterDirection.Output;
//Execute without a return value //Execute query and return number of rows affected
com.ExecuteNonQuery(); com.ExecuteNonQuery();
//The Return value from the SQL Stored Procedure will have the answer to life //Checks if there are any rows successful
return Convert.ToInt32(com.Parameters["@Valid"].Value); //If the query returns 0 the query wasn't successful
} //if its any number above 0 it was successful
return Convert.ToInt32(com.Parameters["@Valid"].Value) == 0 ? 1 : 0;
//Catch any error //Catch any error
} catch (SqlException ex) { } catch (SqlException ex) {
return ex.Number; return ex.Number;
@@ -47,34 +47,174 @@ namespace Server_Dashboard {
con.Close(); con.Close();
} }
} }
public static DataTable GetUserData(string username) {
//Creates the database connection
using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try {
//Open the connection
con.Open();
//SQL Query
const string query = "SELECT ID, Username, Email, RegistrationDate FROM UserData WHERE Username = @username";
//Creates a new command
using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function
//this will avoid SQL Injections
com.Parameters.AddWithValue("@username", username);
//Execute query and return number of rows affected
DataTable resultTable = new DataTable() { TableName = "Userdata" };
using SqlDataAdapter sda = new SqlDataAdapter(com);
sda.Fill(resultTable);
return resultTable;
//Checks if there are any rows successful
//If the query returns 0 the query wasn't successful
//if its any number above 0 it was successful
//Catch any error
} catch (SqlException) {
return null;
} finally {
//Always close the connection
con.Close();
} }
}
public static DataTable GetUserModuleData(int uid) {
//Creates the database connection
using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try {
//Open the connection
con.Open();
//SQL Query
const string query = "SELECT Creator, CreationTime, ModuleName, MI.Image, ModuleData.ID FROM ModuleData LEFT JOIN ModuleIcon MI on ModuleData.ID = MI.Module WHERE UserID = @userID";
//Creates a new command
using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function
//this will avoid SQL Injections
com.Parameters.AddWithValue("@userID", uid);
//Execute query and return number of rows affected
DataTable resultTable = new DataTable();
using SqlDataAdapter sda = new SqlDataAdapter(com);
sda.Fill(resultTable);
return resultTable;
//Checks if there are any rows successful
//If the query returns 0 the query wasn't successful
//if its any number above 0 it was successful
//Catch any error
} catch (SqlException) {
return null;
} finally {
//Always close the connection
con.Close();
}
}
/// <summary> /// <summary>
/// Currently obscolete, would check the Username and Cookie /// This function will fetch every server data for each module
/// This will need some optimization, for now we just asynchronously
/// fetch the server data for each module
/// </summary>
/// <param name="mid">ModuleID to fetch the data from</param>
/// <returns></returns>
public static DataTable GetServerData(int mid) {
//Creates the database connection
using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try {
//Open the connection
con.Open();
//SQL Query
const string query = "SELECT * FROM ServerData WHERE ModuleID = @mid";
//Creates a new command
using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function
//this will avoid SQL Injections
com.Parameters.AddWithValue("@mid", mid);
//Execute query and return number of rows affected
DataTable resultTable = new DataTable();
using SqlDataAdapter sda = new SqlDataAdapter(com);
sda.Fill(resultTable);
return resultTable;
//Checks if there are any rows successful
//If the query returns 0 the query wasn't successful
//if its any number above 0 it was successful
//Catch any error
} catch (SqlException) {
return null;
} finally {
//Always close the connection
con.Close();
}
}
/// <summary>
/// Creates a new Module for the current user
/// </summary>
/// <param name="ipAddress">Server IP Address</param>
/// <param name="moduleName">Module name, default is Module</param>
/// <param name="serverName">Server name, default is Server</param>
/// <param name="username">Username of the current user</param>
/// <param name="moduleIcon">module icon as byte[]</param>
/// <param name="port">port, default ist 22</param>
/// <returns></returns>
public static int CreateNewModule(string ipAddress, string moduleName, string serverName, string username, byte[] moduleIcon, string port = "22") {
//Creates the database connection
using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try {
//Open the connection
con.Open();
//SQL Query
const string query = "EXEC AddNewModuleToUser @UserName = @username, @DateTime = @time, @ModuleName = @moduleName, @ServerName = @serverName, @ModuleIcon = @moduleIcon, @IPAddress = @ipAddress, @Port = @port";
//Creates a new command
using SqlCommand com = new SqlCommand(query, con);
//For security reasons the values are added with this function
//this will avoid SQL Injections
com.Parameters.AddWithValue("@username", username);
com.Parameters.AddWithValue("@time", DateTime.Now);
com.Parameters.AddWithValue("@moduleName", moduleName);
com.Parameters.AddWithValue("@serverName", serverName);
com.Parameters.Add("@moduleIcon", SqlDbType.VarBinary, -1).Value = moduleIcon;
if (moduleIcon == null)
com.Parameters["@moduleIcon"].Value = DBNull.Value;
//com.Parameters.AddWithValue("@moduleIcon", moduleIcon);
com.Parameters.AddWithValue("@ipAddress", ipAddress);
com.Parameters.AddWithValue("@port", port);
//Execute query and return number of rows affected
int sqlResponse = com.ExecuteNonQuery();
//Checks if there are any rows successful
//If the query returns 0 the query wasn't successful
//if its any number above 0 it was successful
return sqlResponse == 0 ? 1 : 0;
//Catch any error
} catch (SqlException ex) {
return ex.Number;
} finally {
//Always close the connection
con.Close();
}
}
/// <summary>
/// Currently obsolete, would check the Username and Cookie
/// </summary> /// </summary>
/// <param name="cookie">Locally stored user cookie</param> /// <param name="cookie">Locally stored user cookie</param>
/// <param name="username">Locally stored username</param> /// <param name="username">Locally stored username</param>
/// <returns>[0] is false, [1] is true, [2] connection error</returns> /// <returns>[0] is false, [1] is true, [2] connection error</returns>
public static int CheckCookie(string cookie, string username) { public static int CheckCookie(string cookie, string username) {
//Creates the database connection //Creates the database connection
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try { try {
//Open the connection //Open the connection
con.Open(); con.Open();
//SQL Query //SQL Query
string query = "EXEC CheckUserCookie @Cookie = @cookie, @UserName = @username, @Valid = @valid OUTPUT"; const string query = "((SELECT Cookie FROM UserData WHERE Username = @username) = @cookie)";
//Creates a new command //Creates a new command
using (SqlCommand com = new SqlCommand(query, con)) { using SqlCommand com = new SqlCommand(query, con);
//For security reasons the values are added with this function //For security reasons the values are added with this function
//this will avoid SQL Injections //this will avoid SQL Injections
com.Parameters.AddWithValue("@cookie", cookie); com.Parameters.AddWithValue("@cookie", cookie);
com.Parameters.AddWithValue("@username", username); com.Parameters.AddWithValue("@username", username);
com.Parameters.Add("@valid", SqlDbType.Bit); //Execute query and return number of rows affected
com.Parameters["@valid"].Direction = ParameterDirection.Output; int sqlResponse = com.ExecuteNonQuery();
//Execute without a return value //Checks if there are any rows successful
com.ExecuteNonQuery(); //If the query returns 0 the query wasn't successful
//The Return value from the SQL Stored Procedure will have the answer to life //if its any number above 0 it was successfull
return Convert.ToInt32(com.Parameters["@Valid"].Value); return sqlResponse == 0 ? 1 : 0;
}
//Catch any error //Catch any error
} catch (SqlException ex) { } catch (SqlException ex) {
return ex.Number; return ex.Number;
@@ -83,73 +223,81 @@ namespace Server_Dashboard {
con.Close(); con.Close();
} }
} }
}
/// <summary> /// <summary>
/// Deletes a the cookie from the given user /// Deletes a the cookie from the given user
/// </summary> /// </summary>
/// <param name="username">User who doesnt deserve any delicious cookies :3</param> /// <param name="username">User who doesnt deserve any delicious cookies :3</param>
public static void DeleteCookie(string username) { public static int DeleteCookie(string username) {
//Creates the database connection //Creates the database connection
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try { try {
//Open the connection //Open the connection
con.Open(); con.Open();
//SQL Query //SQL Query
string query = "EXEC DeleteUserCookie @Username = @username, @ResponseMessage = @response OUTPUT"; const string query = "UPDATE UserData SET Cookie = null WHERE Username = @username";
//Creates a new command //Creates a new command
using (SqlCommand com = new SqlCommand(query, con)) { using SqlCommand com = new SqlCommand(query, con);
//For security reasons the values are added with this function //For security reasons the values are added with this function
//this will avoid SQL Injections //this will avoid SQL Injections
com.Parameters.AddWithValue("@username", username); com.Parameters.AddWithValue("@username", username);
com.Parameters.Add("@response", SqlDbType.NVarChar, 250); //Execute query and return number of rows affected
com.Parameters["@response"].Direction = ParameterDirection.Output; int sqlResponse = com.ExecuteNonQuery();
//Execute without a return value //Checks if there are any rows successful
com.ExecuteNonQuery(); //If the query returns 0 the query wasn't successful
} //if its any number above 0 it was successful
//Catch any error, dont return them, why would you? return sqlResponse == 0 ? 1 : 0;
} catch { //Catch any error
} catch (SqlException ex) {
return ex.Number;
} finally { } finally {
//Always close the connection //Always close the connection
con.Close(); con.Close();
} }
} }
}
/// <summary> /// <summary>
/// Adds a new Cookie to a user /// Adds a new Cookie to a user
/// </summary> /// </summary>
/// <param name="cookie">The delicious locally stored cookie</param> /// <param name="cookie">The delicious locally stored cookie</param>
/// <param name="username">The User who deserves a cookie :3</param> /// <param name="username">The User who deserves a cookie :3</param>
/// <returns>[0] is false, [1] is true, [2] connection error</returns> /// <returns>[0] is false, [1] is true, [2] connection error</returns>
public static int AddCookie(string cookie, string username) { public static int AddCookie(string username, string cookie) {
//Creates the database connection //Creates the database connection
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { using SqlConnection con =
new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString);
try { try {
//Open the connection //Open the connection
con.Open(); con.Open();
//SQL Query //SQL Query
string query = "EXEC AddCookieToUser @Cookie = @cookie, @UserName = @username, @ResponseMessage = @response OUTPUT"; const string query = "UPDATE UserData SET Cookie = @cookie WHERE Username = @username";
//Creates a new command //Creates a new command
using (SqlCommand com = new SqlCommand(query, con)) { using SqlCommand com = new SqlCommand(query, con);
//For security reasons the values are added with this function //For security reasons the values are added with this function
//this will avoid SQL Injections //this will avoid SQL Injections
com.Parameters.AddWithValue("@cookie", cookie); com.Parameters.Add("@cookie", SqlDbType.NVarChar, -1).Value = cookie;
com.Parameters.AddWithValue("@username", username); com.Parameters.AddWithValue("@username", username);
com.Parameters.Add("@response", SqlDbType.NVarChar, 250);
com.Parameters["@response"].Direction = ParameterDirection.Output; //Execute query and return number of rows affected
//Execute without a return value int sqlResponse = com.ExecuteNonQuery();
com.ExecuteNonQuery();
//The Return value from the SQL Stored Procedure will have the answer to life //Checks if there are any rows successful
return Convert.ToInt32(com.Parameters["@ResponseMessage"].Value); //If the query returns 0 the query wasn't successful
} //if its any number above 0 it was successful
return sqlResponse == 0 ? 1 : 0;
//Catch any error //Catch any error
} catch (SqlException ex) { } catch (SqlException ex) {
return ex.Number; return ex.Number;
} finally { } finally {
//Always close connection //Always close the connection
con.Close(); con.Close();
} }
} }
}
#endregion #endregion Public Methods
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Security;
using System.Text; using System.Text;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Interface that makes a SecurePassword go one way /// Interface that makes a SecurePassword go one way
/// </summary> /// </summary>

View File

@@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Text; using System.Text;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Interface to help close a window with a button /// Interface to help close a window with a button
/// </summary> /// </summary>
interface IWindowHelper { internal interface IWindowHelper {
Action Close { get; set; } Action Close { get; set; }
} }
} }

View File

@@ -6,89 +6,99 @@
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:Server_Dashboard" xmlns:local="clr-namespace:Server_Dashboard"
xmlns:loading="clr-namespace:Server_Dashboard.Controls" xmlns:loading="clr-namespace:Server_Dashboard.Controls"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
x:Name="Login" x:Name="Login"
mc:Ignorable="d" mc:Ignorable="d"
Title="Server Dashboard" Title="Server Dashboard"
Height="700" Width="500" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" local:CloseProperty.Value="True"> Height="700" Width="500" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" local:CloseProperty.Value="True">
<WindowChrome.WindowChrome> <WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0"/> <WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
</WindowChrome.WindowChrome> </WindowChrome.WindowChrome>
<Window.DataContext> <Window.DataContext>
<local:LoginViewModel/> <local:LoginViewModel />
</Window.DataContext> </Window.DataContext>
<!--#region Login forms main container--> <!--#region Login forms main container-->
<Border Background="{StaticResource BackgroundSurface_00dp}"> <Border Background="{StaticResource BackgroundSurface_00dp}">
<Grid Grid.Row="0"> <Grid Grid.Row="0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="30"/> <RowDefinition Height="30" />
<RowDefinition Height="*"/> <RowDefinition Height="*" />
<RowDefinition Height="70"/> <RowDefinition Height="70" />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
<RowDefinition Height="30"/> <RowDefinition Height="30" />
<RowDefinition Height="30"/> <RowDefinition Height="30" />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
<RowDefinition Height=".3*"/> <RowDefinition Height=".3*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<!--#region Custom title bar--> <!--#region Custom title bar-->
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="0" Grid.ColumnSpan="2"> <Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="0" Grid.ColumnSpan="2">
<Grid.Effect> <Grid.Effect>
<DropShadowEffect Direction="270" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="270" ShadowDepth="0" BlurRadius="5" />
</Grid.Effect> </Grid.Effect>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" />
<ColumnDefinition Width="40"/> <ColumnDefinition Width="40" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Grid.Column="0"/> <TextBlock Grid.Column="0" Text="Login" Margin="5 0 0 0" VerticalAlignment="Center">
<Button Style="{StaticResource CloseButton}" Grid.Column="2" Content="✕"> <i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<Button Style="{StaticResource CloseButton}" Grid.Column="1" Content="✕">
<i:Interaction.Triggers> <i:Interaction.Triggers>
<i:EventTrigger EventName="Click"> <i:EventTrigger EventName="Click">
<i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/> <i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
</Button> </Button>
</Grid> </Grid>
<!--#endregion--> <!--#endregion-->
<!--#region Greeting text--> <!--#region Greeting text-->
<Border Height="100" BorderBrush="{StaticResource DeepPurple_400}" BorderThickness="0 2 0 2" Background="{StaticResource BackgroundSurface_00dp}" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Grid.ColumnSpan="2" Margin="0 0 0 10"> <Border Height="100" BorderBrush="{StaticResource DeepPurple_A100}" BorderThickness="0 2 0 2" Background="{StaticResource BackgroundSurface_00dp}" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Grid.ColumnSpan="2" Margin="0 0 0 10">
<StackPanel VerticalAlignment="Center" Margin="0 0 0 5" > <StackPanel VerticalAlignment="Center" Margin="0 0 0 5">
<TextBlock Text="Server Dashboard" FontSize="30" HorizontalAlignment="Center"> <TextBlock Text="Server Dashboard" FontSize="30" HorizontalAlignment="Center">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Text="Login" FontSize="30" HorizontalAlignment="Center"> <TextBlock Text="Login" FontSize="30" HorizontalAlignment="Center">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
</Border> </Border>
<UserControl Grid.Row="2" Visibility="{Binding Loading}"> <UserControl Grid.Row="2" Visibility="{Binding Loading}">
<loading:LoadingIndicator/> <loading:LoadingIndicator />
</UserControl> </UserControl>
<!--#endregion--> <!--#endregion-->
<!--#region Username form--> <!--#region Username form-->
<Border CornerRadius="4" Margin="0 10 0 10" Width="350" Height="60" Background="{StaticResource BackgroundSurface_01dp}" Grid.Row="3" Grid.ColumnSpan="2"> <Border CornerRadius="4" Margin="0 10 0 10" Width="350" Height="60" Background="{StaticResource BackgroundSurface_01dp}" Grid.Row="3" Grid.ColumnSpan="2">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/> <ColumnDefinition Width="60" />
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Grid.Column="0" Height="30" Source="Assets/Images/userlogin.png"/> <Viewbox Grid.Column="0" Width="30" Height="30">
<TextBox Text="{Binding Username}" x:Name="UserName" Grid.Column="1" Margin="0 0 5 0"/> <Canvas Width="24" Height="24">
<Path Data="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.38" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBox Text="{Binding Username}" x:Name="UserName" Grid.Column="1" Margin="0 0 5 0" />
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="Username" Visibility="{Binding ElementName=UserName, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False"> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="Username" Visibility="{Binding ElementName=UserName, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Grid> </Grid>
@@ -97,49 +107,57 @@
<!--#region Password form--> <!--#region Password form-->
<Border Margin="0 10 0 10" Background="{StaticResource BackgroundSurface_01dp}" Grid.Row="4" Grid.ColumnSpan="2" Width="350" CornerRadius="4" Padding="0 0 5 0"> <Border Margin="0 10 0 10" Background="{StaticResource BackgroundSurface_01dp}" Grid.Row="4" Grid.ColumnSpan="2" Width="350" CornerRadius="4" Padding="0 0 5 0">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/> <ColumnDefinition Width="60" />
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Grid.Column="0" Height="30" Source="Assets/Images/userpasswd.png"/> <Viewbox Grid.Column="0" Width="30" Height="30">
<Canvas Width="24" Height="24">
<Path Data="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.38" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<PasswordBox Width="290" Height="60" local:MonitorPasswordProperty.Value="True" Grid.Column="1" x:Name="Password"> <PasswordBox Width="290" Height="60" local:MonitorPasswordProperty.Value="True" Grid.Column="1" x:Name="Password">
<PasswordBox.InputBindings> <PasswordBox.InputBindings>
<KeyBinding Key="Return" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}"/> <KeyBinding Key="Return" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}" />
</PasswordBox.InputBindings> </PasswordBox.InputBindings>
</PasswordBox> </PasswordBox>
<TextBlock Visibility="{Binding ElementName=Password, Path=(local:HasTextProperty.Value), Converter={StaticResource UserNameVisibillity}}" x:Name="PasswordHint" Text="Password" Grid.Column="1" IsHitTestVisible="False" VerticalAlignment="Center" HorizontalAlignment="Left"> <TextBlock Visibility="{Binding ElementName=Password, Path=(local:HasTextProperty.Value), Converter={StaticResource UserNameVisibillity}}" x:Name="PasswordHint" Text="Password" Grid.Column="1" IsHitTestVisible="False" VerticalAlignment="Center" HorizontalAlignment="Left">
<TextBlock.InputBindings> <TextBlock.InputBindings>
<KeyBinding Key="Return" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}"/> <KeyBinding Key="Return" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}" />
</TextBlock.InputBindings> </TextBlock.InputBindings>
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Grid> </Grid>
</Border> </Border>
<!--#endregion--> <!--#endregion-->
<!--#region Login button--> <!--#region Login button-->
<Button Height="60" Width="350" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}" Grid.Row="5" Content="LOGIN" Grid.ColumnSpan="2"/> <Button Height="60" Width="350" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=Login}" Grid.Row="5" Content="LOGIN" Grid.ColumnSpan="2" />
<!--#endregion--> <!--#endregion-->
<!--#region Error text--> <!--#region Error text-->
<TextBlock Text="{Binding ErrorText}" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="6" Grid.Column="1" Foreground="{StaticResource ErrorRed}" FontSize="14"/> <TextBlock Text="{Binding ErrorText}" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="6" Grid.Column="1" Foreground="{StaticResource ErrorRed}" FontSize="14" />
<!--#endregion--> <!--#endregion-->
<!--#region Remember me and Password forgotten link--> <!--#region Remember me and Password forgotten link-->
<Grid Grid.Row="7"> <Grid Grid.Row="7">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<CheckBox IsChecked="{Binding RememberUser}" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="75 0 0 0"/> <CheckBox IsChecked="{Binding RememberUser}" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="75 0 0 0" />
<TextBlock Grid.Column="1" Text="Remember me?" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10 0 0 0"> <TextBlock Grid.Column="1" Text="Remember me?" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10 0 0 0">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<TextBlock Grid.Column="3" FontSize="14" Margin="0 0 75 0" VerticalAlignment="Center" HorizontalAlignment="Right"> <TextBlock Grid.Column="3" FontSize="14" Margin="0 0 75 0" VerticalAlignment="Center" HorizontalAlignment="Right">
@@ -148,7 +166,7 @@
Forgot password Forgot password
</Hyperlink> </Hyperlink>
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Grid> </Grid>
@@ -158,10 +176,10 @@
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="Don't have an account?" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Right"> <TextBlock Text="Don't have an account?" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Right">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.64"/> <SolidColorBrush Color="White" Opacity="0.64" />
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
<Button Command="{Binding RegisterCommand}" Content="REGISTER" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="12" Height="30" Width="80" Margin="10 0 0 0"/> <Button Command="{Binding RegisterCommand}" Content="REGISTER" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="12" Height="30" Width="80" Margin="10 0 0 0" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<!--#endregion--> <!--#endregion-->

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Server_Dashboard.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server_Dashboard.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
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">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</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.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:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -5,10 +5,12 @@ using System.Security;
using System.Text; using System.Text;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Secure string helper class to unsecure the Password b4 it goes to the database /// Secure string helper class to unsecure the Password b4 it goes to the database
/// </summary> /// </summary>
public static class SecureStringHelpers { public static class SecureStringHelpers {
//Unsecures a given password //Unsecures a given password
public static string Unsecure(this SecureString secureString) { public static string Unsecure(this SecureString secureString) {
//If empty return nothing //If empty return nothing

View File

@@ -18,23 +18,6 @@
<None Remove="Assets\Fonts\OpenSans\OpenSans-Regular.ttf" /> <None Remove="Assets\Fonts\OpenSans\OpenSans-Regular.ttf" />
<None Remove="Assets\Fonts\OpenSans\OpenSans-SemiBold.ttf" /> <None Remove="Assets\Fonts\OpenSans\OpenSans-SemiBold.ttf" />
<None Remove="Assets\Fonts\OpenSans\OpenSans-SemiBoldItalic.ttf" /> <None Remove="Assets\Fonts\OpenSans\OpenSans-SemiBoldItalic.ttf" />
<None Remove="Assets\Images\Docs.png" />
<None Remove="Assets\Images\Docs.svg" />
<None Remove="Assets\Images\DocsLight.png" />
<None Remove="Assets\Images\GitHub-Mark.zip" />
<None Remove="Assets\Images\GitHub.png" />
<None Remove="Assets\Images\GitHubLight.png" />
<None Remove="Assets\Images\GreenSettings.png" />
<None Remove="Assets\Images\PlaceHolderModule.png" />
<None Remove="Assets\Images\PlaceHolderModuleLight.png" />
<None Remove="Assets\Images\Settings.png" />
<None Remove="Assets\Images\Settings.svg" />
<None Remove="Assets\Images\SettingsLight.png" />
<None Remove="Assets\Images\User.png" />
<None Remove="Assets\Images\User.svg" />
<None Remove="Assets\Images\UserLight.png" />
<None Remove="Assets\Images\userlogin.png" />
<None Remove="Assets\Images\userpasswd.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -65,23 +48,17 @@
<Resource Include="Assets\Fonts\OpenSans\OpenSans-Regular.ttf" /> <Resource Include="Assets\Fonts\OpenSans\OpenSans-Regular.ttf" />
<Resource Include="Assets\Fonts\OpenSans\OpenSans-SemiBold.ttf" /> <Resource Include="Assets\Fonts\OpenSans\OpenSans-SemiBold.ttf" />
<Resource Include="Assets\Fonts\OpenSans\OpenSans-SemiBoldItalic.ttf" /> <Resource Include="Assets\Fonts\OpenSans\OpenSans-SemiBoldItalic.ttf" />
<Resource Include="Assets\Images\Docs.png" />
<Resource Include="Assets\Images\Docs.svg" />
<Resource Include="Assets\Images\DocsLight.png" />
<Resource Include="Assets\Images\GitHub.png" />
<Resource Include="Assets\Images\GitHubLight.png" />
<Resource Include="Assets\Images\PlaceHolderModule.png" />
<Resource Include="Assets\Images\PlaceHolderModuleLight.png" />
<Resource Include="Assets\Images\Settings.svg" />
<Resource Include="Assets\Images\User.svg" />
<Resource Include="Assets\Images\userlogin.png" />
<Resource Include="Assets\Images\userpasswd.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml.cs"> <Compile Update="Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs"> <Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -89,6 +66,13 @@
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Properties\Settings.settings"> <None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Daemon/ConfigureAwaitAnalysisMode/@EntryValue">UI</s:String></wpf:ResourceDictionary>

View File

@@ -18,10 +18,16 @@
<Compile Update="Controls\ServerModules\ServerModule.xaml.cs"> <Compile Update="Controls\ServerModules\ServerModule.xaml.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Update="Views\DashboardPages\MainDashboardPage.xaml.cs"> <Compile Update="Views\Dashboard\AnalyticsPage.xaml.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Update="Controls\Dashboard\CRUD Popup\CreateModulePopup.xaml.cs"> <Compile Update="Views\Dashboard\SettingsPage.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Pages\MainDashboardPage.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Dashboard\CRUD Popup\CreateModulePopup.xaml.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Update="Views\DashboardWindow.xaml.cs"> <Compile Update="Views\DashboardWindow.xaml.cs">
@@ -44,10 +50,16 @@
<Page Update="LoginWindow.xaml"> <Page Update="LoginWindow.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Views\DashboardPages\MainDashboardPage.xaml"> <Page Update="Views\Dashboard\AnalyticsPage.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Controls\Dashboard\CRUD Popup\CreateModulePopup.xaml"> <Page Update="Views\Dashboard\SettingsPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Pages\MainDashboardPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Dashboard\CRUD Popup\CreateModulePopup.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Views\DashboardWindow.xaml"> <Page Update="Views\DashboardWindow.xaml">

View File

@@ -1,34 +1,41 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary>
/// Dashboard Module class that holds all the information that gets displayed internal class ModuleData {
/// </summary>
class DashboardModule {
//The name the user gives the module //The name the user gives the module
public string ModuleName { get; set; } public string ModuleName { get; set; }
//The user who created it //The user who created it
public string Creator { get; set; } public string Creator { get; set; }
//All the information that the server had
public ServerInformation ServerInfo { get; set; }
//The status indicator //The status indicator
public string StatusIndicator { get; set; } public string StatusIndicator { get; set; }
//The background color of the status indicator //The background color of the status indicator
public string StatusIndicatorBG { get; set; } public string StatusIndicatorBG { get; set; }
//If the server is avaibale or not //If the server is avaibale or not
public bool ServerAvailable { get; set; } public bool ServerAvailable { get; set; }
//The Module icon the user give the server, defaults to a generic server symbol //The Module icon the user give the server, defaults to a generic server symbol
public string ModuleIcon { get; set; } public BitmapImage ModuleIcon { get; set; }
//Creation date with System.DateTime.Now //Creation date with System.DateTime.Now
public string CreationDate { get; set; } public DateTime CreationDate { get; set; }
//List that contains all the serverinformation over a period of time(lifespan of the module)
public ServerInformation ServerInformation { get; set; }
/// <summary> /// <summary>
/// This will set the Module status indicator red or green if the server is available or not /// This will set the Module status indicator red or green if the server is available or not
/// </summary> /// </summary>
/// <param name="serverAvailable"></param> /// <param name="serverAvailable"></param>
public DashboardModule(bool serverAvailable) { public ModuleData(bool serverAvailable) {
ServerAvailable = serverAvailable; ServerAvailable = serverAvailable;
StatusIndicator = ServerAvailable ? "#20c657" : "#e53935"; StatusIndicator = ServerAvailable ? "#20c657" : "#e53935";
StatusIndicatorBG = ServerAvailable ? "#94eeb0" : "#ef9a9a"; StatusIndicatorBG = ServerAvailable ? "#94eeb0" : "#ef9a9a";

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// Server information class, this will probably scale pretty big later on
/// This will hold all the information the socket will gather
/// </summary>
internal class ServerInformation {
public string ServerName { get; set; }
public string OsUserName { get; set; }
public double CpuTemp { get; set; }
public double GpuTemp { get; set; }
public TimeSpan Uptime { get; set; }
public DateTime DeployDate { get; set; }
public string PublicIpAddress { get; set; }
public string PrivateIpAddress { get; set; }
public int GpuUsage { get; set; }
public int CpuUsage { get; set; }
public double NetworkUP { get; set; }
public double NetworkDown { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents a single CPU and will be added
/// to a list to account for a multi CPU system
/// </summary>
internal class CPU {
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents a single drive on a server, this will be added
/// to a list to account for multiple drives
/// </summary>
internal class Drives {
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents a single GPU and will be added to a list
/// to account for multiple GPU's
/// </summary>
internal class GPU {
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents the mainboard
/// It will hold information about the chipset, number of hardware etc...
/// </summary>
internal class Motherboard {
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents a single network interface and will be added
/// to a list to account for multiple networking interfaces
/// </summary>
internal class NetworkInterface {
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// This class represents RAM
/// TODO: figure out if it makes sense to create a class for the entire system memory
/// or for each and every stick
/// </summary>
internal class RAM {
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
namespace Server_Dashboard {
/// <summary>
/// User class to store user informations
/// </summary>
internal class User {
public int UID { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public DateTime RegistrationDate { get; set; }
public User(DataTable userData) {
foreach (DataRow row in userData.Rows) {
UID = (int)row[0];
UserName = (string)row[1];
Email = (string)row[2];
RegistrationDate = (DateTime)row[3];
}
}
}
}

View File

@@ -5,11 +5,13 @@ using System.Text;
using System.Windows.Data; using System.Windows.Data;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Value to angle converter /// Value to angle converter
/// </summary> /// </summary>
[ValueConversion(typeof(int), typeof(double))] [ValueConversion(typeof(int), typeof(double))]
public class ValueToAngleConverter : IValueConverter { public class ValueToAngleConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value * 0.01 * 360; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value * 0.01 * 360;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)((double)value / 360); public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)((double)value / 360);

View File

@@ -1,14 +1,13 @@
using System; using System.ComponentModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// Base View Model all the other view models inherit from /// Base View Model all the other view models inherit from
/// Makes me write the INotifyPropertyChanged only once /// Makes me write the INotifyPropertyChanged only once
/// </summary> /// </summary>
class BaseViewModel : INotifyPropertyChanged { public class BaseViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { }; public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
protected void OnPropertyChanged(string prop) { protected void OnPropertyChanged(string prop) {

View File

@@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
internal class AnalyticsViewModel : BaseViewModel {
}
}

View File

@@ -1,39 +1,65 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// View Model for the modules /// View Model for the modules
/// </summary> /// </summary>
class DashboardModuleViewModel : BaseViewModel { internal class DashboardModuleViewModel : BaseViewModel {
//List with all Modules inside
public ObservableCollection<DashboardModule> Modules { get; set; }
//Creates Default Modules, remove before release and when implementing the actual data comming from the socket //List with all Modules inside
public DashboardModuleViewModel() { public ObservableCollection<ModuleData> Modules { get; set; }
Modules = new ObservableCollection<DashboardModule>();
for (int i = 0; i < 10; i++) { //Creates Default Modules, remove before release and when implementing the actual data coming from the socket
Modules.Add(new DashboardModule(true) { public DashboardModuleViewModel(DataTable moduleData) {
ModuleName = "TestModule", Modules = new ObservableCollection<ModuleData>();
Creator = "Username", foreach (DataRow row in moduleData.Rows) {
ModuleIcon = "../../Assets/Images/PlaceHolderModuleLight.png", if (row[0] == null)
CreationDate = DateTime.Now.ToString(), return;
ServerInfo = new ServerInformation() { byte[] iconBytes = row[3] == DBNull.Value ? null : (byte[])row[3];
GpuUsage = "20", DataTable serverData = DatabaseHandler.GetServerData((int)row[4]);
CpuUsage = "20", ServerInformation serverInformation = null;
CpuTemp = "88.88", if (serverData.Rows.Count != 0) {
DeployDate = DateTime.Now.ToString(), DataRow serverRow = serverData.Rows[0];
GpuTemp = "69.69", serverInformation = new ServerInformation {
ServerName = "Ubuntu", ServerName = (string)serverRow[4] ?? "",
OSUserName = "crylia " + i, PublicIpAddress = (string)serverRow[6] ?? "",
PrivateIpAdress = "192.168.1.1", PrivateIpAddress = (string)serverRow[5] ?? "",
PublicIpAdress = "85.69.102.58", Uptime = (TimeSpan)serverRow[7],
Uptime = DateTime.Now.ToString() OsUserName = (string)serverRow[3] ?? ""
};
} }
Modules.Add(new ModuleData(false) {
ModuleName = (string)row[2] ?? "",
Creator = (string)row[0] ?? "",
ModuleIcon = ConvertByteToBitmapImage(iconBytes),
CreationDate = (DateTime)row[1],
ServerInformation = serverInformation
}); });
} }
} }
private static BitmapImage ConvertByteToBitmapImage(byte[] icon) {
if (icon == null)
return null;
try {
using MemoryStream ms = new MemoryStream(icon);
BitmapImage moduleIcon = new BitmapImage();
moduleIcon.BeginInit();
moduleIcon.StreamSource = ms;
moduleIcon.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
moduleIcon.CacheOption = BitmapCacheOption.OnLoad;
moduleIcon.EndInit();
moduleIcon.Freeze();
return moduleIcon;
} catch { }
return null;
}
} }
} }

View File

@@ -1,94 +1,141 @@
using Server_Dashboard.Views.DashboardPages.ModuleCRUD; using Server_Dashboard.Views.DashboardPages.ModuleCRUD;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Server_Dashboard_Socket;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// View Model for the Dashboard /// View Model for the Dashboard
/// </summary> /// </summary>
class DashboardViewModel : BaseViewModel { internal class DashboardViewModel : BaseViewModel {
#region Private Values #region Private Values
private readonly DashboardModuleViewModel dmvm = new DashboardModuleViewModel();
#endregion private DashboardModuleViewModel dmvm;
#endregion Private Values
#region Public Values
public SettingsViewModel SettingsViewModel { get; set; }
public AnalyticsViewModel AnalyticsViewModel { get; set; }
#endregion Public Values
#region Properties #region Properties
//The Username displayed defaults to Username //The Username displayed defaults to Username
private string userName = "Username"; private User user;
public string UserName {
get { return userName; } public User User {
get { return user; }
set { set {
if(userName != value) if (user != value)
userName = value; user = value;
OnPropertyChanged(nameof(userName)); OnPropertyChanged(nameof(user));
} }
} }
//List that contains every Module //List that contains every Module
private ObservableCollection<DashboardModule> modules; private ObservableCollection<ModuleData> modules;
public ObservableCollection<DashboardModule> Modules {
public ObservableCollection<ModuleData> Modules {
get { return modules; } get { return modules; }
set { set {
if(value != modules) if (value != modules)
modules = value; modules = value;
OnPropertyChanged(nameof(modules)); OnPropertyChanged(nameof(modules));
} }
} }
#endregion
private object currentView;
public object CurrentView {
get => currentView;
set {
if (value != currentView)
currentView = value;
OnPropertyChanged(nameof(currentView));
}
}
#endregion Properties
#region Constructor #region Constructor
public DashboardViewModel() {
//Creates a new echo server, remove b4 release public DashboardViewModel(string username) {
EchoServer echoServer = new EchoServer(); //Command init
echoServer.Start();
//Command inits
OpenLinkCommand = new RelayCommand(OpenLink); OpenLinkCommand = new RelayCommand(OpenLink);
OpenNewModuleWindowCommand = new RelayCommand(OpenNewModuleWindow); OpenNewModuleWindowCommand = new RelayCommand(OpenNewModuleWindow);
CreateModuleCommand = new RelayCommand(CreateModule); SwitchViewModelCommand = new RelayCommand(SwitchViewModel);
//Sets the local module to the dashboardviewmodule modules AnalyticsViewModel = new AnalyticsViewModel();
Modules = dmvm.Modules; SettingsViewModel = new SettingsViewModel();
CurrentView = this;
DataTable userData = DatabaseHandler.GetUserData(username);
User = new User(userData);
GetModules();
} }
#endregion
#endregion Constructor
#region ICommands #region ICommands
public ICommand OpenLinkCommand { get; set; } public ICommand OpenLinkCommand { get; set; }
public ICommand OpenNewModuleWindowCommand { get; set; } public ICommand OpenNewModuleWindowCommand { get; set; }
public ICommand CreateModuleCommand { get; set; } public ICommand SwitchViewModelCommand { get; set; }
#endregion
#endregion ICommands
#region Commands #region Commands
private void SwitchViewModel(object param) {
switch (param) {
case "settingsviewmodel":
CurrentView = SettingsViewModel;
break;
case "analyticsviewmodel":
CurrentView = AnalyticsViewModel;
break;
case "dashboardviewmodel":
CurrentView = this;
break;
}
}
/// <summary> /// <summary>
/// Opens a given link in the default browser /// Opens a given link in the default browser
/// </summary> /// </summary>
/// <param name="param">The Link to be opened e.g. https://github.com/Crylia/Server-Dashboard </param> /// <param name="param">The Link to be opened e.g. https://github.com/Crylia/Server-Dashboard </param>
private void OpenLink(object param) { private void OpenLink(object param) => Process.Start(new ProcessStartInfo((string)param) { UseShellExecute = true });
Process.Start(new ProcessStartInfo((string)param) { UseShellExecute = true });
}
/// <summary> /// <summary>
/// Creates a new window to create a new Module /// Creates a new window to create a new Module
/// </summary> /// </summary>
/// <param name="param">Nothing</param> /// <param name="param">Nothing</param>
private void OpenNewModuleWindow(object param) { private void OpenNewModuleWindow(object param) {
//Creates a new CreateModulePopup and sets this view model as datacontext //Creates a new CreateModulePopup and sets this view model as data context
CreateModulePopup cmp = new CreateModulePopup { CreateModulePopup cmp = new CreateModulePopup {
DataContext = this DataContext = new CreateModuleViewModel(User.UserName)
}; };
//Opens it in the middle of the screen, setting the parent window as owner causes the //Opens it in the middle of the screen, setting the parent window as owner causes the
//application to crash when NOT in debug mode(???) //application to crash when NOT in debug mode(???)
cmp.WindowStartupLocation = WindowStartupLocation.CenterScreen; cmp.WindowStartupLocation = WindowStartupLocation.CenterScreen;
cmp.ShowDialog(); cmp.ShowDialog();
GetModules();
} }
/// <summary> private void GetModules() {
/// No function yes dmvm = new DashboardModuleViewModel(DatabaseHandler.GetUserModuleData(User.UID));
/// </summary> //Sets the local module to the dashboard view module modules
/// <param name="param">Nothing</param> Modules = dmvm.Modules;
private void CreateModule(object param) {
} }
#endregion
#endregion Commands
} }
} }

View File

@@ -0,0 +1,178 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media.Imaging;
namespace Server_Dashboard {
internal class CreateModuleViewModel : BaseViewModel, IWindowHelper {
private readonly string username;
private string serverName;
public string ServerName {
get => serverName;
set {
if (serverName != value)
serverName = value;
OnPropertyChanged(nameof(serverName));
}
}
private string moduleName;
public string ModuleName {
get => moduleName;
set {
if (moduleName != value)
moduleName = value;
OnPropertyChanged(nameof(moduleName));
}
}
private string ipAddress;
public string IpAddress {
get => ipAddress;
set {
if (ipAddress != value)
ipAddress = value;
OnPropertyChanged(nameof(ipAddress));
}
}
private string port;
public string Port {
get => port;
set {
if (port != value)
port = value;
OnPropertyChanged(nameof(port));
}
}
private BitmapImage moduleIcon;
public BitmapImage ModuleIcon {
get => moduleIcon;
set {
if (moduleIcon != value)
moduleIcon = value;
OnPropertyChanged(nameof(moduleIcon));
}
}
private string userInformationMessage;
public string UserInformationMessage {
get => userInformationMessage;
set {
if (userInformationMessage != value)
userInformationMessage = value;
OnPropertyChanged(nameof(userInformationMessage));
}
}
public CreateModuleViewModel(string username) {
this.username = username;
CreateModuleCommand = new RelayCommand(CreateModuleAsync);
SelectIconCommand = new RelayCommand(SelectIcon);
RemoveIconCommand = new RelayCommand(RemoveIcon);
TestConnectionCommand = new RelayCommand(TestConnection);
}
public ICommand RemoveIconCommand { get; set; }
public ICommand SelectIconCommand { get; set; }
public ICommand CreateModuleCommand { get; set; }
public ICommand TestConnectionCommand { get; set; }
public Action Close { get; set; }
//private readonly Regex moduleNameFilter = new Regex(@"^[A-Z][a-z][0-9]{0-20}$");
//private readonly Regex serverNameFilter = new Regex(@"^[A-Z][a-z][0-9]{0-20}$");
private readonly Regex ipFilter = new Regex(@"^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$");
/// <summary>
/// First checks if the IP address and the other credentials are valid
/// than asynchronously sends the data to the database where the module will be saved
/// this also triggers a reload of all modules to make sure the newly created module
/// will be shown without an application restart
/// </summary>
/// <param name="param">Nothing</param>
private async void CreateModuleAsync(object param) {
//Checks if the IP field is not empty and valid
if (!string.IsNullOrWhiteSpace(ipAddress) && ipFilter.IsMatch(ipAddress)) {
//Gives the Module a default name if the user doesn't name it
if (string.IsNullOrWhiteSpace(moduleName))
moduleName = "Module";
//Gives the Server a default name is the user doesn't name it
if (string.IsNullOrWhiteSpace(serverName))
serverName = "Server";
//Makes sure the name isn't any longer than characters
if (moduleName.Length >= 20) {
UserInformationMessage = "The Module Name is too long";
return;
}
//Makes sure the name isn't any longer than characters
if (serverName.Length >= 20) {
UserInformationMessage = "The Server Name is too long";
return;
}
//Clears the error message if there isn't any error
UserInformationMessage = "";
byte[] moduleIconStream = null;
if (moduleIcon != null) {
try {
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(moduleIcon));
await using MemoryStream ms = new MemoryStream();
encoder.Save(ms);
moduleIconStream = ms.ToArray();
} catch (Exception) { }
}
if (await Task.Run(() => DatabaseHandler.CreateNewModule(ipAddress, moduleName, serverName, username, moduleIconStream, port)) == 0) {
Close?.Invoke();
} else {
UserInformationMessage = "Unknown error occurred, please try again later";
}
} else {
UserInformationMessage = "The IP Address is invalid";
}
}
/// <summary>
/// Opens a file dialog and lets the user select a .jpg, .jpeg or .png file as icon
/// </summary>
/// <param name="param"></param>
private void SelectIcon(object param) {
OpenFileDialog ofd = new OpenFileDialog {
Title = "Choose an Image",
Filter = "Supported format|*.jpg;*.jpeg;*.png"
};
if (Convert.ToBoolean(ofd.ShowDialog())) {
ModuleIcon = new BitmapImage(new Uri(ofd.FileName));
}
}
/// <summary>
/// Removes the selected ModuleIcon
/// </summary>
/// <param name="param"></param>
private void RemoveIcon(object param) => ModuleIcon = null;
/// <summary>
/// Tests the socket connection
/// </summary>
/// <param name="param"></param>
private void TestConnection(object param) {
//TODO: Test connection to the socket server
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server_Dashboard {
internal class SettingsViewModel : BaseViewModel {
}
}

View File

@@ -3,15 +3,20 @@ using Server_Dashboard.Properties;
using System; using System;
using System.Windows.Input; using System.Windows.Input;
using System.Threading.Tasks; using System.Threading.Tasks;
using Server_Dashboard_Socket;
namespace Server_Dashboard { namespace Server_Dashboard {
/// <summary> /// <summary>
/// View Model for the Login Window /// View Model for the Login Window
/// </summary> /// </summary>
class LoginViewModel : BaseViewModel, IWindowHelper { internal class LoginViewModel : BaseViewModel, IWindowHelper {
#region Properties #region Properties
//Username Property //Username Property
private string username; private string username;
public string Username { public string Username {
get { return username; } get { return username; }
set { set {
@@ -20,8 +25,10 @@ namespace Server_Dashboard {
OnPropertyChanged(nameof(username)); OnPropertyChanged(nameof(username));
} }
} }
//Error Text displays an error to help the user to fill the form //Error Text displays an error to help the user to fill the form
private string errorText; private string errorText;
public string ErrorText { public string ErrorText {
get { return errorText; } get { return errorText; }
set { set {
@@ -30,18 +37,22 @@ namespace Server_Dashboard {
OnPropertyChanged(nameof(errorText)); OnPropertyChanged(nameof(errorText));
} }
} }
//Remember me button //Remember me button
private bool rememberUser; private bool rememberUser;
public bool RememberUser { public bool RememberUser {
get { return rememberUser; } get { return rememberUser; }
set { set {
if(value != rememberUser) if (value != rememberUser)
rememberUser = value; rememberUser = value;
OnPropertyChanged(nameof(rememberUser)); OnPropertyChanged(nameof(rememberUser));
} }
} }
//Loading circle, gets hidden and shown when logging in //Loading circle, gets hidden and shown when logging in
private string loading; private string loading;
public string Loading { public string Loading {
get { return loading; } get { return loading; }
set { set {
@@ -50,35 +61,44 @@ namespace Server_Dashboard {
OnPropertyChanged(nameof(loading)); OnPropertyChanged(nameof(loading));
} }
} }
#endregion
#endregion Properties
#region Public Values #region Public Values
//Close action for the Window to close properly //Close action for the Window to close properly
public Action Close { get ; set; } public Action Close { get; set; }
#endregion
#endregion Public Values
#region Constructor #region Constructor
public LoginViewModel() { public LoginViewModel() {
//SocketClient sc = new SocketClient();
//Loading circle is hidden on startup //Loading circle is hidden on startup
Loading = "Hidden"; Loading = "Hidden";
//Command inits //Command inits
LoginCommand = new RelayCommand(LoginAsync); LoginCommand = new RelayCommand(LoginAsync);
//Checks if the Username and Cookie is saved in the Settings.settings //Checks if the Username and Cookie is saved in the Settings.settings
if (!String.IsNullOrEmpty(Settings.Default.Username) && !String.IsNullOrEmpty(Settings.Default.Cookies)) { if (!String.IsNullOrEmpty(Settings.Default.Username) && !String.IsNullOrEmpty(Settings.Default.Cookies)) {
//Takes the saved Username and Remember me button status and prefills the username and checks the Remember me button //Takes the saved Username and Remember me button status and pre fills the username and checks the Remember me button
Username = Settings.Default.Username; Username = Settings.Default.Username;
RememberUser = Settings.Default.RememberMe; RememberUser = Settings.Default.RememberMe;
} }
//TODO: Autologin //TODO: Auto login
//AutoLoginAsync(); //AutoLoginAsync();
} }
#endregion
#endregion Constructor
#region ICommands #region ICommands
public ICommand LoginCommand { get; set; } public ICommand LoginCommand { get; set; }
#endregion
#endregion ICommands
#region Commands #region Commands
/// <summary> /// <summary>
/// Async login /// Async login
/// </summary> /// </summary>
@@ -88,7 +108,7 @@ namespace Server_Dashboard {
if (!String.IsNullOrWhiteSpace(Username) && !String.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) { if (!String.IsNullOrWhiteSpace(Username) && !String.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) {
//Sets loading to true to show the loading icon //Sets loading to true to show the loading icon
Loading = "Visible"; Loading = "Visible";
//Sends the Username and Password to the database and saved the result, 1 successfull, 0 wrong username or password //Sends the Username and Password to the database and saved the result, 1 successful, 0 wrong username or password
int result = await Task.Run(() => DatabaseHandler.CheckLogin(Username, (parameter as IHavePassword).SecurePassword.Unsecure())); int result = await Task.Run(() => DatabaseHandler.CheckLogin(Username, (parameter as IHavePassword).SecurePassword.Unsecure()));
//hides the loading again //hides the loading again
Loading = "Hidden"; Loading = "Hidden";
@@ -103,6 +123,7 @@ namespace Server_Dashboard {
//Sets the error text and exits function //Sets the error text and exits function
ErrorText = "Username or password is wrong."; ErrorText = "Username or password is wrong.";
return; return;
case 1: case 1:
/*No idea why this is here, gonna let it be till the remember me and autologin is 100% done /*No idea why this is here, gonna let it be till the remember me and autologin is 100% done
if (RememberUser && !String.IsNullOrEmpty(Settings.Default.Cookies)) { if (RememberUser && !String.IsNullOrEmpty(Settings.Default.Cookies)) {
@@ -119,9 +140,9 @@ namespace Server_Dashboard {
DatabaseHandler.DeleteCookie(Username); DatabaseHandler.DeleteCookie(Username);
} }
//If the remember user option is checked and the cookie is not set save everything locally //If the remember user option is checked and the cookie is not set save everything locally
if (RememberUser && String.IsNullOrEmpty(Settings.Default.Cookies)) { if (RememberUser && Settings.Default.Username != Username) {
//Creates a new GUID with the username at the end, this is the cookie //Creates a new GUID with the username at the end, this is the cookie
var cookie = new Guid().ToString() + Username; var cookie = $"{Guid.NewGuid()}+user:{Username}";
//Saves cookie, Username Remember me option to the local storage (Settings.settings) //Saves cookie, Username Remember me option to the local storage (Settings.settings)
Settings.Default.Cookies = cookie; Settings.Default.Cookies = cookie;
Settings.Default.Username = Username; Settings.Default.Username = Username;
@@ -131,35 +152,40 @@ namespace Server_Dashboard {
DatabaseHandler.AddCookie(Username, cookie); DatabaseHandler.AddCookie(Username, cookie);
} }
//Creates a new Dashboard window and shows it //Creates a new Dashboard window and shows it
DashboardWindow window = new DashboardWindow(); DashboardWindow window = new DashboardWindow() {
DataContext = new DashboardViewModel(Username)
};
window.Show(); window.Show();
//When closed, close it correctly //Close window when dashboard is shown
Close?.Invoke(); Close?.Invoke();
return; return;
case 2: case 2:
//Sets the error text //Sets the error text
ErrorText = "Server unreachable, connection timeout."; ErrorText = "Server unreachable, connection timeout.";
return; return;
default: default:
//Sets the error text //Sets the error text
ErrorText = "An unknown error has occured"; ErrorText = "An unknown error has occurred";
return; return;
} }
//If the Username and password is blank //If the Username and password is blank
//All these IF's could be one but i made multiple for the different errors so the user knows whats wrong //All these IF's could be one but i made multiple for the different errors so the user knows whats wrong
} else if (String.IsNullOrWhiteSpace(Username) && String.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) { }
if (string.IsNullOrWhiteSpace(Username) && string.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) {
//Sets the error text //Sets the error text
ErrorText = "Please provide a username and password"; ErrorText = "Please provide a username and password";
return; return;
} }
//Only if the Username is empty //Only if the Username is empty
if (String.IsNullOrWhiteSpace(Username)) { if (string.IsNullOrWhiteSpace(Username)) {
//Sets the error text //Sets the error text
ErrorText = "Username cannot be empty."; ErrorText = "Username cannot be empty.";
return; return;
} }
//Only if the password is empty //Only if the password is empty
if (String.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) { if (string.IsNullOrWhiteSpace((parameter as IHavePassword).SecurePassword.Unsecure())) {
//Sets the error text //Sets the error text
ErrorText = "Password cannot be empty."; ErrorText = "Password cannot be empty.";
return; return;
@@ -167,10 +193,12 @@ namespace Server_Dashboard {
//If there is no error, clear the error text //If there is no error, clear the error text
ErrorText = ""; ErrorText = "";
} }
#endregion
#endregion Commands
#region private functions #region private functions
//TODO: Add autologin function that locks the UI untill the user hits the abort button or the login completes
//TODO: Add auto login function that locks the UI until the user hits the abort button or the login completes
/*private async void AutoLoginAsync() { /*private async void AutoLoginAsync() {
if (Settings.Default.RememberMe && !String.IsNullOrEmpty(Settings.Default.Username) && !String.IsNullOrEmpty(Settings.Default.Cookies)) { if (Settings.Default.RememberMe && !String.IsNullOrEmpty(Settings.Default.Username) && !String.IsNullOrEmpty(Settings.Default.Cookies)) {
Loading = "Visible"; Loading = "Visible";
@@ -184,6 +212,7 @@ namespace Server_Dashboard {
} }
} }
}*/ }*/
#endregion
#endregion private functions
} }
} }

View File

@@ -0,0 +1,12 @@
<UserControl x:Class="Server_Dashboard.Views.Dashboard.AnalyticsPage"
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:local="clr-namespace:Server_Dashboard.Views.Dashboard"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
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 Server_Dashboard.Views.Dashboard {
/// <summary>
/// Interaction logic for AnalyticsPage.xaml
/// </summary>
public partial class AnalyticsPage : UserControl {
public AnalyticsPage() {
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,202 @@
<Window x:Class="Server_Dashboard.Views.DashboardPages.ModuleCRUD.CreateModulePopup"
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:Server_Dashboard.Views.DashboardPages.ModuleCRUD"
xmlns:ap="clr-namespace:Server_Dashboard"
xmlns:root="clr-namespace:Server_Dashboard" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
Height="700" Width="500" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" ap:CloseProperty.Value="True">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
</WindowChrome.WindowChrome>
<!--Create new Server Form-->
<Border Width="500" Height="700">
<Border.Background>
<SolidColorBrush Color="#2D2D2D" Opacity="1" />
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--Title Bar-->
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<TextBlock FontSize="18" Grid.Column="0" Text="Create a new Server" Margin="5 0 0 0" Foreground="White" VerticalAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<Button Style="{StaticResource CloseButton}" Grid.Column="1" Content="✕">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
<!--Main Content-->
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="1" Margin="20">
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0" />
</Grid.Effect>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<!--Server Name-->
<StackPanel VerticalAlignment="Center" Grid.Row="0" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Module Name" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0" />
</Grid.Effect>
<TextBox Text="{Binding ModuleName}" Height="40" FontSize="20" x:Name="ServerName" />
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="My Awesome Server" FontSize="20" Visibility="{Binding ElementName=ServerName, PresentationTraceSources.TraceLevel=High, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Username-->
<StackPanel VerticalAlignment="Center" Grid.Row="1" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Server Name" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0" />
</Grid.Effect>
<TextBox Text="{Binding ServerName}" Height="40" FontSize="20" x:Name="UserName" />
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="Name" FontSize="20" Visibility="{Binding ElementName=UserName, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--IP Address-->
<StackPanel VerticalAlignment="Center" Grid.Row="2" Margin="20 0 20 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="IP Address" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="*" Foreground="{StaticResource ErrorRed}" FontSize="16" />
</StackPanel>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0" />
</Grid.Effect>
<TextBox Text="{Binding IpAddress}" Height="40" FontSize="20" x:Name="IpAddress" />
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="sample.ssh.com" FontSize="20" Visibility="{Binding ElementName=IpAddress, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Port-->
<StackPanel VerticalAlignment="Center" Grid.Row="3" Margin="20 0 20 0">
<TextBlock Text="Port" FontSize="24" Margin="0 0 0 5">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
<Grid>
<Grid.Effect>
<DropShadowEffect Direction="0" BlurRadius="5" ShadowDepth="0" />
</Grid.Effect>
<TextBox Text="{Binding Port}" Height="40" FontSize="20" x:Name="Port" />
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="22" FontSize="20" Visibility="{Binding ElementName=Port, Path=Text.IsEmpty, Converter={StaticResource UserNameVisibillity}}" Grid.Column="1" IsHitTestVisible="False" Margin="5 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.12" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
</StackPanel>
<!--Module Icon-->
<Grid Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="102" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Cursor="Hand" Command="{Binding SelectIconCommand}" HorizontalAlignment="Left" Margin="20 0 20 0" Height="62" Width="62">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" x:Name="Border" Background="{StaticResource BackgroundSurface_04dp}" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}">
<Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect>
<Grid>
<Rectangle RadiusX="4" RadiusY="4">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding ModuleIcon}" />
</Rectangle.Fill>
</Rectangle>
<Viewbox Width="20" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="2">
<Canvas Width="24" Height="24">
<Path Data="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,7H11V11H7V13H11V17H13V13H17V11H13V7Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
</Grid>
</Border>
<ControlTemplate.Triggers>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Button Command="{Binding RemoveIconCommand}" HorizontalAlignment="Left" Grid.Column="1" Content="Remove Icon" Height="40" Width="150" />
</Grid>
<!--Error Text / Test Connection Result-->
<TextBlock Text="{Binding UserInformationMessage}" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="5" FontSize="14">
<TextBlock.Foreground>
<SolidColorBrush Color="#64FFDA" Opacity="0.64" />
</TextBlock.Foreground>
</TextBlock>
<!--Create Module button-->
<Grid Grid.Row="6">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Margin="20 0 10 0" Height="60" Width="Auto" Command="{Binding CreateModuleCommand}" CommandParameter="{Binding ElementName=CREATE_MODULE}" Content="CREATE MODULE" Grid.Column="0" />
<Button Margin="10 0 20 0" Height="60" Width="Auto" Command="{Binding TestConnectionCommand}" Content="TEST CONNECTION" Grid.Column="1" />
</Grid>
</Grid>
</Grid>
</Border>
</Window>

View File

@@ -0,0 +1,13 @@
<UserControl
x:Class="Server_Dashboard.Views.Dashboard.SettingsPage"
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:local="clr-namespace:Server_Dashboard.Views.Dashboard"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
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 Server_Dashboard.Views.Dashboard {
/// <summary>
/// Interaction logic for SettingsPage.xaml
/// </summary>
public partial class SettingsPage : UserControl {
public SettingsPage() {
InitializeComponent();
}
}
}

View File

@@ -1,53 +0,0 @@
<UserControl x:Class="Server_Dashboard.Views.DashboardPages.MainDashboardPage"
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:vm="clr-namespace:Server_Dashboard"
xmlns:local="clr-namespace:Server_Dashboard.Views.DashboardPages"
xmlns:modulescrud="clr-namespace:Server_Dashboard.Views.DashboardPages.ModuleCRUD"
xmlns:root="clr-namespace:Server_Dashboard"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:controls="clr-namespace:Server_Dashboard.Controls.ServerModules"
mc:Ignorable="d" d:DesignHeight="920" d:DesignWidth="1600">
<Grid Background="{StaticResource BackgroundSurface_00dp}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Dashboard and Options-->
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="{StaticResource BackgroundSurface_02dp}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Command="{Binding OpenNewModuleWindowCommand}" Content="New Module" Height="50" Margin="5 10 5 0" Cursor="Hand" x:Name="CreateModule"/>
<Button Grid.Row="1" Command="{Binding OpenDeleteModuleWindowCommand}" Content="Remove Module" Height="50" Margin="5 10 5 0" Cursor="Hand" x:Name="RemoveModule"/>
<Button Grid.Row="2" Command="{Binding OpenUpdateModuleWindowCommand}" Content="Change Module" Height="50" Margin="5 10 5 0" Cursor="Hand" x:Name="ChangeModule"/>
</Grid>
<!--ItemsControl list for the Dashboardmodules-->
<Grid Grid.Column="1">
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding Modules}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:ServerModule/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -3,86 +3,74 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Server_Dashboard.Views"
xmlns:root="clr-namespace:Server_Dashboard"
xmlns:views="clr-namespace:Server_Dashboard.Views.DashboardPages" xmlns:views="clr-namespace:Server_Dashboard.Views.DashboardPages"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/" xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
Height="1000" Width="Auto" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" mc:Ignorable="d" d:Height="1000" d:Width="1900"> Height="1000" Width="Auto" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" mc:Ignorable="d" d:Height="1000" d:Width="1900">
<WindowChrome.WindowChrome> <WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0"/> <WindowChrome CaptionHeight="0" />
</WindowChrome.WindowChrome> </WindowChrome.WindowChrome>
<Window.DataContext>
<root:DashboardViewModel/>
</Window.DataContext>
<!--Dashboard Window and Container for the Dashboards--> <!--Dashboard Window and Container for the Dashboards-->
<Grid Background="{StaticResource BackgroundSurface_00dp}"> <Grid Background="{StaticResource BackgroundSurface_00dp}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="30"/> <RowDefinition Height="30" />
<RowDefinition Height="50"/> <RowDefinition Height="50" />
<RowDefinition Height="*"/> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--Window Title--> <!--Window Title-->
<Grid Background="{StaticResource BackgroundSurface_06dp}" Grid.Row="0"> <Grid Background="{StaticResource BackgroundSurface_06dp}" Grid.Row="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" />
<ColumnDefinition Width="40"/> <ColumnDefinition Width="40" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock FontSize="18" VerticalAlignment="Center" Grid.Column="0" Text="Server Dashboard" Margin="5 0 0 0">
<i:Interaction.Triggers> <i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown"> <i:EventTrigger EventName="MouseLeftButtonDown">
<i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/> <i:CallMethodAction MethodName="DragMove" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
<Label Grid.Column="0"/> </TextBlock>
<Button Style="{StaticResource CloseButton}" Grid.Column="2" Content="✕" Cursor="Hand"> <Button Style="{StaticResource CloseButton}" Grid.Column="1" Content="✕">
<i:Interaction.Triggers> <i:Interaction.Triggers>
<i:EventTrigger EventName="Click"> <i:EventTrigger EventName="Click">
<i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/> <i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
</Button> </Button>
</Grid> </Grid>
<!--Settings, Docs, User, links etc--> <!--Settings, Docs, User, links etc-->
<Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="1" x:Name="TopBarGrid"> <Grid Background="{StaticResource BackgroundSurface_04dp}" Grid.Row="1">
<Grid.Effect> <Grid.Effect>
<DropShadowEffect Direction="270" BlurRadius="5"/> <DropShadowEffect Direction="270" BlurRadius="5" />
</Grid.Effect> </Grid.Effect>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Grid.Column="0" > <Button Grid.Column="3" Command="{Binding OpenLinkCommand}" Content="{Binding User.UserName}" Margin="10 0 10 0" Height="40" Cursor="Hand">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="4" Padding="2" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" >
<svgc:SvgViewbox Source="../Assets/Images/Settings.svg" Margin="5" IsHitTestVisible="False" Opacity="0.87"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
</Trigger>
<Trigger Property="IsPressed" Value="True">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button Grid.Column="4" Command="{Binding OpenLinkCommand}" Content="{Binding UserName}" Margin="10 0 10 0" Height="40" Cursor="Hand">
<Button.Template> <Button.Template>
<ControlTemplate TargetType="{x:Type Button}"> <ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> <Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}"> <Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}">
<Border.BorderBrush> <Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush> </Border.BorderBrush>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<svgc:SvgViewbox Source="../Assets/Images/User.svg" Margin="5" IsHitTestVisible="False" Opacity="0.87"/> <Viewbox Width="Auto" Height="Auto" IsHitTestVisible="False" Margin="5">
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0"/> <Canvas Width="24" Height="24">
<Path Data="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0" />
</StackPanel> </StackPanel>
</Border> </Border>
</Border> </Border>
@@ -90,7 +78,7 @@
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04"/> <SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -99,12 +87,12 @@
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12"/> <SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter TargetName="BackgroundOverlay" Property="BorderBrush"> <Setter TargetName="BackgroundOverlay" Property="BorderBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87"/> <SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -112,20 +100,28 @@
</ControlTemplate> </ControlTemplate>
</Button.Template> </Button.Template>
</Button> </Button>
<Button Grid.Column="3" Command="{Binding OpenLinkCommand}" CommandParameter="https://github.com/Crylia/Server-Dashboard/wiki" Content="Docs" Margin="10 0 10 0" Height="40"> <Button Grid.Column="2" Command="{Binding OpenLinkCommand}" CommandParameter="https://github.com/Crylia/Server-Dashboard/wiki" Content="Docs" Margin="10 0 10 0" Height="40">
<Button.Template> <Button.Template>
<ControlTemplate TargetType="{x:Type Button}"> <ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> <Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}"> <Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}">
<Border.BorderBrush> <Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush> </Border.BorderBrush>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<svgc:SvgViewbox Source="../Assets/Images/Docs.svg" Margin="5" IsHitTestVisible="False" Opacity="0.87"/> <Viewbox IsHitTestVisible="False" Width="Auto" Height="Auto" Margin="5">
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0"/> <Canvas Width="24" Height="24">
<Path Data="M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0" />
</StackPanel> </StackPanel>
</Border> </Border>
</Border> </Border>
@@ -133,7 +129,7 @@
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04"/> <SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -142,12 +138,12 @@
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12"/> <SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter TargetName="BackgroundOverlay" Property="BorderBrush"> <Setter TargetName="BackgroundOverlay" Property="BorderBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87"/> <SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -155,20 +151,28 @@
</ControlTemplate> </ControlTemplate>
</Button.Template> </Button.Template>
</Button> </Button>
<Button Grid.Column="2" Command="{Binding OpenLinkCommand}" CommandParameter="https://github.com/Crylia/Server-Dashboard" Content="GitHub" Margin="10 0 10 0" Height="40" Opacity="0.87" Cursor="Hand"> <Button Grid.Column="1" Command="{Binding OpenLinkCommand}" CommandParameter="https://github.com/Crylia/Server-Dashboard" Content="GitHub" Margin="10 0 10 0" Height="40" Opacity="0.87" Cursor="Hand">
<Button.Template> <Button.Template>
<ControlTemplate TargetType="{x:Type Button}"> <ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> <Border x:Name="Border" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0">
<Border.Effect> <Border.Effect>
<DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5"/> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" />
</Border.Effect> </Border.Effect>
<Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}"> <Border x:Name="BackgroundOverlay" CornerRadius="4" Background="Transparent" BorderThickness="{TemplateBinding BorderThickness}">
<Border.BorderBrush> <Border.BorderBrush>
<SolidColorBrush Color="White" Opacity="0.12"/> <SolidColorBrush Color="White" Opacity="0.12" />
</Border.BorderBrush> </Border.BorderBrush>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Source="../Assets/Images/GitHubLight.png" Margin="5"/> <Viewbox IsHitTestVisible="False" Width="Auto" Height="Auto" Margin="5">
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0"/> <Canvas Width="24" Height="24">
<Path Data="M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5 0 10 0" />
</StackPanel> </StackPanel>
</Border> </Border>
</Border> </Border>
@@ -176,7 +180,7 @@
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04"/> <SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -185,12 +189,12 @@
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter TargetName="BackgroundOverlay" Property="Background"> <Setter TargetName="BackgroundOverlay" Property="Background">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12"/> <SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Setter TargetName="BackgroundOverlay" Property="BorderBrush"> <Setter TargetName="BackgroundOverlay" Property="BorderBrush">
<Setter.Value> <Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87"/> <SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </Trigger>
@@ -200,8 +204,264 @@
</Button> </Button>
</Grid> </Grid>
<!--UserControl Container for the Dashboard pages--> <!--UserControl Container for the Dashboard pages-->
<UserControl Grid.Row="3"> <Grid Grid.Row="2">
<views:MainDashboardPage/> <Grid.ColumnDefinitions>
</UserControl> <ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="{StaticResource BackgroundSurface_02dp}">
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Navigation" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.67" />
</TextBlock.Foreground>
</TextBlock>
<RadioButton IsChecked="True" Command="{Binding SwitchViewModelCommand}" CommandParameter="dashboardviewmodel" Grid.Row="1" Content="Dashboard" Height="50">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="{StaticResource BackgroundSurface_02dp}" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border x:Name="Background" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="3 0 0 0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<Viewbox IsHitTestVisible="False" Width="20" Height="20" Margin="15 0 5 0">
<Canvas Width="24" Height="24">
<Path x:Name="PathHome" Data="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock x:Name="Text" FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter TargetName="PathHome" Property="Fill">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#181818" />
<Setter TargetName="Text" Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value>
</Setter>
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton Command="{Binding SwitchViewModelCommand}" CommandParameter="analyticsviewmodel" Grid.Row="2" Content="Analytics" Height="50">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="{StaticResource BackgroundSurface_02dp}" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border x:Name="Background" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="3 0 0 0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<Viewbox Margin="15 0 5 0" IsHitTestVisible="False" Width="20" Height="20">
<Canvas Width="24" Height="24">
<Path x:Name="PathAnalysis" Data="M6,22A3,3 0 0,1 3,19C3,18.4 3.18,17.84 3.5,17.37L9,7.81V6A1,1 0 0,1 8,5V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V5A1,1 0 0,1 15,6V7.81L20.5,17.37C20.82,17.84 21,18.4 21,19A3,3 0 0,1 18,22H6M5,19A1,1 0 0,0 6,20H18A1,1 0 0,0 19,19C19,18.79 18.93,18.59 18.82,18.43L16.53,14.47L14,17L8.93,11.93L5.18,18.43C5.07,18.59 5,18.79 5,19M13,10A1,1 0 0,0 12,11A1,1 0 0,0 13,12A1,1 0 0,0 14,11A1,1 0 0,0 13,10Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock x:Name="Text" FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter TargetName="PathAnalysis" Property="Fill">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#181818" />
<Setter TargetName="Text" Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value>
</Setter>
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton Command="{Binding SwitchViewModelCommand}" CommandParameter="settingsviewmodel" Grid.Row="3" Content="Settings" Height="50">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="{StaticResource BackgroundSurface_02dp}" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border x:Name="Background" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="3 0 0 0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<Viewbox Margin="15 0 5 0" IsHitTestVisible="False" Width="20" Height="20">
<Canvas Width="24" Height="24">
<Path x:Name="PathSettings" Data="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z">
<Path.Fill>
<SolidColorBrush Color="White" Opacity="0.87" />
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<TextBlock x:Name="Text" FontSize="{TemplateBinding FontSize}" TextAlignment="Center" Padding="0" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.87" />
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.04" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter TargetName="PathSettings" Property="Fill">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#181818" />
<Setter TargetName="Text" Property="Foreground" Value="{StaticResource DeepPurple_A100}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity="0.12" />
</Setter.Value>
</Setter>
<Setter TargetName="Background" Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="#B388FF" Opacity=".87" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
</Grid>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Module" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10 0 0 0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" Opacity="0.67" />
</TextBlock.Foreground>
</TextBlock>
<Button Grid.Row="1" Command="{Binding OpenNewModuleWindowCommand}" Content="New Module" Height="50" Margin="5 10 5 0" Cursor="Hand" />
<Button Grid.Row="2" Command="{Binding OpenDeleteModuleWindowCommand}" Content="Remove Module" Height="50" Margin="5 10 5 0" Cursor="Hand" />
<Button Grid.Row="3" Command="{Binding OpenUpdateModuleWindowCommand}" Content="Change Module" Height="50" Margin="5 10 5 0" Cursor="Hand" />
</Grid>
</Grid>
<ContentControl Grid.Column="1" Content="{Binding CurrentView}" />
</Grid>
</Grid> </Grid>
</Window> </Window>

View File

@@ -0,0 +1,30 @@
<UserControl x:Class="Server_Dashboard.Views.DashboardPages.MainDashboardPage"
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:controls="clr-namespace:Server_Dashboard.Controls.ServerModules"
mc:Ignorable="d" d:DesignHeight="920" d:DesignWidth="1600">
<Grid Background="{StaticResource BackgroundSurface_00dp}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--ItemsControl list for the Dashboard modules-->
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding Modules}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel VerticalAlignment="Top" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:ServerModule />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
</UserControl>

View File

@@ -12,10 +12,12 @@ using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace Server_Dashboard.Views.DashboardPages { namespace Server_Dashboard.Views.DashboardPages {
/// <summary> /// <summary>
/// Interaktionslogik für MainDashboardPage.xaml /// Interaktionslogik für MainDashboardPage.xaml
/// </summary> /// </summary>
public partial class MainDashboardPage : UserControl { public partial class MainDashboardPage : UserControl {
public MainDashboardPage() { public MainDashboardPage() {
InitializeComponent(); InitializeComponent();
} }

View File

@@ -33,6 +33,14 @@
} }
} }
}, },
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"runtime.native.System.Data.SqlClient.sni/4.7.0": { "runtime.native.System.Data.SqlClient.sni/4.7.0": {
"dependencies": { "dependencies": {
"runtime.win-arm64.runtime.native.System.Data.SqlClient.sni": "4.4.0", "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni": "4.4.0",
@@ -157,6 +165,9 @@
}, },
"System.Security.Principal.Windows/4.7.0": {}, "System.Security.Principal.Windows/4.7.0": {},
"Server Dashboard Socket/1.0.0": { "Server Dashboard Socket/1.0.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1"
},
"runtime": { "runtime": {
"Server Dashboard Socket.dll": {} "Server Dashboard Socket.dll": {}
} }
@@ -198,6 +209,13 @@
"path": "microsoft.xaml.behaviors.wpf/1.1.31", "path": "microsoft.xaml.behaviors.wpf/1.1.31",
"hashPath": "microsoft.xaml.behaviors.wpf.1.1.31.nupkg.sha512" "hashPath": "microsoft.xaml.behaviors.wpf.1.1.31.nupkg.sha512"
}, },
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"runtime.native.System.Data.SqlClient.sni/4.7.0": { "runtime.native.System.Data.SqlClient.sni/4.7.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "FA6871C28C6B96CD3932405F6C88CE357B9CAC41" #pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "BA652589A766CDFB2D42F74F8B0DDD26A50869F0"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
@@ -10,8 +10,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using Server_Dashboard; using Server_Dashboard;
using Server_Dashboard.Views.Dashboard;
using Server_Dashboard.Views.DashboardPages; using Server_Dashboard.Views.DashboardPages;
using Server_Dashboard.Views.DashboardPages.ModuleCRUD; using Server_Dashboard.Views.DashboardPages.ModuleCRUD;
using SharpVectors.Converters;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
@@ -56,7 +58,7 @@ namespace Server_Dashboard {
} }
_contentLoaded = true; _contentLoaded = true;
#line 7 "..\..\..\App.xaml" #line 9 "..\..\..\App.xaml"
this.StartupUri = new System.Uri("LoginWindow.xaml", System.UriKind.Relative); this.StartupUri = new System.Uri("LoginWindow.xaml", System.UriKind.Relative);
#line default #line default

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "FA6871C28C6B96CD3932405F6C88CE357B9CAC41" #pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "BA652589A766CDFB2D42F74F8B0DDD26A50869F0"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
@@ -10,8 +10,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using Server_Dashboard; using Server_Dashboard;
using Server_Dashboard.Views.Dashboard;
using Server_Dashboard.Views.DashboardPages; using Server_Dashboard.Views.DashboardPages;
using Server_Dashboard.Views.DashboardPages.ModuleCRUD; using Server_Dashboard.Views.DashboardPages.ModuleCRUD;
using SharpVectors.Converters;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
@@ -56,7 +58,7 @@ namespace Server_Dashboard {
} }
_contentLoaded = true; _contentLoaded = true;
#line 7 "..\..\..\App.xaml" #line 9 "..\..\..\App.xaml"
this.StartupUri = new System.Uri("LoginWindow.xaml", System.UriKind.Relative); this.StartupUri = new System.Uri("LoginWindow.xaml", System.UriKind.Relative);
#line default #line default

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\..\Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "74B46BE3BAB1BA752DF3E2239D67C2C6B44ED2A3" #pragma checksum "..\..\..\..\..\Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "74BED8DF4E986CFA6EFDD59B3915D539092EE365"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\..\Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "74B46BE3BAB1BA752DF3E2239D67C2C6B44ED2A3" #pragma checksum "..\..\..\..\..\Controls\DoubleRoundProgressBar\DoubleRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "74BED8DF4E986CFA6EFDD59B3915D539092EE365"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\..\Controls\HalfRoundProgressBar\HalfRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "F8123F9E313CFC197FD21BBF3619385A6FC8FC20" #pragma checksum "..\..\..\..\..\Controls\HalfRoundProgressBar\HalfRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "B2F50F33E8CEEA6D3D19CD60460CE63C13BA1394"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.

View File

@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\..\Controls\HalfRoundProgressBar\HalfRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "F8123F9E313CFC197FD21BBF3619385A6FC8FC20" #pragma checksum "..\..\..\..\..\Controls\HalfRoundProgressBar\HalfRoundProgressBar.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "B2F50F33E8CEEA6D3D19CD60460CE63C13BA1394"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.

Some files were not shown because too many files have changed in this diff Show More