diff --git a/.gitignore b/.gitignore
index a6e99c5..67fa262 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ packages/
*.user
TestResults/
*/App_Data/
-*.suo
\ No newline at end of file
+*.suo
+.vs
diff --git a/.vs/CalDav/config/applicationhost.config b/.vs/CalDav/config/applicationhost.config
new file mode 100644
index 0000000..c54b7dd
--- /dev/null
+++ b/.vs/CalDav/config/applicationhost.config
@@ -0,0 +1,1037 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json
new file mode 100644
index 0000000..7f3f169
--- /dev/null
+++ b/.vs/VSWorkspaceState.json
@@ -0,0 +1,7 @@
+{
+ "ExpandedNodes": [
+ ""
+ ],
+ "SelectedNode": "\\CalDav.sln (CalDav.sln)",
+ "PreviewInSolutionExplorer": false
+}
\ No newline at end of file
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
new file mode 100644
index 0000000..0fc515c
Binary files /dev/null and b/.vs/slnx.sqlite differ
diff --git a/Backup/Demo.MVC.csproj b/Backup/Demo.MVC.csproj
new file mode 100644
index 0000000..4c28463
--- /dev/null
+++ b/Backup/Demo.MVC.csproj
@@ -0,0 +1,174 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ 2.0
+ {9164611E-4CAF-4FE1-B707-397CC1D515C0}
+ {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ Demo.MVC
+ Demo.MVC
+ v4.0
+ false
+ true
+
+
+
+
+ ..\
+ true
+
+
+
+ true
+ full
+ false
+ bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll
+
+
+ True
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.Helpers.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Mvc.3.0.20105.1\lib\net40\System.Web.Mvc.dll
+
+
+ ..\packages\Microsoft.AspNet.Providers.Core.1.1\lib\net40\System.Web.Providers.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Deployment.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll
+
+
+
+
+
+ Global.asax
+
+
+
+
+
+
+
+
+
+ Web.config
+
+
+ Web.config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {471ea68f-fb1f-4df8-aac1-31022c7316ab}
+ CalDav.Server
+
+
+ {01a4c4cf-5ad1-4324-a391-dc922c84be1c}
+ CalDav
+
+
+
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+ /
+ http://localhost:59780/
+ False
+ False
+
+
+ False
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Backup/Global.asax b/Backup/Global.asax
new file mode 100644
index 0000000..eaaf9a9
--- /dev/null
+++ b/Backup/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="Demo.MVC.MvcApplication" Language="C#" %>
diff --git a/Backup/Global.asax.cs b/Backup/Global.asax.cs
new file mode 100644
index 0000000..6549a0a
--- /dev/null
+++ b/Backup/Global.asax.cs
@@ -0,0 +1,38 @@
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace Demo.MVC {
+ // Note: For instructions on enabling IIS6 or IIS7 classic mode,
+ // visit http://go.microsoft.com/?LinkId=9394801
+
+ public class MvcApplication : System.Web.HttpApplication {
+ public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
+ filters.Add(new HandleErrorAttribute());
+ }
+
+ public static void RegisterRoutes(RouteCollection routes) {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+ CalDav.Server.Controllers.CalDavController.RegisterRoutes(routes);
+
+ routes.MapRoute(
+ "Default", // Route name
+ "{controller}/{action}/{id}", // URL with parameters
+ new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
+ );
+
+
+ }
+
+ protected void Application_Start() {
+ AreaRegistration.RegisterAllAreas();
+
+ // Use LocalDB for Entity Framework by default
+ Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
+
+ RegisterGlobalFilters(GlobalFilters.Filters);
+ RegisterRoutes(RouteTable.Routes);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backup/Models/Calendar.cs b/Backup/Models/Calendar.cs
new file mode 100644
index 0000000..c0a33a9
--- /dev/null
+++ b/Backup/Models/Calendar.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Linq;
+
+namespace CalDav.MVC.Models {
+ public class CalendarInfo : CalDav.Calendar, CalDav.Server.Models.ICalendarInfo {
+ public string Filename { get; set; }
+ public DateTime LastModified {
+ get {
+ return System.IO.File.GetLastWriteTimeUtc(Filename);
+ }
+ }
+
+ private string this[string name] {
+ get {
+ name = name.ToUpper();
+ if (!name.StartsWith("X-")) name = "X-" + name;
+ var prop = Properties.FirstOrDefault(x => x.Item1.Is(name));
+ if (prop == null) return null;
+ return prop.Item2;
+ }
+ set {
+ name = name.ToUpper();
+ if (!name.StartsWith("X-")) name = "X-" + name;
+ var newprop = Tuple.Create(name, value, (System.Collections.Specialized.NameValueCollection)null);
+ var prop = Properties.FirstOrDefault(x => x.Item1.Is(name));
+ if (prop != null) Properties.Remove(prop);
+ Properties.Add(newprop);
+ }
+ }
+
+ public string Name {
+ get {
+ return this["Name"];
+ }
+ set {
+ this["Name"] = value;
+ }
+ }
+
+ public string Description {
+ get {
+ return this["Description"];
+ }
+ set {
+ this["Description"] = value;
+ }
+ }
+
+ public string ID {
+ get {
+ return this["ID"];
+ }
+ set {
+ this["ID"] = value;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Backup/Models/CalendarRepository.cs b/Backup/Models/CalendarRepository.cs
new file mode 100644
index 0000000..884468b
--- /dev/null
+++ b/Backup/Models/CalendarRepository.cs
@@ -0,0 +1,127 @@
+using CalDav.Server.Models;
+using System;
+using System.Linq;
+using System.Security.Principal;
+
+namespace CalDav.MVC.Models {
+ public class CalendarRepository : ICalendarRepository {
+ private string _Directory;
+
+ public CalendarRepository(IPrincipal user) {
+ _Directory = System.IO.Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "App_Data\\Calendars");
+ System.IO.Directory.CreateDirectory(_Directory);
+ }
+
+ public IQueryable GetCalendars() {
+ var files = System.IO.Directory.GetDirectories(_Directory, "*.ical", System.IO.SearchOption.AllDirectories);
+ if (files.Length == 0)
+ return new[] { CreateCalendar("me") }.AsQueryable();
+
+ var serializer = new Serializer();
+ return files.Select(x => {
+ using (var file = System.IO.File.OpenText(x)) {
+ var cal = new CalendarInfo();
+ cal.Deserialize(file, serializer);
+ cal.Filename = x;
+ cal.ID = System.IO.Path.GetDirectoryName(x)
+ .Trim(System.IO.Path.DirectorySeparatorChar)
+ .Split(System.IO.Path.DirectorySeparatorChar)
+ .LastOrDefault();
+ return cal;
+ }
+ }).Where(x => x != null).AsQueryable();
+ }
+
+ private static string MakePathSafe(string input) {
+ if (input == null) return null;
+ foreach (var c in System.IO.Path.GetInvalidFileNameChars())
+ input = input.Replace(c, '_');
+ return input.Trim('_');
+ }
+
+ public ICalendarInfo CreateCalendar(string id) {
+ if (string.IsNullOrEmpty(id)) return null;
+ id = MakePathSafe(id);
+ var filename = System.IO.Path.Combine(_Directory, id + "\\_.ical");
+ var ical = new CalendarInfo();
+ var serializer = new Serializer();
+ System.IO.Directory.CreateDirectory(System.IO.Path.Combine(_Directory, id));
+ using (var file = System.IO.File.OpenWrite(filename))
+ serializer.Serialize(file, ical);
+ ical.Filename = filename;
+ return ical;
+ }
+
+ public ICalendarInfo GetCalendarByID(string id) {
+ if (string.IsNullOrEmpty(id)) id = "me";
+ id = MakePathSafe(id);
+ var filename = System.IO.Path.Combine(_Directory, id + "\\_.ical");
+ if (!System.IO.File.Exists(filename)) {
+ if (id == "me") return CreateCalendar("me");
+ return null;
+ }
+
+ var calendar = new CalendarInfo();
+ using (var file = System.IO.File.OpenText(filename)) {
+ calendar.Deserialize(file);
+ calendar.Filename = filename;
+ calendar.ID = id;
+ return calendar;
+ }
+ }
+
+ public ICalendarObject GetObjectByUID(ICalendarInfo calendar, string uid) {
+ var filename = System.IO.Path.Combine(_Directory, calendar.ID, uid + ".ics");
+ if (!System.IO.File.Exists(filename)) return null;
+ var serializer = new Serializer();
+ using (var file = System.IO.File.OpenText(filename)) {
+ var ical = (serializer.Deserialize(file))[0];
+ return ical.Events.OfType()
+ .Union(ical.ToDos)
+ .Union(ical.FreeBusy)
+ .Union(ical.JournalEntries)
+ .FirstOrDefault();
+ }
+ }
+
+ public void Save(ICalendarInfo calendar, ICalendarObject e) {
+ var filename = System.IO.Path.Combine(_Directory, calendar.ID, e.UID + ".ics");
+ var ical = new CalDav.Calendar();
+ ical.AddItem(e);
+ var serializer = new Serializer();
+ using (var file = System.IO.File.Open(filename, System.IO.FileMode.Create))
+ serializer.Serialize(file, ical);
+ }
+
+ public IQueryable GetObjectsByFilter(ICalendarInfo calendar, Filter filter) {
+ throw new NotImplementedException();
+ }
+
+ public IQueryable GetObjects(ICalendarInfo calendar) {
+ if (calendar == null) return new ICalendarObject[0].AsQueryable();
+ var directory = System.IO.Path.Combine(_Directory, calendar.ID);
+ var files = System.IO.Directory.GetFiles(directory, "*.ics");
+ var serializer = new Serializer();
+ return files
+ .SelectMany(x => serializer.Deserialize(x))
+ .SelectMany(x => x.Items)
+ .AsQueryable();
+ }
+
+ public ICalendarObject GetObjectByPath(string path) {
+ var calendar = GetCalendarByID(path);
+ var uid = path.Split('/').Last().Split('.').FirstOrDefault();
+ return GetObjectByUID(calendar, uid);
+ }
+
+ public void DeleteObject(ICalendarInfo calendar, string path) {
+ var uid = path.Split('/').Last().Split('.').FirstOrDefault();
+ var obj = GetObjectByUID(calendar, uid);
+ if (obj == null) return;
+ var filename = System.IO.Path.Combine(_Directory, calendar.ID, obj.UID + ".ics");
+ if (!System.IO.File.Exists(filename))
+ return;
+ System.IO.File.Delete(filename);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backup/Properties/AssemblyInfo.cs b/Backup/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b8035dd
--- /dev/null
+++ b/Backup/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Demo.MVC")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo.MVC")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3fb7599d-a6a9-4202-99e5-d780f734cf9b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Backup/Views/Shared/Error.cshtml b/Backup/Views/Shared/Error.cshtml
new file mode 100644
index 0000000..7618dc4
--- /dev/null
+++ b/Backup/Views/Shared/Error.cshtml
@@ -0,0 +1,15 @@
+@{
+ Layout = null;
+}
+
+
+
+
+ Error
+
+
+
+ Sorry, an error occurred while processing your request.
+
+
+
\ No newline at end of file
diff --git a/Backup/Views/Shared/_Layout.cshtml b/Backup/Views/Shared/_Layout.cshtml
new file mode 100644
index 0000000..73ddad9
--- /dev/null
+++ b/Backup/Views/Shared/_Layout.cshtml
@@ -0,0 +1,12 @@
+
+
+
+ @ViewBag.Title
+
+
+
+
+
+ @RenderBody()
+
+
diff --git a/Backup/Views/Web.config b/Backup/Views/Web.config
new file mode 100644
index 0000000..a4def2a
--- /dev/null
+++ b/Backup/Views/Web.config
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Backup/Views/_ViewStart.cshtml b/Backup/Views/_ViewStart.cshtml
new file mode 100644
index 0000000..efda124
--- /dev/null
+++ b/Backup/Views/_ViewStart.cshtml
@@ -0,0 +1,3 @@
+@{
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
\ No newline at end of file
diff --git a/Backup/Web.Debug.config b/Backup/Web.Debug.config
new file mode 100644
index 0000000..2c6dd51
--- /dev/null
+++ b/Backup/Web.Debug.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Backup/Web.Release.config b/Backup/Web.Release.config
new file mode 100644
index 0000000..4122d79
--- /dev/null
+++ b/Backup/Web.Release.config
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Backup/Web.config b/Backup/Web.config
new file mode 100644
index 0000000..fa06dd1
--- /dev/null
+++ b/Backup/Web.config
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Backup/packages.config b/Backup/packages.config
new file mode 100644
index 0000000..bb29542
--- /dev/null
+++ b/Backup/packages.config
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CalCli.API/AlarmActions.cs b/CalCli.API/AlarmActions.cs
new file mode 100644
index 0000000..0b2cb03
--- /dev/null
+++ b/CalCli.API/AlarmActions.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CalCli.API
+{
+ public enum AlarmActions
+ {
+ NONE,
+ AUDIO,
+ DISPLAY,
+ EMAIL
+ }
+}
diff --git a/CalCli.API/CalCli.API.csproj b/CalCli.API/CalCli.API.csproj
new file mode 100644
index 0000000..038a825
--- /dev/null
+++ b/CalCli.API/CalCli.API.csproj
@@ -0,0 +1,67 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2C258FAE-97ED-4916-B5A3-4723700D675D}
+ Library
+ Properties
+ CalCli.API
+ CalCli.API
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CalCli.API/IAlarm.cs b/CalCli.API/IAlarm.cs
new file mode 100644
index 0000000..ddb505a
--- /dev/null
+++ b/CalCli.API/IAlarm.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CalCli.API
+{
+ public interface IAlarm
+ {
+ AlarmActions Action { get; set; }
+ string Description { get; set; }
+ ITrigger Trigger { get; set; }
+ }
+}
diff --git a/CalCli.API/ICalendar.cs b/CalCli.API/ICalendar.cs
new file mode 100644
index 0000000..07fa9e3
--- /dev/null
+++ b/CalCli.API/ICalendar.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CalCli.API
+{
+ public interface ICalendar
+ {
+ string Name { get; set; }
+ string Description { get; set; }
+ void Save(IEvent e);
+ void Save(IToDo t);
+ IToDo createToDo();
+ ITrigger createTrigger();
+ IAlarm createAlarm();
+ IEvent createEvent();
+ }
+}
diff --git a/CalCli.API/IConnection.cs b/CalCli.API/IConnection.cs
new file mode 100644
index 0000000..d4303f3
--- /dev/null
+++ b/CalCli.API/IConnection.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net;
+using System.IO;
+
+namespace CalCli.API
+{
+ public interface IConnection
+ {
+ WebRequest Authorize(WebRequest request);
+ }
+}
diff --git a/CalCli.API/IEvent.cs b/CalCli.API/IEvent.cs
new file mode 100644
index 0000000..11db4b7
--- /dev/null
+++ b/CalCli.API/IEvent.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CalCli.API
+{
+ public interface IEvent
+ {
+ ICollection Alarms { get; set; }
+ ICollection Categories { get; set; }
+ DateTime? Created { get; set; }
+ string Description { get; set; }
+ DateTime? Start { get; set; }
+ DateTime? End { get; set; }
+ string Summary { get; set; }
+ string UID { get; set; }
+ Uri Url { get; set; }
+ }
+}
diff --git a/CalCli.API/IServer.cs b/CalCli.API/IServer.cs
new file mode 100644
index 0000000..551f270
--- /dev/null
+++ b/CalCli.API/IServer.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace CalCli.API
+{
+ public interface IServer
+ {
+ Uri Url { get; set; }
+ IConnection Connection { get; set; }
+ ICalendar[] GetCalendars();
+ void CreateCalendar(ICalendar calendar);
+ }
+}
diff --git a/CalCli.API/IToDo.cs b/CalCli.API/IToDo.cs
new file mode 100644
index 0000000..3377ef2
--- /dev/null
+++ b/CalCli.API/IToDo.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CalCli.API
+{
+ public interface IToDo
+ {
+ string UID { get; set; }
+ DateTime? Start { get; set; }
+ DateTime? Due { get; set; }
+ string Summary { get; set; }
+ ICollection Categories { get; set; }
+ int? Priority { get; set; }
+ int? Sequence { get; set; }
+ Statuses? Status { get; set; }
+ DateTime? Completed { get; set; }
+ }
+}
diff --git a/CalCli.API/ITrigger.cs b/CalCli.API/ITrigger.cs
new file mode 100644
index 0000000..a51c6ea
--- /dev/null
+++ b/CalCli.API/ITrigger.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CalCli.API
+{
+ public interface ITrigger
+ {
+ Relateds Related { get; set; }
+ TimeSpan? Duration { get; set; }
+ DateTime? DateTime { get; set; }
+ }
+}
diff --git a/CalCli.API/Properties/AssemblyInfo.cs b/CalCli.API/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..29a202b
--- /dev/null
+++ b/CalCli.API/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CalCli.API")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CalCli.API")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2c258fae-97ed-4916-b5a3-4723700d675d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/CalCli.API/Relateds.cs b/CalCli.API/Relateds.cs
new file mode 100644
index 0000000..290c698
--- /dev/null
+++ b/CalCli.API/Relateds.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CalCli.API
+{
+ public enum Relateds
+ {
+ Start, End
+ }
+}
diff --git a/CalDav/Statuses.cs b/CalCli.API/Statuses.cs
similarity index 79%
rename from CalDav/Statuses.cs
rename to CalCli.API/Statuses.cs
index 828a67b..2972458 100644
--- a/CalDav/Statuses.cs
+++ b/CalCli.API/Statuses.cs
@@ -1,5 +1,5 @@
-namespace CalDav {
+namespace CalCli.API {
public enum Statuses {
COMPLETED, CANCELED, TENTATIVE, NEEDS_ACTION, DRAFT
}
diff --git a/CalCli.Util/AutoConfiguration.cs b/CalCli.Util/AutoConfiguration.cs
new file mode 100644
index 0000000..d5bfef6
--- /dev/null
+++ b/CalCli.Util/AutoConfiguration.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CalCli;
+using OutlookClient;
+using CalCli.API;
+using System.IO;
+using CalCli.Connections;
+using CalCli.UI;
+
+namespace CalCli.Util
+{
+ public class AutoConfiguration
+ {
+ private static IConnection refreshGoogleToken()
+ {
+ IConnection connection;
+ GoogleOAuthForm form = new GoogleOAuthForm();
+ form.ShowDialog();
+ connection = new GoogleConnection(form.Result.Token);
+ StreamWriter sw = new StreamWriter("token");
+ sw.WriteLine(form.Result.Token);
+ sw.Close();
+ return connection;
+ }
+ public static IServer GetCalendarServer(CalendarTypes calendarTypes, string username = null, string password = null)
+ {
+ IServer server;
+ if(calendarTypes == CalendarTypes.Outlook)
+ {
+ return new OutlookServer();
+ }
+ else
+ {
+ IConnection connection;
+ if (calendarTypes == CalendarTypes.Google)
+ {
+ if (File.Exists("token"))
+ {
+ StreamReader sr = new StreamReader("token");
+ connection = new GoogleConnection(sr.ReadLine());
+ sr.Close();
+ }
+ else
+ {
+ connection = refreshGoogleToken();
+ }
+ server = null;
+ }
+ else
+ {
+ connection = new BasicConnection(username , password);
+ server = null;
+ }
+ if (server == null)
+ {
+ try
+ {
+ server = new CalDav.Client.Server(urlFromCalendarType(calendarTypes), connection, username, password);
+
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "Authentication is required" && connection.GetType().Equals(new GoogleConnection("").GetType()))
+ {
+ connection = refreshGoogleToken();
+ server = new CalDav.Client.Server(urlFromCalendarType(calendarTypes), connection, username, password);
+
+ }
+ else
+ throw ex;
+ }
+ }
+ return server;
+ }
+ }
+
+ private static string urlFromCalendarType(CalendarTypes calendarTypes)
+ {
+ switch (calendarTypes) {
+ case CalendarTypes.Google:
+ return "https://apidata.googleusercontent.com/caldav/v2/";
+ case CalendarTypes.iCloud:
+ return "https://caldav.icloud.com/";
+ case CalendarTypes.Yahoo:
+ return "https://caldav.calendar.yahoo.com/dav/";
+ case CalendarTypes.Outlook:
+ return "Outlook";
+ }
+ return null;
+ }
+ }
+}
+
+
+
diff --git a/CalCli.Util/CalCli.Util.csproj b/CalCli.Util/CalCli.Util.csproj
new file mode 100644
index 0000000..8b73cfb
--- /dev/null
+++ b/CalCli.Util/CalCli.Util.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}
+ Library
+ Properties
+ CalCli.Util
+ CalCli.Util
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
+
+ {dbefed7e-dc69-48c0-9ac3-428b2168a17a}
+ CalCli
+
+
+ {1b9b42a0-a34b-4bf6-a5d5-21c46ed0d9b3}
+ CalDav.Client
+
+
+ {01af789a-f9ce-47f7-a66c-d3bae82aecc3}
+ OutlookClient
+
+
+
+
+
\ No newline at end of file
diff --git a/CalCli.Util/CalendarTypes.cs b/CalCli.Util/CalendarTypes.cs
new file mode 100644
index 0000000..a59ed6c
--- /dev/null
+++ b/CalCli.Util/CalendarTypes.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CalCli.Util
+{
+ public enum CalendarTypes
+ {
+ Outlook,
+ Google,
+ Yahoo,
+ iCloud
+ }
+}
diff --git a/CalCli.Util/Properties/AssemblyInfo.cs b/CalCli.Util/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0412bc2
--- /dev/null
+++ b/CalCli.Util/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CalCli.Util")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CalCli.Util")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("00b20f5c-ee2c-4a3d-9bb6-ea426a02c985")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.1.1.0")]
+[assembly: AssemblyFileVersion("1.1.1.0")]
diff --git a/CalCli/CalCli.csproj b/CalCli/CalCli.csproj
new file mode 100644
index 0000000..71e77c1
--- /dev/null
+++ b/CalCli/CalCli.csproj
@@ -0,0 +1,91 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {DBEFED7E-DC69-48C0-9AC3-428B2168A17A}
+ Library
+ Properties
+ CalCli
+ CalCli
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ GoogleOAuthForm.cs
+
+
+
+
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
+
+ {1b9b42a0-a34b-4bf6-a5d5-21c46ed0d9b3}
+ CalDav.Client
+
+
+ {01a4c4cf-5ad1-4324-a391-dc922c84be1c}
+ CalDav
+
+
+
+
+ GoogleOAuthForm.cs
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CalCli/Connections/BasicConnection.cs b/CalCli/Connections/BasicConnection.cs
new file mode 100644
index 0000000..71674aa
--- /dev/null
+++ b/CalCli/Connections/BasicConnection.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Net;
+using CalCli.API;
+
+namespace CalCli
+{
+ public class BasicConnection : IConnection, ICredentials
+ {
+ private string username;
+ private string password;
+
+ public BasicConnection(string username, string password)
+ {
+ this.username = username;
+ this.password = password;
+ }
+
+ public WebRequest Authorize(WebRequest request)
+ {
+ request.Credentials = this;
+
+ if (request.Credentials != null)
+ {
+ //req.Credentials = credentials;
+ var b64 = username + ":" + password;
+ b64 = System.Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(b64));
+ request.Headers[HttpRequestHeader.Authorization] = "Basic " + b64;
+ }
+ ((HttpWebRequest)request).UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
+ return request;
+ }
+
+ public NetworkCredential GetCredential(Uri uri, string authType)
+ {
+ return new NetworkCredential(username, password);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CalCli/Connections/GoogleConnection.cs b/CalCli/Connections/GoogleConnection.cs
new file mode 100644
index 0000000..6c877b0
--- /dev/null
+++ b/CalCli/Connections/GoogleConnection.cs
@@ -0,0 +1,21 @@
+using System.Net;
+using CalCli.API;
+
+namespace CalCli.Connections
+{
+ public class GoogleConnection : IConnection
+ {
+ private string token;
+
+ public GoogleConnection(string token)
+ {
+ this.token = token;
+ }
+
+ public WebRequest Authorize(WebRequest request)
+ {
+ request.Headers.Add(HttpRequestHeader.Authorization, "Bearer "+token);
+ return request;
+ }
+ }
+}
diff --git a/CalCli/Connections/GoogleOAuthFormResponse.cs b/CalCli/Connections/GoogleOAuthFormResponse.cs
new file mode 100644
index 0000000..1886648
--- /dev/null
+++ b/CalCli/Connections/GoogleOAuthFormResponse.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace CalCli.Connections
+{
+ public class GoogleOAuthFormResponse
+ {
+ public DialogResult DialogResult { get; set; }
+ public string Token { get; set; }
+ public string RefreshToken { get; set; }
+ public int ExpiresIn { get; set; }
+ }
+}
diff --git a/CalCli/Properties/AssemblyInfo.cs b/CalCli/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7b5f4b6
--- /dev/null
+++ b/CalCli/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CalCli")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CalCli")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dbefed7e-dc69-48c0-9ac3-428b2168a17a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/CalCli/UI/GoogleOAuthForm.Designer.cs b/CalCli/UI/GoogleOAuthForm.Designer.cs
new file mode 100644
index 0000000..686174d
--- /dev/null
+++ b/CalCli/UI/GoogleOAuthForm.Designer.cs
@@ -0,0 +1,74 @@
+namespace CalCli.UI
+{
+ partial class GoogleOAuthForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.webBrowser1 = new System.Windows.Forms.WebBrowser();
+ this.authWebBrowser = new System.Windows.Forms.WebBrowser();
+ this.SuspendLayout();
+ //
+ // webBrowser1
+ //
+ this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.webBrowser1.Location = new System.Drawing.Point(0, 0);
+ this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
+ this.webBrowser1.Name = "webBrowser1";
+ this.webBrowser1.Size = new System.Drawing.Size(872, 499);
+ this.webBrowser1.TabIndex = 0;
+ //
+ // authWebBrowser
+ //
+ this.authWebBrowser.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.authWebBrowser.Location = new System.Drawing.Point(0, 0);
+ this.authWebBrowser.MinimumSize = new System.Drawing.Size(20, 20);
+ this.authWebBrowser.Name = "authWebBrowser";
+ this.authWebBrowser.Size = new System.Drawing.Size(872, 499);
+ this.authWebBrowser.TabIndex = 1;
+ this.authWebBrowser.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.authWebBrowser_DocumentCompleted);
+ //
+ // GoogleOAuthForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(872, 499);
+ this.Controls.Add(this.authWebBrowser);
+ this.Controls.Add(this.webBrowser1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Name = "GoogleOAuthForm";
+ this.Text = "Google Authentication";
+ this.Load += new System.EventHandler(this.GoogleOAuthForm_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.WebBrowser webBrowser1;
+ private System.Windows.Forms.WebBrowser authWebBrowser;
+ }
+}
\ No newline at end of file
diff --git a/CalCli/UI/GoogleOAuthForm.cs b/CalCli/UI/GoogleOAuthForm.cs
new file mode 100644
index 0000000..5146d66
--- /dev/null
+++ b/CalCli/UI/GoogleOAuthForm.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Net;
+using System.IO;
+using Newtonsoft.Json.Linq;
+using CalCli.Connections;
+
+namespace CalCli.UI
+{
+ public partial class GoogleOAuthForm : Form
+ {
+ public GoogleOAuthFormResponse Result { get; set; }
+
+ public GoogleOAuthForm()
+ {
+ InitializeComponent();
+ }
+
+ private void GoogleOAuthForm_Load(object sender, EventArgs e)
+ {
+ authWebBrowser.Navigate("https://accounts.google.com/o/oauth2/auth?response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto&" +
+ "client_id=562771573604-thtg508t2k88730qveaalj8fuq43iuki.apps.googleusercontent.com&" +
+ "scope=https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.readonly");
+ }
+
+ private void authWebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
+ {
+ if (authWebBrowser.DocumentTitle.Contains("code="))
+ {
+ getToken(extractCode(authWebBrowser.DocumentTitle));
+ }
+ }
+
+ private void getToken(object code)
+ {
+ WebRequest request = HttpWebRequest.Create("https://accounts.google.com/o/oauth2/token");
+
+ string postData = "code="+code+"&" +
+ "client_id=562771573604-thtg508t2k88730qveaalj8fuq43iuki.apps.googleusercontent.com&" +
+ "client_secret=LpgRRdGGqrHDr7KIG-FA604x&" +
+ "redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto&" +
+ "grant_type=authorization_code";
+
+ var data = Encoding.ASCII.GetBytes(postData);
+
+ request.Method = "POST";
+ request.ContentType = "application/x-www-form-urlencoded";
+ request.ContentLength = data.Length;
+
+ using (var stream = request.GetRequestStream())
+ {
+ stream.Write(data, 0, data.Length);
+ }
+
+ string response = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
+
+ Result = new GoogleOAuthFormResponse()
+ {
+ DialogResult = DialogResult.OK,
+ Token = extractToken(response),
+ RefreshToken = extractRefreshToken(response),
+ ExpiresIn = extractExpiresIn(response)
+ };
+ Close();
+ }
+
+ private int extractExpiresIn(string response)
+ {
+ return Convert.ToInt32(extractJsonParameter("expires_in", response));
+ }
+
+ private string extractRefreshToken(string response)
+ {
+ return extractJsonParameter("refresh_token", response);
+ }
+
+ private string extractToken(string response)
+ {
+ return extractJsonParameter("access_token", response);
+ }
+
+ private string extractJsonParameter(string key, string json)
+ {
+ JObject o = JObject.Parse(json);
+ return o.GetValue(key).ToString() ;
+ }
+
+ private object extractCode(string documentTitle)
+ {
+ return documentTitle.Substring(documentTitle.IndexOf("code=") + 5);
+ }
+ }
+}
diff --git a/CalCli/UI/GoogleOAuthForm.resx b/CalCli/UI/GoogleOAuthForm.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/CalCli/UI/GoogleOAuthForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/CalCli/packages.config b/CalCli/packages.config
new file mode 100644
index 0000000..583acbd
--- /dev/null
+++ b/CalCli/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/CalDav.Client/CalDav.Client.csproj b/CalDav.Client/CalDav.Client.csproj
index 5b3b531..ca94863 100644
--- a/CalDav.Client/CalDav.Client.csproj
+++ b/CalDav.Client/CalDav.Client.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -9,10 +9,11 @@
Properties
CalDav.Client
CalDav.Client
- v4.5
+ v4.8
512
..\
true
+
true
@@ -47,6 +48,10 @@
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
{01a4c4cf-5ad1-4324-a391-dc922c84be1c}
CalDav
diff --git a/CalDav.Client/Calendar.cs b/CalDav.Client/Calendar.cs
index 99d95db..e13dd7f 100644
--- a/CalDav.Client/Calendar.cs
+++ b/CalDav.Client/Calendar.cs
@@ -3,16 +3,31 @@
using System.Linq;
using System.Net;
using System.Xml.Linq;
+using CalCli.API;
namespace CalDav.Client {
- public class Calendar {
+ public class Calendar : ICalendar {
public Uri Url { get; set; }
public NetworkCredential Credentials { get; set; }
public string Name { get; set; }
public string Description { get; set; }
-
- public void Initialize() {
- var result = Common.Request(Url, "PROPFIND", CalDav.Common.xDav.Element("propfind",
+ public Common common { get; set; }
+
+ public Calendar(Common common)
+ {
+ this.common = common;
+ }
+
+ public Calendar(Common common, Uri Url)
+ {
+ this.Url = Url;
+ this.common = common;
+ Initialize();
+ }
+
+
+ public void Initialize() {
+ var result = common.Request(Url, "PROPFIND", CalDav.Common.xDav.Element("propfind",
CalDav.Common.xDav.Element("allprop")), Credentials, new Dictionary {
{ "Depth", 0 }
});
@@ -31,7 +46,7 @@ public void Initialize() {
}
public CalendarCollection Search(CalDav.CalendarQuery query) {
- var result = Common.Request(Url, "REPORT", (XElement)query, Credentials, new Dictionary {
+ var result = common.Request(Url, "REPORT", (XElement)query, Credentials, new Dictionary {
{ "Depth", 1 }
});
var xdoc = XDocument.Parse(result.Item2);
@@ -45,12 +60,17 @@ public CalendarCollection Search(CalDav.CalendarQuery query) {
}
public void Save(Event e) {
- if (string.IsNullOrEmpty(e.UID)) e.UID = Guid.NewGuid().ToString();
+ bool update = !string.IsNullOrEmpty(e.UID);
+
+ if (string.IsNullOrEmpty(e.UID)) e.UID = Guid.NewGuid().ToString();
e.LastModified = DateTime.UtcNow;
- var result = Common.Request(new Uri(Url, e.UID + ".ics"), "PUT", (req, str) => {
- req.Headers[System.Net.HttpRequestHeader.IfNoneMatch] = "*";
- req.ContentType = "text/calendar";
+ var result = common.Request(new Uri(Url,e.UID + ".ics"), "PUT", (req, str) => {
+ if (!update)
+ {
+ req.Headers[System.Net.HttpRequestHeader.IfNoneMatch] = "*";
+ }
+ req.ContentType = "text/calendar";
var calendar = new CalDav.Calendar();
e.Sequence = (e.Sequence ?? 0) + 1;
calendar.Events.Add(e);
@@ -63,9 +83,83 @@ public void Save(Event e) {
GetObject(e.UID);
}
-
- public CalendarCollection GetAll() {
- var result = Common.Request(Url, "PROPFIND", CalDav.Common.xCalDav.Element("calendar-multiget",
+ public void Delete(Event e)
+ {
+ bool update = !string.IsNullOrEmpty(e.UID);
+
+ if (string.IsNullOrEmpty(e.UID)) e.UID = Guid.NewGuid().ToString();
+ e.LastModified = DateTime.UtcNow;
+
+ var result = common.Request(new Uri(Url, e.UID + ".ics"), "DELETE", (req, str) => {
+ if (!update)
+ {
+ req.Headers[System.Net.HttpRequestHeader.IfNoneMatch] = "*";
+ }
+ req.ContentType = "text/calendar";
+ var calendar = new CalDav.Calendar();
+ e.Sequence = (e.Sequence ?? 0) + 1;
+ calendar.Events.Add(e);
+ Common.Serialize(str, calendar);
+
+ }, Credentials);
+ if (result.Item1 != System.Net.HttpStatusCode.Created && result.Item1 != HttpStatusCode.NoContent)
+ throw new Exception("Unable to save event: " + result.Item1);
+ e.Url = new Uri(Url, result.Item3[System.Net.HttpResponseHeader.Location]);
+
+ GetObject(e.UID);
+ }
+ public void Save(ToDo e)
+ {
+ bool update = !string.IsNullOrEmpty(e.UID);
+
+ if (string.IsNullOrEmpty(e.UID)) e.UID = Guid.NewGuid().ToString();
+ e.LastModified = DateTime.UtcNow;
+
+ var result = common.Request(new Uri(Url, e.UID + ".ics"), "PUT", (req, str) => {
+ if (!update)
+ {
+ req.Headers[System.Net.HttpRequestHeader.IfNoneMatch] = "*";
+ }
+ req.ContentType = "text/calendar";
+ var calendar = new CalDav.Calendar();
+ e.Sequence = (e.Sequence ?? 0) + 1;
+ calendar.ToDos.Add(e);
+ Common.Serialize(str, calendar);
+
+ }, Credentials);
+ if (result.Item1 != System.Net.HttpStatusCode.Created && result.Item1 != HttpStatusCode.NoContent)
+ throw new Exception("Unable to save event: " + result.Item1);
+ // e.Url = new Uri(Url, result.Item3[System.Net.HttpResponseHeader.Location]);
+
+ GetObject(e.UID);
+ }
+ public void Delete(ToDo e)
+ {
+ bool update = !string.IsNullOrEmpty(e.UID);
+
+ if (string.IsNullOrEmpty(e.UID)) e.UID = Guid.NewGuid().ToString();
+ e.LastModified = DateTime.UtcNow;
+
+ var result = common.Request(new Uri(Url, e.UID + ".ics"), "DELETE", (req, str) => {
+ if (!update)
+ {
+ req.Headers[System.Net.HttpRequestHeader.IfNoneMatch] = "*";
+ }
+ req.ContentType = "text/calendar";
+ var calendar = new CalDav.Calendar();
+ e.Sequence = (e.Sequence ?? 0) + 1;
+ calendar.ToDos.Add(e);
+ Common.Serialize(str, calendar);
+
+ }, Credentials);
+ if (result.Item1 != System.Net.HttpStatusCode.Created && result.Item1 != HttpStatusCode.NoContent)
+ throw new Exception("Unable to save event: " + result.Item1);
+ // e.Url = new Uri(Url, result.Item3[System.Net.HttpResponseHeader.Location]);
+
+ GetObject(e.UID);
+ }
+ public CalendarCollection GetAll() {
+ var result = common.Request(Url, "REPORT", CalDav.Common.xCalDav.Element("calendar-multiget",
CalDav.Common.xDav.Element("prop",
CalDav.Common.xDav.Element("getetag"),
CalDav.Common.xCalDav.Element("calendar-data")
@@ -79,7 +173,7 @@ public CalendarCollection GetAll() {
}
public CalendarCollection GetObject(string uid) {
- var result = Common.Request(Url, "REPORT", CalDav.Common.xCalDav.Element("calendar-multiget",
+ var result = common.Request(Url, "REPORT", CalDav.Common.xCalDav.Element("calendar-multiget",
CalDav.Common.xDav.Element("prop",
CalDav.Common.xDav.Element("getetag"),
CalDav.Common.xCalDav.Element("calendar-data")
@@ -91,5 +185,48 @@ public CalendarCollection GetObject(string uid) {
return null;
}
- }
+
+ public void Save(IEvent e)
+ {
+ Event ev = (Event)e;
+ Save(ev);
+ }
+ public void Delete(IEvent e)
+ {
+ Event ev = (Event)e;
+ Delete(ev);
+ }
+
+ public void Save(IToDo t)
+ {
+ ToDo todo = (ToDo)t;
+ Save(todo);
+ }
+ public void Delete(IToDo t)
+ {
+ ToDo todo = (ToDo)t;
+ Delete(todo);
+ }
+
+ public IToDo createToDo()
+ {
+ CalDav.ToDo todo = new CalDav.ToDo();
+ return todo;
+ }
+
+ public ITrigger createTrigger()
+ {
+ return new Trigger();
+ }
+
+ public IAlarm createAlarm()
+ {
+ return new Alarm();
+ }
+
+ public IEvent createEvent()
+ {
+ return new CalDav.Event();
+ }
+ }
}
diff --git a/CalDav.Client/Common.cs b/CalDav.Client/Common.cs
index f2af237..53261a7 100644
--- a/CalDav.Client/Common.cs
+++ b/CalDav.Client/Common.cs
@@ -1,23 +1,30 @@
using System;
using System.Net;
using System.Xml.Linq;
+using CalCli.API;
namespace CalDav.Client {
- internal static class Common {
+ public class Common {
+ private IConnection connection;
- public static Tuple Request(Uri url, string method, XDocument content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
+ public Common(IConnection connection)
+ {
+ this.connection = connection;
+ }
+
+ public Tuple Request(Uri url, string method, XDocument content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
return Request(url, method, content.Root, credentials, headers);
}
- public static Tuple Request(Uri url, string method, XElement content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
+ public Tuple Request(Uri url, string method, XElement content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
return Request(url, method, (req, str) => {
req.ContentType = "text/xml";
- var xml = content.ToString();
- using (var wrtr = new System.IO.StreamWriter(str))
+ var xml = content.ToString();
+ using (var wrtr = new System.IO.StreamWriter(str))
wrtr.Write(xml);
}, credentials, headers);
}
- public static Tuple Request(Uri url, string method, string contentType, string content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
+ public Tuple Request(Uri url, string method, string contentType, string content, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
return Request(url, method, (req, str) => {
req.ContentType = contentType;
using (var wrtr = new System.IO.StreamWriter(str))
@@ -25,8 +32,9 @@ internal static class Common {
}, credentials, headers);
}
- public static Tuple Request(Uri url, string method = "GET", Action content = null, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
+ public Tuple Request(Uri url, string method = "GET", Action content = null, NetworkCredential credentials = null, System.Collections.Generic.Dictionary headers = null) {
var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
+ req = (System.Net.HttpWebRequest)connection.Authorize(req);
req.Method = method.ToUpper();
//Dear .NET, please don't try to do things for me. kthxbai
@@ -40,13 +48,13 @@ internal static class Common {
else req.Headers[header.Key] = value;
}
- if (credentials != null) {
- //req.Credentials = credentials;
- var b64 = credentials.UserName + ":" + credentials.Password;
- b64 = System.Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(b64));
- req.Headers[HttpRequestHeader.Authorization] = "Basic " + b64;
- }
-
+ //if (credentials != null) {
+ // //req.Credentials = credentials;
+ // var b64 = credentials.UserName + ":" + credentials.Password;
+ // b64 = System.Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(b64));
+ // req.Headers[HttpRequestHeader.Authorization] = "Basic " + b64;
+ //}
+ connection.Authorize(req);
using (var stream = req.GetRequestStream()) {
if (content != null) {
content(req, stream);
@@ -60,7 +68,7 @@ internal static class Common {
}
}
- private static System.Net.HttpWebResponse GetResponse(System.Net.HttpWebRequest req) {
+ private System.Net.HttpWebResponse GetResponse(System.Net.HttpWebRequest req) {
try {
return (System.Net.HttpWebResponse)req.GetResponse();
} catch (System.Net.WebException wex) {
@@ -75,6 +83,21 @@ public static void Serialize(System.IO.Stream stream, Event e, System.Text.Encod
}
public static void Serialize(System.IO.Stream stream, CalDav.Calendar ical, System.Text.Encoding encoding = null) {
+ //System.IO.StreamWriter sr = new System.IO.StreamWriter(stream);
+ //sr.WriteLine("BEGIN: VCALENDAR");
+ //sr.WriteLine("VERSION:2.0");
+ //sr.WriteLine("PRODID: CalCli");
+ //sr.WriteLine("BEGIN:VEVENT");
+ //var enumer = ical.Events.GetEnumerator();
+ //enumer.MoveNext();
+ //sr.WriteLine("UID:"+enumer.Current.UID);
+ //sr.WriteLine("DTSTAMP:20060712T182145Z");
+ //sr.WriteLine("DTSTART:20060714T170000Z");
+ //sr.WriteLine("DTEND:20060715T040000Z");
+ //sr.WriteLine("SUMMARY:Bastille Day Party");
+ //sr.WriteLine("END:VEVENT");
+ //sr.WriteLine("END:VCALENDAR");
+ //return
var serializer = new CalDav.Serializer();
serializer.Serialize(stream, ical, encoding);
}
diff --git a/CalDav.Client/Server.cs b/CalDav.Client/Server.cs
index 7e89355..7b2541e 100644
--- a/CalDav.Client/Server.cs
+++ b/CalDav.Client/Server.cs
@@ -2,25 +2,74 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
+using CalDav.Client;
+using CalCli.API;
namespace CalDav.Client {
- public class Server {
+ public class Server : IServer {
+ private Common Common;
+ private IConnection connection;
public Uri Url { get; set; }
public System.Net.NetworkCredential Credentials { get; set; }
- public Server(string url, string username = null, string password = null)
- : this(new Uri(url), username, password) { }
+ public Server(string url, IConnection connection, string username = null, string password = null)
+ : this(new Uri(url), connection, username, password) { }
- private HashSet _Options;
+ private HashSet _Options;
+ // private string v;
+ // private IConnection connection;
- public Server(Uri url, string username = null, string password = null) {
- Url = url;
+ public Server(Uri url, IConnection connection, string username = null, string password = null) {
+ this.connection = connection;
+ Common = new Common(connection);
+ Url = url;
if (username != null && password != null) {
Credentials = new System.Net.NetworkCredential(username, password);
}
_Options = GetOptions();
+ completeUrl();
}
- public HashSet Options {
+ private void completeUrl()
+ {
+ var xcollectionset = CalDav.Common.xDav.GetName("current-user-principal");
+ var result = Common.Request(Url, "propfind", new XDocument(
+ new XElement(CalDav.Common.xDav.GetName("propfind"),
+ new XElement(CalDav.Common.xDav.GetName("prop"),
+ new XElement(xcollectionset)
+ )
+
+ )
+ ), Credentials, new System.Collections.Generic.Dictionary { { "Depth", 0 } });
+
+ var xdoc = XDocument.Parse(result.Item2);
+ Uri userprincipal = Url;
+ foreach(XNode node in xdoc.Descendants(xcollectionset))
+ {
+ foreach (XElement href in xdoc.Descendants(CalDav.Common.xDav.GetName("href")))
+ {
+ if (href.Parent == node)
+ {
+ userprincipal = new Uri(Url, href.Value);
+ }
+ }
+ }
+ // get homeset
+ xcollectionset = CalDav.Common.xCalDav.GetName("calendar-home-set");
+ result = Common.Request(userprincipal, "propfind", new XDocument(
+ new XElement(CalDav.Common.xDav.GetName("propfind"),
+ new XElement(CalDav.Common.xDav.GetName("prop"),
+ new XElement(xcollectionset)
+ )
+
+ )
+ ), Credentials, new System.Collections.Generic.Dictionary { { "Depth", 0 } });
+
+ xdoc = XDocument.Parse(result.Item2);
+ var hrefs = xdoc.Descendants(xcollectionset).SelectMany(x => x.Descendants(CalDav.Common.xDav.GetName("href")));
+ Url = new Uri(Url, hrefs.First().Value);
+ }
+
+ public HashSet Options {
get {
if (_Options == null)
lock (this)
@@ -30,7 +79,21 @@ public HashSet Options {
}
}
- private HashSet GetOptions() {
+ public IConnection Connection
+ {
+ get
+ {
+ return connection;
+ }
+
+ set
+ {
+ connection = value;
+ Common = new Common(connection);
+ }
+ }
+
+ private HashSet GetOptions() {
var result = Common.Request(Url, "options", credentials: Credentials);
if (result.Item3["WWW-Authenticate"] != null)
throw new Exception("Authentication is required");
@@ -49,26 +112,50 @@ public void CreateCalendar(string name) {
}
public Calendar[] GetCalendars() {
- var xcollectionset = CalDav.Common.xCalDav.GetName("calendar-collection-set");
- var result = Common.Request(Url, "propfind", new XDocument(
- new XElement(CalDav.Common.xDav.GetName("options"),
- new XElement(xcollectionset)
- )
- ), Credentials, new System.Collections.Generic.Dictionary { { "Depth", 0 } });
-
- if (string.IsNullOrEmpty(result.Item2))
+ var xcollectionset = CalDav.Common.xCalDav.GetName("calendar-home-set");
+ var result = Common.Request(Url, "propfind", new XDocument(
+ new XElement(CalDav.Common.xDav.GetName("propfind"),
+ new XElement(CalDav.Common.xDav.GetName("allprop")//,
+ //new XElement(xcollectionset)
+ )
+
+ )
+ ), Credentials, new System.Collections.Generic.Dictionary { { "Depth", 1 } });
+
+ if (string.IsNullOrEmpty(result.Item2))
return new[]{
- new Calendar { Url = Url, Credentials = Credentials }
+ new Calendar(Common) { Url = Url, Credentials = Credentials }
};
var xdoc = XDocument.Parse(result.Item2);
- var hrefs = xdoc.Descendants(xcollectionset).SelectMany(x => x.Descendants(CalDav.Common.xDav.GetName("href")));
- return hrefs.Select(x => new Calendar { Url = new Uri(Url, x.Value), Credentials = Credentials }).ToArray();
+ var responses = xdoc.Descendants(CalDav.Common.xDav.GetName("response"));
+ List calendars = new List();
+ // var hrefs = xdoc.Descendants(CalDav.Common.xDav.GetName("href"));
+ foreach(XElement response in responses)
+ {
+ if(response.Descendants(CalDav.Common.xCalDav.GetName("calendar")).Count() > 0)
+ {
+ string href = response.Descendants(CalDav.Common.xDav.GetName("href")).First().Value;
+ calendars.Add(new Calendar(Common, new Uri(Url, href)) { Credentials = Credentials });
+ }
+ }
+ return calendars.ToArray();
}
public bool Supports(string option) {
return Options.Contains(option);
}
- }
+
+ ICalendar[] IServer.GetCalendars()
+ {
+ return GetCalendars();
+ }
+
+ public void CreateCalendar(ICalendar calendar)
+ {
+ Calendar cal = (Calendar)calendar;
+ CreateCalendar(cal.Name);
+ }
+ }
}
diff --git a/CalDav.Server/CalDav.Server.csproj b/CalDav.Server/CalDav.Server.csproj
index 76140e4..bab9108 100644
--- a/CalDav.Server/CalDav.Server.csproj
+++ b/CalDav.Server/CalDav.Server.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -9,7 +9,7 @@
Properties
CalDav.Server
CalDav.Server
- v4.0
+ v4.8
512
..\
true
@@ -23,6 +23,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -31,12 +32,33 @@
TRACE
prompt
4
+ false
+
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
-
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll
+
+
+ ..\packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll
+
+
+ ..\packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll
+
@@ -49,6 +71,10 @@
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
{01a4c4cf-5ad1-4324-a391-dc922c84be1c}
CalDav
@@ -58,6 +84,7 @@
Designer
+
diff --git a/CalDav.Server/Controllers/CalDavController.cs b/CalDav.Server/Controllers/CalDavController.cs
index 7481558..cf04704 100644
--- a/CalDav.Server/Controllers/CalDavController.cs
+++ b/CalDav.Server/Controllers/CalDavController.cs
@@ -6,6 +6,8 @@
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;
+using CalDavController = CalDav.Server.Controllers.CalDavController;
+
//http://greenbytes.de/tech/webdav/draft-dusseault-caldav-05.html
//http://wwcsd.net/principals/__uids__/wiki-ilovemysmartboard/
diff --git a/CalDav.Server/Properties/AssemblyInfo.cs b/CalDav.Server/Properties/AssemblyInfo.cs
index e58bb7b..75b1bfd 100644
--- a/CalDav.Server/Properties/AssemblyInfo.cs
+++ b/CalDav.Server/Properties/AssemblyInfo.cs
@@ -32,4 +32,5 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.0.1.0")]
-[assembly: AssemblyFileVersion("0.0.1-beta3")]
+//[assembly: AssemblyFileVersion("0.0.1-beta3")]
+[assembly: AssemblyFileVersion("0.0.1")]
diff --git a/CalDav.Server/packages.config b/CalDav.Server/packages.config
new file mode 100644
index 0000000..f5288df
--- /dev/null
+++ b/CalDav.Server/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CalDav.sln b/CalDav.sln
index 2cf0eb5..89639cb 100644
--- a/CalDav.sln
+++ b/CalDav.sln
@@ -1,6 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9A2D1E8A-0F23-4431-8FAD-113F12F2AD96}"
+ ProjectSection(SolutionItems) = preProject
+ .nuget\NuGet.Config = .nuget\NuGet.Config
+ .nuget\NuGet.exe = .nuget\NuGet.exe
+ .nuget\NuGet.targets = .nuget\NuGet.targets
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0374EF10-4265-4EEC-8608-94D0561FBF7F}"
+ ProjectSection(SolutionItems) = preProject
+ Create-Package.ps1 = Create-Package.ps1
+ EndProjectSection
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "Console\Console.csproj", "{EE946C60-392B-4A4F-B0A5-9D9A32C283DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{FABD2E1F-315B-4DCB-8DDA-FDE9263F99E1}"
@@ -9,23 +23,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalDav", "CalDav\CalDav.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalDav.Client", "CalDav.Client\CalDav.Client.csproj", "{1B9B42A0-A34B-4BF6-A5D5-21C46ED0D9B3}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9A2D1E8A-0F23-4431-8FAD-113F12F2AD96}"
- ProjectSection(SolutionItems) = preProject
- .nuget\NuGet.Config = .nuget\NuGet.Config
- .nuget\NuGet.exe = .nuget\NuGet.exe
- .nuget\NuGet.targets = .nuget\NuGet.targets
- EndProjectSection
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.WPF", "Demo.WPF\Demo.WPF.csproj", "{69BD41BC-3945-4C33-8A07-A0BD6DD9B160}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalDav.Server", "CalDav.Server\CalDav.Server.csproj", "{471EA68F-FB1F-4DF8-AAC1-31022C7316AB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.MVC", "Demo.MVC\Demo.MVC.csproj", "{9164611E-4CAF-4FE1-B707-397CC1D515C0}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0374EF10-4265-4EEC-8608-94D0561FBF7F}"
- ProjectSection(SolutionItems) = preProject
- Create-Package.ps1 = Create-Package.ps1
- EndProjectSection
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalCli", "CalCli\CalCli.csproj", "{DBEFED7E-DC69-48C0-9AC3-428B2168A17A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.CalCli", "Demo.CalCli\Demo.CalCli.csproj", "{4ED47A68-871A-4069-8B20-1D3D7AD163E6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalCli.API", "CalCli.API\CalCli.API.csproj", "{2C258FAE-97ED-4916-B5A3-4723700D675D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OutlookClient", "OutlookClient\OutlookClient.csproj", "{01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalCli.Util", "CalCli.Util\CalCli.Util.csproj", "{00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -61,8 +73,31 @@ Global
{9164611E-4CAF-4FE1-B707-397CC1D515C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9164611E-4CAF-4FE1-B707-397CC1D515C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9164611E-4CAF-4FE1-B707-397CC1D515C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DBEFED7E-DC69-48C0-9AC3-428B2168A17A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DBEFED7E-DC69-48C0-9AC3-428B2168A17A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DBEFED7E-DC69-48C0-9AC3-428B2168A17A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DBEFED7E-DC69-48C0-9AC3-428B2168A17A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4ED47A68-871A-4069-8B20-1D3D7AD163E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4ED47A68-871A-4069-8B20-1D3D7AD163E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4ED47A68-871A-4069-8B20-1D3D7AD163E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4ED47A68-871A-4069-8B20-1D3D7AD163E6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2C258FAE-97ED-4916-B5A3-4723700D675D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2C258FAE-97ED-4916-B5A3-4723700D675D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2C258FAE-97ED-4916-B5A3-4723700D675D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2C258FAE-97ED-4916-B5A3-4723700D675D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00B20F5C-EE2C-4A3D-9BB6-EA426A02C985}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {BC555101-0410-4588-8E6F-9CCA0D48DD4C}
+ EndGlobalSection
EndGlobal
diff --git a/CalDav/Alarm.cs b/CalDav/Alarm.cs
index bc3b6cd..3f5f32b 100644
--- a/CalDav/Alarm.cs
+++ b/CalDav/Alarm.cs
@@ -1,22 +1,62 @@
-
+using System;
+using CalCli.API;
namespace CalDav {
- public class Alarm : ISerializeToICAL {
- public string Action { get; set; }
+ public class Alarm : ISerializeToICAL, IAlarm {
+ public AlarmActions Action { get; set; }
public string Description { get; set; }
- public Trigger Trigger { get; set; }
+ public Trigger CalDavTrigger { get; set; }
+
+ public ITrigger Trigger
+ {
+ get
+ {
+ return CalDavTrigger;
+ }
+ }
+
+ ITrigger IAlarm.Trigger
+ {
+ get
+ {
+ return CalDavTrigger;
+ }
+
+ set
+ {
+ CalDavTrigger = (CalDav.Trigger)value;
+ }
+ }
public void Deserialize(System.IO.TextReader rdr, Serializer serializer) {
string name, value;
var parameters = new System.Collections.Specialized.NameValueCollection();
while (rdr.Property(out name, out value, parameters) && !string.IsNullOrEmpty(name)) {
switch (name) {
- case "ACTION": Action = value; break;
+ case "ACTION": Action = getAlarmActions(value); break;
case "DESCRIPTION": Description = value; break;
- case "TRIGGER": Trigger = serializer.GetService(); Trigger.Deserialize(value, parameters); break;
+ case "TRIGGER": CalDavTrigger = serializer.GetService(); CalDavTrigger.Deserialize(value, parameters); break;
+ case "END": return;
}
}
}
+ private AlarmActions getAlarmActions(string value)
+ {
+ switch(value)
+ {
+ case "EMAIL":
+ return AlarmActions.EMAIL;
+ case "AUDIO":
+ return AlarmActions.AUDIO;
+ case "DISPLAY":
+ return AlarmActions.DISPLAY;
+ case "NONE":
+ return AlarmActions.NONE;
+ default:
+ throw new Exception("Action is not valid for alarm.");
+ }
+ }
+
public void Serialize(System.IO.TextWriter wrtr) {
wrtr.BeginBlock("VALARM");
wrtr.Property("ACTION", Action);
diff --git a/CalDav/CalDav.csproj b/CalDav/CalDav.csproj
index daef403..69ea8fa 100644
--- a/CalDav/CalDav.csproj
+++ b/CalDav/CalDav.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -9,7 +9,7 @@
Properties
CalDav
CalDav
- v4.0
+ v4.8
512
..\
true
@@ -23,6 +23,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -31,6 +32,7 @@
TRACE
prompt
4
+ false
@@ -61,7 +63,6 @@
-
@@ -71,6 +72,12 @@
Designer
+
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
+
+
\ No newline at end of file
diff --git a/Demo.CalCli/Main.Designer.cs b/Demo.CalCli/Main.Designer.cs
new file mode 100644
index 0000000..f11fdcd
--- /dev/null
+++ b/Demo.CalCli/Main.Designer.cs
@@ -0,0 +1,365 @@
+namespace Demo.CalCli
+{
+ partial class Main
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.authButton = new System.Windows.Forms.Button();
+ this.createEventButton = new System.Windows.Forms.Button();
+ this.eventStartPicker = new System.Windows.Forms.DateTimePicker();
+ this.eventEndPicker = new System.Windows.Forms.DateTimePicker();
+ this.eventSummaryTextBox = new System.Windows.Forms.TextBox();
+ this.eventDescriptionTextBox = new System.Windows.Forms.TextBox();
+ this.summaryLabel = new System.Windows.Forms.Label();
+ this.descriptionLabel = new System.Windows.Forms.Label();
+ this.startLabel = new System.Windows.Forms.Label();
+ this.eventGroupBox = new System.Windows.Forms.GroupBox();
+ this.button1 = new System.Windows.Forms.Button();
+ this.connectionGroupBox = new System.Windows.Forms.GroupBox();
+ this.comboBox1 = new System.Windows.Forms.ComboBox();
+ this.calidLabel = new System.Windows.Forms.Label();
+ this.pswdLabel = new System.Windows.Forms.Label();
+ this.passwordTextBox = new System.Windows.Forms.TextBox();
+ this.usernameLabel = new System.Windows.Forms.Label();
+ this.usernameTextBox = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.urlCombo = new System.Windows.Forms.ComboBox();
+ this.checkList = new System.Windows.Forms.CheckedListBox();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.button2 = new System.Windows.Forms.Button();
+ this.comboBox2 = new System.Windows.Forms.ComboBox();
+ this.button3 = new System.Windows.Forms.Button();
+ this.eventGroupBox.SuspendLayout();
+ this.connectionGroupBox.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // authButton
+ //
+ this.authButton.Location = new System.Drawing.Point(64, 134);
+ this.authButton.Name = "authButton";
+ this.authButton.Size = new System.Drawing.Size(104, 23);
+ this.authButton.TabIndex = 0;
+ this.authButton.Text = "Connect";
+ this.authButton.UseVisualStyleBackColor = true;
+ this.authButton.Click += new System.EventHandler(this.testButton_Click);
+ //
+ // createEventButton
+ //
+ this.createEventButton.Location = new System.Drawing.Point(82, 134);
+ this.createEventButton.Name = "createEventButton";
+ this.createEventButton.Size = new System.Drawing.Size(102, 23);
+ this.createEventButton.TabIndex = 1;
+ this.createEventButton.Text = "Create Event";
+ this.createEventButton.UseVisualStyleBackColor = true;
+ this.createEventButton.Click += new System.EventHandler(this.createEventButton_Click);
+ //
+ // eventStartPicker
+ //
+ this.eventStartPicker.Format = System.Windows.Forms.DateTimePickerFormat.Time;
+ this.eventStartPicker.Location = new System.Drawing.Point(82, 23);
+ this.eventStartPicker.Name = "eventStartPicker";
+ this.eventStartPicker.Size = new System.Drawing.Size(102, 20);
+ this.eventStartPicker.TabIndex = 2;
+ //
+ // eventEndPicker
+ //
+ this.eventEndPicker.Format = System.Windows.Forms.DateTimePickerFormat.Time;
+ this.eventEndPicker.Location = new System.Drawing.Point(190, 23);
+ this.eventEndPicker.Name = "eventEndPicker";
+ this.eventEndPicker.Size = new System.Drawing.Size(102, 20);
+ this.eventEndPicker.TabIndex = 3;
+ //
+ // eventSummaryTextBox
+ //
+ this.eventSummaryTextBox.Location = new System.Drawing.Point(82, 52);
+ this.eventSummaryTextBox.Name = "eventSummaryTextBox";
+ this.eventSummaryTextBox.Size = new System.Drawing.Size(210, 20);
+ this.eventSummaryTextBox.TabIndex = 4;
+ //
+ // eventDescriptionTextBox
+ //
+ this.eventDescriptionTextBox.Location = new System.Drawing.Point(82, 78);
+ this.eventDescriptionTextBox.Multiline = true;
+ this.eventDescriptionTextBox.Name = "eventDescriptionTextBox";
+ this.eventDescriptionTextBox.Size = new System.Drawing.Size(210, 50);
+ this.eventDescriptionTextBox.TabIndex = 5;
+ //
+ // summaryLabel
+ //
+ this.summaryLabel.AutoSize = true;
+ this.summaryLabel.Location = new System.Drawing.Point(28, 55);
+ this.summaryLabel.Name = "summaryLabel";
+ this.summaryLabel.Size = new System.Drawing.Size(50, 13);
+ this.summaryLabel.TabIndex = 6;
+ this.summaryLabel.Text = "Summary";
+ //
+ // descriptionLabel
+ //
+ this.descriptionLabel.AutoSize = true;
+ this.descriptionLabel.Location = new System.Drawing.Point(18, 81);
+ this.descriptionLabel.Name = "descriptionLabel";
+ this.descriptionLabel.Size = new System.Drawing.Size(60, 13);
+ this.descriptionLabel.TabIndex = 7;
+ this.descriptionLabel.Text = "Description";
+ //
+ // startLabel
+ //
+ this.startLabel.AutoSize = true;
+ this.startLabel.Location = new System.Drawing.Point(44, 27);
+ this.startLabel.Name = "startLabel";
+ this.startLabel.Size = new System.Drawing.Size(30, 13);
+ this.startLabel.TabIndex = 8;
+ this.startLabel.Text = "Time";
+ //
+ // eventGroupBox
+ //
+ this.eventGroupBox.Controls.Add(this.button1);
+ this.eventGroupBox.Controls.Add(this.eventDescriptionTextBox);
+ this.eventGroupBox.Controls.Add(this.createEventButton);
+ this.eventGroupBox.Controls.Add(this.startLabel);
+ this.eventGroupBox.Controls.Add(this.eventStartPicker);
+ this.eventGroupBox.Controls.Add(this.descriptionLabel);
+ this.eventGroupBox.Controls.Add(this.eventEndPicker);
+ this.eventGroupBox.Controls.Add(this.summaryLabel);
+ this.eventGroupBox.Controls.Add(this.eventSummaryTextBox);
+ this.eventGroupBox.Location = new System.Drawing.Point(270, 185);
+ this.eventGroupBox.Name = "eventGroupBox";
+ this.eventGroupBox.Size = new System.Drawing.Size(301, 167);
+ this.eventGroupBox.TabIndex = 10;
+ this.eventGroupBox.TabStop = false;
+ this.eventGroupBox.Text = "Event";
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(190, 134);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(102, 23);
+ this.button1.TabIndex = 9;
+ this.button1.Text = "Create ToDo";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click_1);
+ //
+ // connectionGroupBox
+ //
+ this.connectionGroupBox.Controls.Add(this.button3);
+ this.connectionGroupBox.Controls.Add(this.comboBox2);
+ this.connectionGroupBox.Controls.Add(this.comboBox1);
+ this.connectionGroupBox.Controls.Add(this.calidLabel);
+ this.connectionGroupBox.Controls.Add(this.pswdLabel);
+ this.connectionGroupBox.Controls.Add(this.passwordTextBox);
+ this.connectionGroupBox.Controls.Add(this.authButton);
+ this.connectionGroupBox.Controls.Add(this.usernameLabel);
+ this.connectionGroupBox.Controls.Add(this.usernameTextBox);
+ this.connectionGroupBox.Controls.Add(this.label1);
+ this.connectionGroupBox.Controls.Add(this.urlCombo);
+ this.connectionGroupBox.Location = new System.Drawing.Point(12, 12);
+ this.connectionGroupBox.Name = "connectionGroupBox";
+ this.connectionGroupBox.Size = new System.Drawing.Size(559, 167);
+ this.connectionGroupBox.TabIndex = 11;
+ this.connectionGroupBox.TabStop = false;
+ this.connectionGroupBox.Text = "Connection";
+ //
+ // comboBox1
+ //
+ this.comboBox1.FormattingEnabled = true;
+ this.comboBox1.Location = new System.Drawing.Point(64, 55);
+ this.comboBox1.Name = "comboBox1";
+ this.comboBox1.Size = new System.Drawing.Size(486, 21);
+ this.comboBox1.TabIndex = 22;
+ //
+ // calidLabel
+ //
+ this.calidLabel.AutoSize = true;
+ this.calidLabel.Location = new System.Drawing.Point(27, 59);
+ this.calidLabel.Name = "calidLabel";
+ this.calidLabel.Size = new System.Drawing.Size(31, 13);
+ this.calidLabel.TabIndex = 19;
+ this.calidLabel.Text = "CalId";
+ //
+ // pswdLabel
+ //
+ this.pswdLabel.AutoSize = true;
+ this.pswdLabel.Location = new System.Drawing.Point(6, 111);
+ this.pswdLabel.Name = "pswdLabel";
+ this.pswdLabel.Size = new System.Drawing.Size(53, 13);
+ this.pswdLabel.TabIndex = 17;
+ this.pswdLabel.Text = "Password";
+ //
+ // passwordTextBox
+ //
+ this.passwordTextBox.Location = new System.Drawing.Point(64, 108);
+ this.passwordTextBox.Name = "passwordTextBox";
+ this.passwordTextBox.Size = new System.Drawing.Size(486, 20);
+ this.passwordTextBox.TabIndex = 16;
+ this.passwordTextBox.Text = "Aliasgarikh20";
+ this.passwordTextBox.UseSystemPasswordChar = true;
+ //
+ // usernameLabel
+ //
+ this.usernameLabel.AutoSize = true;
+ this.usernameLabel.Location = new System.Drawing.Point(6, 85);
+ this.usernameLabel.Name = "usernameLabel";
+ this.usernameLabel.Size = new System.Drawing.Size(55, 13);
+ this.usernameLabel.TabIndex = 15;
+ this.usernameLabel.Text = "Username";
+ //
+ // usernameTextBox
+ //
+ this.usernameTextBox.Location = new System.Drawing.Point(64, 82);
+ this.usernameTextBox.Name = "usernameTextBox";
+ this.usernameTextBox.Size = new System.Drawing.Size(486, 20);
+ this.usernameTextBox.TabIndex = 14;
+ this.usernameTextBox.Text = "aliasgarikh@icloud.com";
+ this.usernameTextBox.TextChanged += new System.EventHandler(this.usernameTextBox_TextChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(38, 33);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(20, 13);
+ this.label1.TabIndex = 13;
+ this.label1.Text = "Url";
+ //
+ // urlCombo
+ //
+ this.urlCombo.FormattingEnabled = true;
+ this.urlCombo.Items.AddRange(new object[] {
+ "https://caldav.icloud.com/",
+ "https://apidata.googleusercontent.com/caldav/v2/",
+ "https://caldav.calendar.yahoo.com/dav/",
+ "Outlook"});
+ this.urlCombo.Location = new System.Drawing.Point(64, 29);
+ this.urlCombo.Name = "urlCombo";
+ this.urlCombo.Size = new System.Drawing.Size(486, 21);
+ this.urlCombo.TabIndex = 12;
+ this.urlCombo.Text = "https://caldav.icloud.com/";
+ //
+ // checkList
+ //
+ this.checkList.FormattingEnabled = true;
+ this.checkList.Location = new System.Drawing.Point(9, 34);
+ this.checkList.Name = "checkList";
+ this.checkList.Size = new System.Drawing.Size(237, 94);
+ this.checkList.TabIndex = 12;
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.button2);
+ this.groupBox1.Controls.Add(this.checkList);
+ this.groupBox1.Location = new System.Drawing.Point(12, 185);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(252, 167);
+ this.groupBox1.TabIndex = 13;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "ToDos";
+ //
+ // button2
+ //
+ this.button2.Location = new System.Drawing.Point(9, 134);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(102, 23);
+ this.button2.TabIndex = 10;
+ this.button2.Text = "Update";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
+ //
+ // comboBox2
+ //
+ this.comboBox2.FormattingEnabled = true;
+ this.comboBox2.Items.AddRange(new object[] {
+ "Google",
+ "iCloud",
+ "Yahoo",
+ "Outlook"});
+ this.comboBox2.Location = new System.Drawing.Point(367, 135);
+ this.comboBox2.Name = "comboBox2";
+ this.comboBox2.Size = new System.Drawing.Size(82, 21);
+ this.comboBox2.TabIndex = 23;
+ this.comboBox2.Text = "Google";
+ //
+ // button3
+ //
+ this.button3.Location = new System.Drawing.Point(448, 134);
+ this.button3.Name = "button3";
+ this.button3.Size = new System.Drawing.Size(102, 23);
+ this.button3.TabIndex = 24;
+ this.button3.Text = "Auto Config";
+ this.button3.UseVisualStyleBackColor = true;
+ this.button3.Click += new System.EventHandler(this.button3_Click);
+ //
+ // Main
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(580, 362);
+ this.Controls.Add(this.groupBox1);
+ this.Controls.Add(this.connectionGroupBox);
+ this.Controls.Add(this.eventGroupBox);
+ this.Name = "Main";
+ this.Text = "CalCli Demo";
+ this.Load += new System.EventHandler(this.Main_Load);
+ this.eventGroupBox.ResumeLayout(false);
+ this.eventGroupBox.PerformLayout();
+ this.connectionGroupBox.ResumeLayout(false);
+ this.connectionGroupBox.PerformLayout();
+ this.groupBox1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button authButton;
+ private System.Windows.Forms.Button createEventButton;
+ private System.Windows.Forms.DateTimePicker eventStartPicker;
+ private System.Windows.Forms.DateTimePicker eventEndPicker;
+ private System.Windows.Forms.TextBox eventSummaryTextBox;
+ private System.Windows.Forms.TextBox eventDescriptionTextBox;
+ private System.Windows.Forms.Label summaryLabel;
+ private System.Windows.Forms.Label descriptionLabel;
+ private System.Windows.Forms.Label startLabel;
+ private System.Windows.Forms.GroupBox eventGroupBox;
+ private System.Windows.Forms.GroupBox connectionGroupBox;
+ private System.Windows.Forms.Label pswdLabel;
+ private System.Windows.Forms.TextBox passwordTextBox;
+ private System.Windows.Forms.Label usernameLabel;
+ private System.Windows.Forms.TextBox usernameTextBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.ComboBox urlCombo;
+ private System.Windows.Forms.Label calidLabel;
+ private System.Windows.Forms.ComboBox comboBox1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.CheckedListBox checkList;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Button button2;
+ private System.Windows.Forms.Button button3;
+ private System.Windows.Forms.ComboBox comboBox2;
+ }
+}
+
diff --git a/Demo.CalCli/Main.cs b/Demo.CalCli/Main.cs
new file mode 100644
index 0000000..a0a8feb
--- /dev/null
+++ b/Demo.CalCli/Main.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Windows.Forms;
+using CalCli.UI;
+using CalCli.Connections;
+using System.IO;
+using CalCli.API;
+using CalCli;
+using Outlook = Microsoft.Office.Interop.Outlook;
+using System.Collections.Generic;
+using CalCli.Util;
+
+namespace Demo.CalCli
+{
+ public partial class Main : Form
+ {
+ IConnection connection;
+
+ ICalendar[] calendars;
+
+ List todos;
+
+ IServer server;
+
+ public Main()
+ {
+ InitializeComponent();
+
+ todos = new List();
+ }
+
+ private void testButton_Click(object sender, EventArgs e)
+ {
+ if (urlCombo.Text.Contains("google"))
+ {
+ if (File.Exists("token"))
+ {
+ StreamReader sr = new StreamReader("token");
+ connection = new GoogleConnection(sr.ReadLine());
+ sr.Close();
+ }
+ else
+ {
+ refreshGoogleToken();
+ }
+ server = null;
+ }
+ else if (urlCombo.Text.Contains("Outlook"))
+ {
+ connection = new BasicConnection(null, null);
+ server = new OutlookClient.OutlookServer();
+ }
+ else
+ {
+ connection = new BasicConnection(usernameTextBox.Text, passwordTextBox.Text);
+ server = null;
+ }
+ if(server == null)
+ {
+ try
+ {
+ server = new CalDav.Client.Server(urlCombo.Text, connection, usernameTextBox.Text, passwordTextBox.Text);
+
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "Authentication is required")
+ {
+ refreshGoogleToken();
+ server = new CalDav.Client.Server(urlCombo.Text, connection, usernameTextBox.Text, passwordTextBox.Text);
+
+ }
+ }
+ }
+
+ try {
+ calendars = server.GetCalendars();
+ }catch(NullReferenceException ex)
+ {
+ MessageBox.Show("Could not login.");
+ return;
+ }
+ comboBox1.Items.Clear();
+ foreach(ICalendar calendar in calendars)
+ {
+ comboBox1.Items.Add(calendar.Name);
+ }
+ if(comboBox1.Items.Count > 0)
+ {
+ comboBox1.Text = (string)comboBox1.Items[0];
+ }
+ }
+
+ private void refreshGoogleToken()
+ {
+ GoogleOAuthForm form = new GoogleOAuthForm();
+ form.ShowDialog();
+ connection = new GoogleConnection(form.Result.Token);
+ StreamWriter sw = new StreamWriter("token");
+ sw.WriteLine(form.Result.Token);
+ sw.Close();
+ }
+
+ private void createEventButton_Click(object sender, EventArgs e)
+ {
+ List < IAlarm > alarms = new List();
+ IAlarm alarm = calendars[comboBox1.SelectedIndex].createAlarm();
+ ITrigger trigger = calendars[comboBox1.SelectedIndex].createTrigger();
+ alarm.Trigger = trigger;
+ //trigger.DateTime = eventStartPicker.Value;
+ trigger.Duration = new TimeSpan();
+ trigger.Duration = trigger.Duration.Value.Add(new TimeSpan(0, -5, 0));
+ trigger.Related = Relateds.Start;
+ alarm.Action = AlarmActions.DISPLAY;
+ alarms.Add(alarm);
+ IEvent ev = calendars[comboBox1.SelectedIndex].createEvent();
+
+ ev.Description = eventDescriptionTextBox.Text;
+ ev.Summary = eventSummaryTextBox.Text;
+ ev.Start = eventStartPicker.Value;
+ ev.End = eventEndPicker.Value;
+ ev.Alarms = alarms;
+ calendars[comboBox1.SelectedIndex].Save(ev);
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ Outlook.Application olApp = new Outlook.Application();
+ Outlook.NameSpace mapiNS = olApp.GetNamespace("MAPI");
+
+ string profile = "";
+ mapiNS.Logon(profile, null, null, null);
+
+ Outlook.AppointmentItem apt = olApp.CreateItem(Outlook.OlItemType.olAppointmentItem);
+ apt.Start = DateTime.Now.AddHours(-3);
+ apt.End = apt.Start.AddHours(1);
+ apt.Subject = "Please synch in advance.";
+ apt.Save();
+ apt.Send();
+ }
+
+ private void Main_Load(object sender, EventArgs e)
+ {
+
+ }
+
+ private void usernameTextBox_TextChanged(object sender, EventArgs e)
+ {
+
+ }
+
+ private void button1_Click_1(object sender, EventArgs e)
+ {
+ IToDo todo = calendars[comboBox1.SelectedIndex].createToDo();
+ todo.Summary = eventSummaryTextBox.Text;
+ todo.Start = eventStartPicker.Value;
+ todo.Due = eventStartPicker.Value;
+ try
+ {
+ calendars[comboBox1.SelectedIndex].Save(todo);
+ todos.Add(todo);
+ checkList.Items.Add(todo.Summary);
+ }catch(Exception ex)
+ {
+ MessageBox.Show("Calendar doesn't support todos.");
+ }
+ }
+
+ private void button2_Click(object sender, EventArgs e)
+ {
+ for(int i = 0; i < checkList.Items.Count; i++)
+ {
+ if(checkList.GetItemChecked(i) != (todos[i].Completed != null))
+ {
+ if (checkList.GetItemChecked(i))
+ {
+ todos[i].Completed = DateTime.UtcNow;
+ todos[i].Status = Statuses.COMPLETED;
+ }
+ else
+ {
+ todos[i].Completed = null;
+ }
+ calendars[comboBox1.SelectedIndex].Save(todos[i]);
+ }
+ }
+ }
+
+ private void button3_Click(object sender, EventArgs e)
+ {
+ try {
+ server = AutoConfiguration.GetCalendarServer(calendarTypeFromText(comboBox2.Text), usernameTextBox.Text, passwordTextBox.Text);
+ }
+ catch(Exception ex)
+ {
+ if (ex.Message == "Authentication is required")
+ MessageBox.Show("Could not login.");
+ else {
+ MessageBox.Show("Could not login.");
+ return;
+ }
+
+ }
+ try
+ {
+ calendars = server.GetCalendars();
+ }
+ catch (NullReferenceException ex)
+ {
+ MessageBox.Show("Could not login.");
+ return;
+ }
+ comboBox1.Items.Clear();
+ foreach (ICalendar calendar in calendars)
+ {
+ comboBox1.Items.Add(calendar.Name);
+ }
+ if (comboBox1.Items.Count > 0)
+ {
+ comboBox1.Text = (string)comboBox1.Items[0];
+ }
+ }
+
+ private CalendarTypes calendarTypeFromText(string text)
+ {
+ if (text == "Google")
+ return CalendarTypes.Google;
+ if (text == "iCloud")
+ return CalendarTypes.iCloud;
+ if (text == "Yahoo")
+ return CalendarTypes.Yahoo;
+ if (text == "Outlook")
+ return CalendarTypes.Outlook;
+ return CalendarTypes.Google;
+ }
+ }
+}
diff --git a/Demo.CalCli/Main.resx b/Demo.CalCli/Main.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Demo.CalCli/Main.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Demo.CalCli/Program.cs b/Demo.CalCli/Program.cs
new file mode 100644
index 0000000..d6f61b1
--- /dev/null
+++ b/Demo.CalCli/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Demo.CalCli
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Main());
+ }
+ }
+}
diff --git a/Demo.CalCli/Properties/AssemblyInfo.cs b/Demo.CalCli/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..826ecff
--- /dev/null
+++ b/Demo.CalCli/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Demo.CalCli")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo.CalCli")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4ed47a68-871a-4069-8b20-1d3d7ad163e6")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Demo.CalCli/Properties/Resources.Designer.cs b/Demo.CalCli/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..d33b530
--- /dev/null
+++ b/Demo.CalCli/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo.CalCli.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // 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() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [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("Demo.CalCli.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Demo.CalCli/Properties/Resources.resx b/Demo.CalCli/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Demo.CalCli/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Demo.CalCli/Properties/Settings.Designer.cs b/Demo.CalCli/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..26bb228
--- /dev/null
+++ b/Demo.CalCli/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo.CalCli.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Demo.CalCli/Properties/Settings.settings b/Demo.CalCli/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/Demo.CalCli/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Demo.CalCli/packages.config b/Demo.CalCli/packages.config
new file mode 100644
index 0000000..e146e3c
--- /dev/null
+++ b/Demo.CalCli/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Demo.MVC/Content/themes/base/accordion.css b/Demo.MVC/Content/themes/base/accordion.css
new file mode 100644
index 0000000..13e5752
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/accordion.css
@@ -0,0 +1,36 @@
+/*!
+ * jQuery UI Accordion 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/accordion/#theming
+ */
+.ui-accordion .ui-accordion-header {
+ display: block;
+ cursor: pointer;
+ position: relative;
+ margin: 2px 0 0 0;
+ padding: .5em .5em .5em .7em;
+ min-height: 0; /* support: IE7 */
+ font-size: 100%;
+}
+.ui-accordion .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+ position: absolute;
+ left: .5em;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+ padding: 1em 2.2em;
+ border-top: 0;
+ overflow: auto;
+}
diff --git a/Demo.MVC/Content/themes/base/all.css b/Demo.MVC/Content/themes/base/all.css
new file mode 100644
index 0000000..0bab991
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/all.css
@@ -0,0 +1,12 @@
+/*!
+ * jQuery UI CSS Framework 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/theming/
+ */
+@import "base.css";
+@import "theme.css";
diff --git a/Demo.MVC/Content/themes/base/autocomplete.css b/Demo.MVC/Content/themes/base/autocomplete.css
new file mode 100644
index 0000000..c21c54f
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/autocomplete.css
@@ -0,0 +1,16 @@
+/*!
+ * jQuery UI Autocomplete 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/autocomplete/#theming
+ */
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+}
diff --git a/Demo.MVC/Content/themes/base/base.css b/Demo.MVC/Content/themes/base/base.css
new file mode 100644
index 0000000..7f53172
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/base.css
@@ -0,0 +1,28 @@
+/*!
+ * jQuery UI CSS Framework 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/theming/
+ */
+@import url("core.css");
+
+@import url("accordion.css");
+@import url("autocomplete.css");
+@import url("button.css");
+@import url("datepicker.css");
+@import url("dialog.css");
+@import url("draggable.css");
+@import url("menu.css");
+@import url("progressbar.css");
+@import url("resizable.css");
+@import url("selectable.css");
+@import url("selectmenu.css");
+@import url("sortable.css");
+@import url("slider.css");
+@import url("spinner.css");
+@import url("tabs.css");
+@import url("tooltip.css");
diff --git a/Demo.MVC/Content/themes/base/button.css b/Demo.MVC/Content/themes/base/button.css
new file mode 100644
index 0000000..7f11bdd
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/button.css
@@ -0,0 +1,114 @@
+/*!
+ * jQuery UI Button 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/button/#theming
+ */
+.ui-button {
+ display: inline-block;
+ position: relative;
+ padding: 0;
+ line-height: normal;
+ margin-right: .1em;
+ cursor: pointer;
+ vertical-align: middle;
+ text-align: center;
+ overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+ text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+ width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+ width: 2.4em;
+}
+.ui-button-icons-only {
+ width: 3.4em;
+}
+button.ui-button-icons-only {
+ width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+ display: block;
+ line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+ padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+ padding: .4em;
+ text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+ padding-left: 2.1em;
+ padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+ padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+ left: 50%;
+ margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+ left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+ right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+ margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+ margin-left: 0;
+ margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
diff --git a/Demo.MVC/Content/themes/base/core.css b/Demo.MVC/Content/themes/base/core.css
new file mode 100644
index 0000000..154f1f8
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/core.css
@@ -0,0 +1,93 @@
+/*!
+ * jQuery UI CSS Framework 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/theming/
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+ display: none;
+}
+.ui-helper-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.ui-helper-reset {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ line-height: 1.3;
+ text-decoration: none;
+ font-size: 100%;
+ list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+ content: "";
+ display: table;
+ border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+ clear: both;
+}
+.ui-helper-clearfix {
+ min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+ z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+ cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ display: block;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
diff --git a/Demo.MVC/Content/themes/base/datepicker.css b/Demo.MVC/Content/themes/base/datepicker.css
new file mode 100644
index 0000000..ea559d8
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/datepicker.css
@@ -0,0 +1,175 @@
+/*!
+ * jQuery UI Datepicker 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/datepicker/#theming
+ */
+.ui-datepicker {
+ width: 17em;
+ padding: .2em .2em 0;
+ display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ position: absolute;
+ top: 2px;
+ width: 1.8em;
+ height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+ right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+ margin: 0 2.3em;
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+ width: 45%;
+}
+.ui-datepicker table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-datepicker th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-datepicker td {
+ border: 0;
+ padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+ width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+ float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+ width: 95%;
+ margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+ width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+ width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+ width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+ border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+ clear: left;
+}
+.ui-datepicker-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+ direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+ left: 2px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+ clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+ float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+ float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
diff --git a/Demo.MVC/Content/themes/base/dialog.css b/Demo.MVC/Content/themes/base/dialog.css
new file mode 100644
index 0000000..66b90cc
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/dialog.css
@@ -0,0 +1,70 @@
+/*!
+ * jQuery UI Dialog 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/dialog/#theming
+ */
+.ui-dialog {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: .2em;
+ outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+ padding: .4em 1em;
+ position: relative;
+}
+.ui-dialog .ui-dialog-title {
+ float: left;
+ margin: .1em 0;
+ white-space: nowrap;
+ width: 90%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+ position: absolute;
+ right: .3em;
+ top: 50%;
+ width: 20px;
+ margin: -10px 0 0 0;
+ padding: 1px;
+ height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+ position: relative;
+ border: 0;
+ padding: .5em 1em;
+ background: none;
+ overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+ text-align: left;
+ border-width: 1px 0 0 0;
+ background-image: none;
+ margin-top: .5em;
+ padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+ margin: .5em .4em .5em 0;
+ cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+ width: 12px;
+ height: 12px;
+ right: -5px;
+ bottom: -5px;
+ background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+ cursor: move;
+}
diff --git a/Demo.MVC/Content/themes/base/draggable.css b/Demo.MVC/Content/themes/base/draggable.css
new file mode 100644
index 0000000..df01f29
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/draggable.css
@@ -0,0 +1,12 @@
+/*!
+ * jQuery UI Draggable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+.ui-draggable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/Demo.MVC/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..5b5dab2
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png b/Demo.MVC/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000..ac8b229
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/Demo.MVC/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000..ad3d634
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/Demo.MVC/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000..42ccba2
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000..5a46b47
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000..86c2baa
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png b/Demo.MVC/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..4443fdc
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/Demo.MVC/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000..7c9fa6c
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_222222_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000..ee039dc
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_222222_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_2e83ff_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000..45e8928
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_2e83ff_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_444444_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_444444_256x240.png
new file mode 100644
index 0000000..348243b
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_444444_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_454545_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_454545_256x240.png
new file mode 100644
index 0000000..7ec70d1
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_454545_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_555555_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_555555_256x240.png
new file mode 100644
index 0000000..949749b
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_555555_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_777620_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_777620_256x240.png
new file mode 100644
index 0000000..350c783
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_777620_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_777777_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_777777_256x240.png
new file mode 100644
index 0000000..f8b5cc4
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_777777_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_888888_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_888888_256x240.png
new file mode 100644
index 0000000..5ba708c
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_888888_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_cc0000_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_cc0000_256x240.png
new file mode 100644
index 0000000..a046ee5
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_cc0000_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_cd0a0a_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..7930a55
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/images/ui-icons_ffffff_256x240.png b/Demo.MVC/Content/themes/base/images/ui-icons_ffffff_256x240.png
new file mode 100644
index 0000000..ea57ef0
Binary files /dev/null and b/Demo.MVC/Content/themes/base/images/ui-icons_ffffff_256x240.png differ
diff --git a/Demo.MVC/Content/themes/base/jquery-ui.css b/Demo.MVC/Content/themes/base/jquery-ui.css
new file mode 100644
index 0000000..ffdcb23
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/jquery-ui.css
@@ -0,0 +1,1312 @@
+/*! jQuery UI - v1.12.0 - 2016-07-08
+* http://jqueryui.com
+* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+ display: none;
+}
+.ui-helper-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.ui-helper-reset {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ line-height: 1.3;
+ text-decoration: none;
+ font-size: 100%;
+ list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+ content: "";
+ display: table;
+ border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+ clear: both;
+}
+.ui-helper-zfix {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+ z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+ cursor: default !important;
+ pointer-events: none;
+}
+
+
+/* Icons
+----------------------------------*/
+.ui-icon {
+ display: inline-block;
+ vertical-align: middle;
+ margin-top: -.25em;
+ position: relative;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+}
+
+.ui-widget-icon-block {
+ left: 50%;
+ margin-left: -8px;
+ display: block;
+}
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.ui-accordion .ui-accordion-header {
+ display: block;
+ cursor: pointer;
+ position: relative;
+ margin: 2px 0 0 0;
+ padding: .5em .5em .5em .7em;
+ font-size: 100%;
+}
+.ui-accordion .ui-accordion-content {
+ padding: 1em 2.2em;
+ border-top: 0;
+ overflow: auto;
+}
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+}
+.ui-menu {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ display: block;
+ outline: 0;
+}
+.ui-menu .ui-menu {
+ position: absolute;
+}
+.ui-menu .ui-menu-item {
+ margin: 0;
+ cursor: pointer;
+ /* support: IE10, see #8844 */
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-item-wrapper {
+ position: relative;
+ padding: 3px 1em 3px .4em;
+}
+.ui-menu .ui-menu-divider {
+ margin: 5px 0;
+ height: 0;
+ font-size: 0;
+ line-height: 0;
+ border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+ margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+ position: relative;
+}
+.ui-menu-icons .ui-menu-item-wrapper {
+ padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: .2em;
+ margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+ left: auto;
+ right: 0;
+}
+.ui-button {
+ padding: .4em 1em;
+ display: inline-block;
+ position: relative;
+ line-height: normal;
+ margin-right: .1em;
+ cursor: pointer;
+ vertical-align: middle;
+ text-align: center;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ /* Support: IE <= 11 */
+ overflow: visible;
+}
+
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+ text-decoration: none;
+}
+
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+ width: 2em;
+ box-sizing: border-box;
+ text-indent: -9999px;
+ white-space: nowrap;
+}
+
+/* no icon support for input elements */
+input.ui-button.ui-button-icon-only {
+ text-indent: 0;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -8px;
+ margin-left: -8px;
+}
+
+.ui-button.ui-icon-notext .ui-icon {
+ padding: 0;
+ width: 2.1em;
+ height: 2.1em;
+ text-indent: -9999px;
+ white-space: nowrap;
+
+}
+
+input.ui-button.ui-icon-notext .ui-icon {
+ width: auto;
+ height: auto;
+ text-indent: 0;
+ white-space: normal;
+ padding: .4em 1em;
+}
+
+/* workarounds */
+/* Support: Firefox 5 - 40 */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+.ui-controlgroup {
+ vertical-align: middle;
+ display: inline-block;
+}
+.ui-controlgroup > .ui-controlgroup-item {
+ float: left;
+ margin-left: 0;
+ margin-right: 0;
+}
+.ui-controlgroup > .ui-controlgroup-item:focus,
+.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
+ z-index: 9999;
+}
+.ui-controlgroup-vertical > .ui-controlgroup-item {
+ display: block;
+ float: none;
+ width: 100%;
+ margin-top: 0;
+ margin-bottom: 0;
+ text-align: left;
+}
+.ui-controlgroup-vertical .ui-controlgroup-item {
+ box-sizing: border-box;
+}
+.ui-controlgroup .ui-controlgroup-label {
+ padding: .4em 1em;
+}
+.ui-controlgroup .ui-controlgroup-label span {
+ font-size: 80%;
+}
+.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
+ border-left: none;
+}
+.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
+ border-top: none;
+}
+.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
+ border-right: none;
+}
+.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
+ border-bottom: none;
+}
+
+/* Spinner specific style fixes */
+.ui-controlgroup-vertical .ui-spinner-input {
+
+ /* Support: IE8 only, Android < 4.4 only */
+ width: 75%;
+ width: calc( 100% - 2.4em );
+}
+.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
+ border-top-style: solid;
+}
+
+.ui-checkboxradio-label .ui-icon-background {
+ box-shadow: inset 1px 1px 1px #ccc;
+ border-radius: .12em;
+ border: none;
+}
+.ui-checkboxradio-radio-label .ui-icon-background {
+ width: 16px;
+ height: 16px;
+ border-radius: 1em;
+ overflow: visible;
+ border: none;
+}
+.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
+.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
+ background-image: none;
+ width: 8px;
+ height: 8px;
+ border-width: 4px;
+ border-style: solid;
+}
+.ui-checkboxradio-disabled {
+ pointer-events: none;
+}
+.ui-datepicker {
+ width: 17em;
+ padding: .2em .2em 0;
+ display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ position: absolute;
+ top: 2px;
+ width: 1.8em;
+ height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+ right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+ margin: 0 2.3em;
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+ width: 45%;
+}
+.ui-datepicker table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-datepicker th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-datepicker td {
+ border: 0;
+ padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+ width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+ float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+ width: 95%;
+ margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+ width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+ width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+ width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+ border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+ clear: left;
+}
+.ui-datepicker-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+ direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+ left: 2px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+ clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+ float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+ float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
+
+/* Icons */
+.ui-datepicker .ui-icon {
+ display: block;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+ left: .5em;
+ top: .3em;
+}
+.ui-dialog {
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: .2em;
+ outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+ padding: .4em 1em;
+ position: relative;
+}
+.ui-dialog .ui-dialog-title {
+ float: left;
+ margin: .1em 0;
+ white-space: nowrap;
+ width: 90%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+ position: absolute;
+ right: .3em;
+ top: 50%;
+ width: 20px;
+ margin: -10px 0 0 0;
+ padding: 1px;
+ height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+ position: relative;
+ border: 0;
+ padding: .5em 1em;
+ background: none;
+ overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+ text-align: left;
+ border-width: 1px 0 0 0;
+ background-image: none;
+ margin-top: .5em;
+ padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+ margin: .5em .4em .5em 0;
+ cursor: pointer;
+}
+.ui-dialog .ui-resizable-n {
+ height: 2px;
+ top: 0;
+}
+.ui-dialog .ui-resizable-e {
+ width: 2px;
+ right: 0;
+}
+.ui-dialog .ui-resizable-s {
+ height: 2px;
+ bottom: 0;
+}
+.ui-dialog .ui-resizable-w {
+ width: 2px;
+ left: 0;
+}
+.ui-dialog .ui-resizable-se,
+.ui-dialog .ui-resizable-sw,
+.ui-dialog .ui-resizable-ne,
+.ui-dialog .ui-resizable-nw {
+ width: 7px;
+ height: 7px;
+}
+.ui-dialog .ui-resizable-se {
+ right: 0;
+ bottom: 0;
+}
+.ui-dialog .ui-resizable-sw {
+ left: 0;
+ bottom: 0;
+}
+.ui-dialog .ui-resizable-ne {
+ right: 0;
+ top: 0;
+}
+.ui-dialog .ui-resizable-nw {
+ left: 0;
+ top: 0;
+}
+.ui-draggable .ui-dialog-titlebar {
+ cursor: move;
+}
+.ui-draggable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable {
+ position: relative;
+}
+.ui-resizable-handle {
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+ display: none;
+}
+.ui-resizable-n {
+ cursor: n-resize;
+ height: 7px;
+ width: 100%;
+ top: -5px;
+ left: 0;
+}
+.ui-resizable-s {
+ cursor: s-resize;
+ height: 7px;
+ width: 100%;
+ bottom: -5px;
+ left: 0;
+}
+.ui-resizable-e {
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-w {
+ cursor: w-resize;
+ width: 7px;
+ left: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-se {
+ cursor: se-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ bottom: 1px;
+}
+.ui-resizable-sw {
+ cursor: sw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ bottom: -5px;
+}
+.ui-resizable-nw {
+ cursor: nw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ top: -5px;
+}
+.ui-resizable-ne {
+ cursor: ne-resize;
+ width: 9px;
+ height: 9px;
+ right: -5px;
+ top: -5px;
+}
+.ui-progressbar {
+ height: 2em;
+ text-align: left;
+ overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+ margin: -1px;
+ height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+ height: 100%;
+ filter: alpha(opacity=25); /* support: IE8 */
+ opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+ background-image: none;
+}
+.ui-selectable {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-selectable-helper {
+ position: absolute;
+ z-index: 100;
+ border: 1px dotted black;
+}
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ overflow-x: hidden;
+ padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+.ui-selectmenu-open {
+ display: block;
+}
+.ui-selectmenu-text {
+ display: block;
+ margin-right: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.ui-selectmenu-button.ui-button {
+ text-align: left;
+ white-space: nowrap;
+ width: 14em;
+}
+.ui-selectmenu-icon.ui-icon {
+ float: right;
+ margin-top: 0;
+}
+.ui-slider {
+ position: relative;
+ text-align: left;
+}
+.ui-slider .ui-slider-handle {
+ position: absolute;
+ z-index: 2;
+ width: 1.2em;
+ height: 1.2em;
+ cursor: default;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-slider .ui-slider-range {
+ position: absolute;
+ z-index: 1;
+ font-size: .7em;
+ display: block;
+ border: 0;
+ background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+ filter: inherit;
+}
+
+.ui-slider-horizontal {
+ height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+ top: -.3em;
+ margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+ top: 0;
+ height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+ left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+ right: 0;
+}
+
+.ui-slider-vertical {
+ width: .8em;
+ height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -.3em;
+ margin-left: 0;
+ margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+ left: 0;
+ width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+ bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+ top: 0;
+}
+.ui-sortable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-spinner {
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ padding: 0;
+ vertical-align: middle;
+}
+.ui-spinner-input {
+ border: none;
+ background: none;
+ color: inherit;
+ padding: .222em 0;
+ margin: .2em 0;
+ vertical-align: middle;
+ margin-left: .4em;
+ margin-right: 2em;
+}
+.ui-spinner-button {
+ width: 1.6em;
+ height: 50%;
+ font-size: .5em;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ position: absolute;
+ cursor: default;
+ display: block;
+ overflow: hidden;
+ right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+ border-top-style: none;
+ border-bottom-style: none;
+ border-right-style: none;
+}
+.ui-spinner-up {
+ top: 0;
+}
+.ui-spinner-down {
+ bottom: 0;
+}
+.ui-tabs {
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+ padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+ margin: 0;
+ padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+ list-style: none;
+ float: left;
+ position: relative;
+ top: 0;
+ margin: 1px .2em 0 0;
+ border-bottom-width: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+ float: left;
+ padding: .5em 1em;
+ text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+ cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+ cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 1em 1.4em;
+ background: none;
+}
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+}
+body .ui-tooltip {
+ border-width: 2px;
+}
+/* Component containers
+----------------------------------*/
+.ui-widget {
+ font-family: Arial,Helvetica,sans-serif;
+ font-size: 1em;
+}
+.ui-widget .ui-widget {
+ font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: Arial,Helvetica,sans-serif;
+ font-size: 1em;
+}
+.ui-widget.ui-widget-content {
+ border: 1px solid #c5c5c5;
+}
+.ui-widget-content {
+ border: 1px solid #dddddd;
+ background: #ffffff;
+ color: #333333;
+}
+.ui-widget-content a {
+ color: #333333;
+}
+.ui-widget-header {
+ border: 1px solid #dddddd;
+ background: #e9e9e9;
+ color: #333333;
+ font-weight: bold;
+}
+.ui-widget-header a {
+ color: #333333;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default,
+.ui-button,
+
+/* We use html here because we need a greater specificity to make sure disabled
+works properly when clicked or hovered */
+html .ui-button.ui-state-disabled:hover,
+html .ui-button.ui-state-disabled:active {
+ border: 1px solid #c5c5c5;
+ background: #f6f6f6;
+ font-weight: normal;
+ color: #454545;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited,
+a.ui-button,
+a:link.ui-button,
+a:visited.ui-button,
+.ui-button {
+ color: #454545;
+ text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus,
+.ui-button:hover,
+.ui-button:focus {
+ border: 1px solid #cccccc;
+ background: #ededed;
+ font-weight: normal;
+ color: #2b2b2b;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited,
+a.ui-button:hover,
+a.ui-button:focus {
+ color: #2b2b2b;
+ text-decoration: none;
+}
+
+.ui-visual-focus {
+ box-shadow: 0 0 3px 1px rgb(94, 158, 214);
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active,
+a.ui-button:active,
+.ui-button:active,
+.ui-button.ui-state-active:hover {
+ border: 1px solid #003eff;
+ background: #007fff;
+ font-weight: normal;
+ color: #ffffff;
+}
+.ui-icon-background,
+.ui-state-active .ui-icon-background {
+ border: #003eff;
+ background-color: #ffffff;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #ffffff;
+ text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+ border: 1px solid #dad55e;
+ background: #fffa90;
+ color: #777620;
+}
+.ui-state-checked {
+ border: 1px solid #dad55e;
+ background: #fffa90;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+ color: #777620;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+ border: 1px solid #f1a899;
+ background: #fddfdf;
+ color: #5f3f3f;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+ color: #5f3f3f;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+ color: #5f3f3f;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+ font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+ opacity: .7;
+ filter:Alpha(Opacity=70); /* support: IE8 */
+ font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+ opacity: .35;
+ filter:Alpha(Opacity=35); /* support: IE8 */
+ background-image: none;
+}
+.ui-state-disabled .ui-icon {
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ width: 16px;
+ height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+ background-image: url("images/ui-icons_444444_256x240.png");
+}
+.ui-widget-header .ui-icon {
+ background-image: url("images/ui-icons_444444_256x240.png");
+}
+.ui-button .ui-icon {
+ background-image: url("images/ui-icons_777777_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon,
+.ui-button:hover .ui-icon,
+.ui-button:focus .ui-icon,
+.ui-state-default .ui-icon {
+ background-image: url("images/ui-icons_555555_256x240.png");
+}
+.ui-state-active .ui-icon,
+.ui-button:active .ui-icon {
+ background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-highlight .ui-icon,
+.ui-button .ui-state-highlight.ui-icon {
+ background-image: url("images/ui-icons_777620_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+ background-image: url("images/ui-icons_cc0000_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-caret-1-n { background-position: 0 0; }
+.ui-icon-caret-1-ne { background-position: -16px 0; }
+.ui-icon-caret-1-e { background-position: -32px 0; }
+.ui-icon-caret-1-se { background-position: -48px 0; }
+.ui-icon-caret-1-s { background-position: -65px 0; }
+.ui-icon-caret-1-sw { background-position: -80px 0; }
+.ui-icon-caret-1-w { background-position: -96px 0; }
+.ui-icon-caret-1-nw { background-position: -112px 0; }
+.ui-icon-caret-2-n-s { background-position: -128px 0; }
+.ui-icon-caret-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -65px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -65px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 3px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+ background: #aaaaaa;
+ opacity: .3;
+ filter: Alpha(Opacity=30); /* support: IE8 */
+}
+.ui-widget-shadow {
+ -webkit-box-shadow: 0px 0px 5px #666666;
+ box-shadow: 0px 0px 5px #666666;
+}
diff --git a/Demo.MVC/Content/themes/base/jquery-ui.min.css b/Demo.MVC/Content/themes/base/jquery-ui.min.css
new file mode 100644
index 0000000..1f47347
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/jquery-ui.min.css
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.12.0 - 2016-07-08
+* http://jqueryui.com
+* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon,.ui-state-default .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666}
\ No newline at end of file
diff --git a/Demo.MVC/Content/themes/base/menu.css b/Demo.MVC/Content/themes/base/menu.css
new file mode 100644
index 0000000..221fc51
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/menu.css
@@ -0,0 +1,63 @@
+/*!
+ * jQuery UI Menu 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/menu/#theming
+ */
+.ui-menu {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ display: block;
+ outline: none;
+}
+.ui-menu .ui-menu {
+ position: absolute;
+}
+.ui-menu .ui-menu-item {
+ position: relative;
+ margin: 0;
+ padding: 3px 1em 3px .4em;
+ cursor: pointer;
+ min-height: 0; /* support: IE7 */
+ /* support: IE10, see #8844 */
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-divider {
+ margin: 5px 0;
+ height: 0;
+ font-size: 0;
+ line-height: 0;
+ border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+ margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+ position: relative;
+}
+.ui-menu-icons .ui-menu-item {
+ padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: .2em;
+ margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+ left: auto;
+ right: 0;
+}
diff --git a/Demo.MVC/Content/themes/base/progressbar.css b/Demo.MVC/Content/themes/base/progressbar.css
new file mode 100644
index 0000000..5e43600
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/progressbar.css
@@ -0,0 +1,28 @@
+/*!
+ * jQuery UI Progressbar 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/progressbar/#theming
+ */
+.ui-progressbar {
+ height: 2em;
+ text-align: left;
+ overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+ margin: -1px;
+ height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+ height: 100%;
+ filter: alpha(opacity=25); /* support: IE8 */
+ opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+ background-image: none;
+}
diff --git a/Demo.MVC/Content/themes/base/resizable.css b/Demo.MVC/Content/themes/base/resizable.css
new file mode 100644
index 0000000..23d9a07
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/resizable.css
@@ -0,0 +1,78 @@
+/*!
+ * jQuery UI Resizable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+.ui-resizable {
+ position: relative;
+}
+.ui-resizable-handle {
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+ display: none;
+}
+.ui-resizable-n {
+ cursor: n-resize;
+ height: 7px;
+ width: 100%;
+ top: -5px;
+ left: 0;
+}
+.ui-resizable-s {
+ cursor: s-resize;
+ height: 7px;
+ width: 100%;
+ bottom: -5px;
+ left: 0;
+}
+.ui-resizable-e {
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-w {
+ cursor: w-resize;
+ width: 7px;
+ left: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-se {
+ cursor: se-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ bottom: 1px;
+}
+.ui-resizable-sw {
+ cursor: sw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ bottom: -5px;
+}
+.ui-resizable-nw {
+ cursor: nw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ top: -5px;
+}
+.ui-resizable-ne {
+ cursor: ne-resize;
+ width: 9px;
+ height: 9px;
+ right: -5px;
+ top: -5px;
+}
diff --git a/Demo.MVC/Content/themes/base/selectable.css b/Demo.MVC/Content/themes/base/selectable.css
new file mode 100644
index 0000000..482597c
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/selectable.css
@@ -0,0 +1,17 @@
+/*!
+ * jQuery UI Selectable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+.ui-selectable {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-selectable-helper {
+ position: absolute;
+ z-index: 100;
+ border: 1px dotted black;
+}
diff --git a/Demo.MVC/Content/themes/base/selectmenu.css b/Demo.MVC/Content/themes/base/selectmenu.css
new file mode 100644
index 0000000..2417b6b
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/selectmenu.css
@@ -0,0 +1,59 @@
+/*!
+ * jQuery UI Selectmenu 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectmenu/#theming
+ */
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ /* Support: IE7 */
+ overflow-x: hidden;
+ padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+.ui-selectmenu-open {
+ display: block;
+}
+.ui-selectmenu-button {
+ display: inline-block;
+ overflow: hidden;
+ position: relative;
+ text-decoration: none;
+ cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+ right: 0.5em;
+ left: auto;
+ margin-top: -8px;
+ position: absolute;
+ top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+ text-align: left;
+ padding: 0.4em 2.1em 0.4em 1em;
+ display: block;
+ line-height: 1.4;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/Demo.MVC/Content/themes/base/slider.css b/Demo.MVC/Content/themes/base/slider.css
new file mode 100644
index 0000000..7c4f01a
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/slider.css
@@ -0,0 +1,75 @@
+/*!
+ * jQuery UI Slider 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/slider/#theming
+ */
+.ui-slider {
+ position: relative;
+ text-align: left;
+}
+.ui-slider .ui-slider-handle {
+ position: absolute;
+ z-index: 2;
+ width: 1.2em;
+ height: 1.2em;
+ cursor: default;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-slider .ui-slider-range {
+ position: absolute;
+ z-index: 1;
+ font-size: .7em;
+ display: block;
+ border: 0;
+ background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+ filter: inherit;
+}
+
+.ui-slider-horizontal {
+ height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+ top: -.3em;
+ margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+ top: 0;
+ height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+ left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+ right: 0;
+}
+
+.ui-slider-vertical {
+ width: .8em;
+ height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -.3em;
+ margin-left: 0;
+ margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+ left: 0;
+ width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+ bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+ top: 0;
+}
diff --git a/Demo.MVC/Content/themes/base/sortable.css b/Demo.MVC/Content/themes/base/sortable.css
new file mode 100644
index 0000000..1c27bad
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/sortable.css
@@ -0,0 +1,12 @@
+/*!
+ * jQuery UI Sortable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+.ui-sortable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
diff --git a/Demo.MVC/Content/themes/base/spinner.css b/Demo.MVC/Content/themes/base/spinner.css
new file mode 100644
index 0000000..9a9b78b
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/spinner.css
@@ -0,0 +1,65 @@
+/*!
+ * jQuery UI Spinner 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/spinner/#theming
+ */
+.ui-spinner {
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ padding: 0;
+ vertical-align: middle;
+}
+.ui-spinner-input {
+ border: none;
+ background: none;
+ color: inherit;
+ padding: 0;
+ margin: .2em 0;
+ vertical-align: middle;
+ margin-left: .4em;
+ margin-right: 22px;
+}
+.ui-spinner-button {
+ width: 16px;
+ height: 50%;
+ font-size: .5em;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ position: absolute;
+ cursor: default;
+ display: block;
+ overflow: hidden;
+ right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+ border-top: none;
+ border-bottom: none;
+ border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+ position: absolute;
+ margin-top: -8px;
+ top: 50%;
+ left: 0;
+}
+.ui-spinner-up {
+ top: 0;
+}
+.ui-spinner-down {
+ bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+ /* need to fix icons sprite */
+ background-position: -65px -16px;
+}
diff --git a/Demo.MVC/Content/themes/base/tabs.css b/Demo.MVC/Content/themes/base/tabs.css
new file mode 100644
index 0000000..c92a1b8
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/tabs.css
@@ -0,0 +1,51 @@
+/*!
+ * jQuery UI Tabs 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tabs/#theming
+ */
+.ui-tabs {
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+ padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+ margin: 0;
+ padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+ list-style: none;
+ float: left;
+ position: relative;
+ top: 0;
+ margin: 1px .2em 0 0;
+ border-bottom-width: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+ float: left;
+ padding: .5em 1em;
+ text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+ cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+ cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 1em 1.4em;
+ background: none;
+}
diff --git a/Demo.MVC/Content/themes/base/theme.css b/Demo.MVC/Content/themes/base/theme.css
new file mode 100644
index 0000000..da972f5
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/theme.css
@@ -0,0 +1,444 @@
+/*!
+ * jQuery UI CSS Framework 1.12.0
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/theming/
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+ font-family: Arial,Helvetica,sans-serif;
+ font-size: 1em;
+}
+.ui-widget .ui-widget {
+ font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: Arial,Helvetica,sans-serif;
+ font-size: 1em;
+}
+.ui-widget.ui-widget-content {
+ border: 1px solid #c5c5c5;
+}
+.ui-widget-content {
+ border: 1px solid #dddddd;
+ background: #ffffff;
+ color: #333333;
+}
+.ui-widget-content a {
+ color: #333333;
+}
+.ui-widget-header {
+ border: 1px solid #dddddd;
+ background: #e9e9e9;
+ color: #333333;
+ font-weight: bold;
+}
+.ui-widget-header a {
+ color: #333333;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default,
+.ui-button,
+
+/* We use html here because we need a greater specificity to make sure disabled
+works properly when clicked or hovered */
+html .ui-button.ui-state-disabled:hover,
+html .ui-button.ui-state-disabled:active {
+ border: 1px solid #c5c5c5;
+ background: #f6f6f6;
+ font-weight: normal;
+ color: #454545;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited,
+a.ui-button,
+a:link.ui-button,
+a:visited.ui-button,
+.ui-button {
+ color: #454545;
+ text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus,
+.ui-button:hover,
+.ui-button:focus {
+ border: 1px solid #cccccc;
+ background: #ededed;
+ font-weight: normal;
+ color: #2b2b2b;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited,
+a.ui-button:hover,
+a.ui-button:focus {
+ color: #2b2b2b;
+ text-decoration: none;
+}
+
+.ui-visual-focus {
+ box-shadow: 0 0 3px 1px rgb(94, 158, 214);
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active,
+a.ui-button:active,
+.ui-button:active,
+.ui-button.ui-state-active:hover {
+ border: 1px solid #003eff;
+ background: #007fff;
+ font-weight: normal;
+ color: #ffffff;
+}
+.ui-icon-background,
+.ui-state-active .ui-icon-background {
+ border: #003eff;
+ background-color: #ffffff;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #ffffff;
+ text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+ border: 1px solid #dad55e;
+ background: #fffa90;
+ color: #777620;
+}
+.ui-state-checked {
+ border: 1px solid #dad55e;
+ background: #fffa90;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+ color: #777620;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+ border: 1px solid #f1a899;
+ background: #fddfdf;
+ color: #5f3f3f;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+ color: #5f3f3f;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+ color: #5f3f3f;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+ font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+ opacity: .7;
+ filter:Alpha(Opacity=70); /* support: IE8 */
+ font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+ opacity: .35;
+ filter:Alpha(Opacity=35); /* support: IE8 */
+ background-image: none;
+}
+.ui-state-disabled .ui-icon {
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ width: 16px;
+ height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+ background-image: url("images/ui-icons_444444_256x240.png");
+}
+.ui-widget-header .ui-icon {
+ background-image: url("images/ui-icons_444444_256x240.png");
+}
+.ui-button .ui-icon {
+ background-image: url("images/ui-icons_777777_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon,
+.ui-button:hover .ui-icon,
+.ui-button:focus .ui-icon,
+.ui-state-default .ui-icon {
+ background-image: url("images/ui-icons_555555_256x240.png");
+}
+.ui-state-active .ui-icon,
+.ui-button:active .ui-icon {
+ background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-highlight .ui-icon,
+.ui-button .ui-state-highlight.ui-icon {
+ background-image: url("images/ui-icons_777620_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+ background-image: url("images/ui-icons_cc0000_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-caret-1-n { background-position: 0 0; }
+.ui-icon-caret-1-ne { background-position: -16px 0; }
+.ui-icon-caret-1-e { background-position: -32px 0; }
+.ui-icon-caret-1-se { background-position: -48px 0; }
+.ui-icon-caret-1-s { background-position: -65px 0; }
+.ui-icon-caret-1-sw { background-position: -80px 0; }
+.ui-icon-caret-1-w { background-position: -96px 0; }
+.ui-icon-caret-1-nw { background-position: -112px 0; }
+.ui-icon-caret-2-n-s { background-position: -128px 0; }
+.ui-icon-caret-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -65px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -65px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 3px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 3px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+ background: #aaaaaa;
+ opacity: .3;
+ filter: Alpha(Opacity=30); /* support: IE8 */
+}
+.ui-widget-shadow {
+ -webkit-box-shadow: 0px 0px 5px #666666;
+ box-shadow: 0px 0px 5px #666666;
+}
diff --git a/Demo.MVC/Content/themes/base/tooltip.css b/Demo.MVC/Content/themes/base/tooltip.css
new file mode 100644
index 0000000..6eb8b91
--- /dev/null
+++ b/Demo.MVC/Content/themes/base/tooltip.css
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI Tooltip 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tooltip/#theming
+ */
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+ -webkit-box-shadow: 0 0 5px #aaa;
+ box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+ border-width: 2px;
+}
diff --git a/Demo.MVC/Controllers/HomeController.cs b/Demo.MVC/Controllers/HomeController.cs
new file mode 100644
index 0000000..80ae87d
--- /dev/null
+++ b/Demo.MVC/Controllers/HomeController.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+namespace Demo.MVC.Controllers
+{
+ public class HomeController : Controller
+ {
+ // GET: Home
+ public ActionResult Index()
+ {
+ return View();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo.MVC/Demo.MVC.csproj b/Demo.MVC/Demo.MVC.csproj
index 4c28463..ab6d103 100644
--- a/Demo.MVC/Demo.MVC.csproj
+++ b/Demo.MVC/Demo.MVC.csproj
@@ -1,5 +1,6 @@
-
+
+
Debug
@@ -8,12 +9,12 @@
2.0
{9164611E-4CAF-4FE1-B707-397CC1D515C0}
- {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
Library
Properties
Demo.MVC
Demo.MVC
- v4.0
+ v4.8
false
true
@@ -23,6 +24,16 @@
..\
true
+ true
+
+
+
+
+ 4.0
+
+
+
+
true
@@ -32,6 +43,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -40,8 +52,15 @@
TRACE
prompt
4
+ false
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll
+
@@ -52,51 +71,43 @@
-
-
-
-
-
-
-
- ..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll
-
-
- True
- ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll
-
- True
- ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.Helpers.dll
+
+ ..\packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll
-
- True
- ..\packages\Microsoft.AspNet.Mvc.3.0.20105.1\lib\net40\System.Web.Mvc.dll
+
+ ..\packages\Microsoft.AspNet.Providers.Core.2.0.0\lib\net40\System.Web.Providers.dll
-
- ..\packages\Microsoft.AspNet.Providers.Core.1.1\lib\net40\System.Web.Providers.dll
+
+ ..\packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll
-
- True
- ..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll
-
- True
- ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.dll
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll
-
- True
- ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Deployment.dll
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll
-
+
+
+
+
+
True
- ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
Global.asax
@@ -105,7 +116,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Web.config
@@ -117,16 +180,19 @@
+
-
-
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
{471ea68f-fb1f-4df8-aac1-31022c7316ab}
CalDav.Server
@@ -136,6 +202,12 @@
CalDav
+
+
+
+
+
+
10.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
@@ -152,9 +224,9 @@
True
True
- 0
+ 49970
/
- http://localhost:59780/
+ http://localhost:49970/
False
False
@@ -165,6 +237,14 @@
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/Demo.MVC/Web.config b/Demo.MVC/Web.config
index fa06dd1..7c35679 100644
--- a/Demo.MVC/Web.config
+++ b/Demo.MVC/Web.config
@@ -1,4 +1,4 @@
-
+
-
+
-
-
-
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Demo.MVC/packages.config b/Demo.MVC/packages.config
index bb29542..b776f6b 100644
--- a/Demo.MVC/packages.config
+++ b/Demo.MVC/packages.config
@@ -1,14 +1,14 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Demo.WPF/App.config b/Demo.WPF/App.config
index 8e15646..4bfa005 100644
--- a/Demo.WPF/App.config
+++ b/Demo.WPF/App.config
@@ -1,6 +1,6 @@
-
+
-
+
-
\ No newline at end of file
+
diff --git a/Demo.WPF/Demo.WPF.csproj b/Demo.WPF/Demo.WPF.csproj
index 4690144..156bfdf 100644
--- a/Demo.WPF/Demo.WPF.csproj
+++ b/Demo.WPF/Demo.WPF.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -9,10 +9,11 @@
Properties
CalDav.WPF
CalDav.WPF
- v4.5
+ v4.8
512
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
4
+
AnyCPU
diff --git a/Demo.WPF/MainWindow.xaml.cs b/Demo.WPF/MainWindow.xaml.cs
index 29fdea6..7833b0c 100644
--- a/Demo.WPF/MainWindow.xaml.cs
+++ b/Demo.WPF/MainWindow.xaml.cs
@@ -17,64 +17,65 @@ public MainWindow() {
CalDav.Client.Calendar _Calendar;
void MainWindow_Loaded(object sender, RoutedEventArgs e) {
- _Server = new CalDav.Client.Server("https://www.google.com/calendar/dav/andy.edinborough@gmail.com/events/", "andy.edinborough@gmail.com", "Gboey6Emo!");
- _Calendar = _Server.GetCalendars().FirstOrDefault();
+ // CalCli.API.IConnection c =
+ //_Server = new CalDav.Client.Server("https://www.google.com/calendar/dav/andy.edinborough@gmail.com/events/", c, "andy.edinborough@gmail.com", "Gboey6Emo!");
+ //_Calendar = _Server.GetCalendars().FirstOrDefault();
- this.AsyncUI(_Calendar.Initialize, () => lblCalendarName.Content = _Calendar.Name);
- LoadEvents();
+ //this.AsyncUI(_Calendar.Initialize, () => lblCalendarName.Content = _Calendar.Name);
+ //LoadEvents();
}
void LoadEvents() {
- this.AsyncUI(() => {
- var now = DateTime.UtcNow;
- var from = new DateTime(now.Year, now.Month, 1);
- var to = from.AddMonths(1);
- return _Calendar.Search(CalDav.CalendarQuery.SearchEvents(from, to));
- }, results => {
- lbEvents.Items.Clear();
- var events = results.SelectMany(x => x.Events);
- lbEvents.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
- foreach (var evnt in events) {
- var grid = new Grid();
- grid.Margin = new Thickness(0);
- grid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
- grid.ColumnDefinitions.Add(new ColumnDefinition { });
- grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(90) });
- grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(90) });
+ //this.AsyncUI(() => {
+ // var now = DateTime.UtcNow;
+ // var from = new DateTime(now.Year, now.Month, 1);
+ // var to = from.AddMonths(1);
+ // //return _Calendar.Search(CalDav.CalendarQuery.SearchEvents(from, to));
+ //}, results => {
+ // lbEvents.Items.Clear();
+ // var events = results.SelectMany(x => x.Events);
+ // lbEvents.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
+ // foreach (var evnt in events) {
+ // var grid = new Grid();
+ // grid.Margin = new Thickness(0);
+ // grid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
+ // grid.ColumnDefinitions.Add(new ColumnDefinition { });
+ // grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(90) });
+ // grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(90) });
- var lbl = new Label { Content = evnt.Start.Value.ToShortDateString() + " " + evnt.Summary };
- grid.Children.Add(lbl);
- Grid.SetColumn(lbl, 0);
+ // var lbl = new Label { Content = evnt.Start.Value.ToShortDateString() + " " + evnt.Summary };
+ // grid.Children.Add(lbl);
+ // Grid.SetColumn(lbl, 0);
- var btn = new Button {
- Content = "Tomorrow"
- };
- btn.Click += (sender, ee) => {
- evnt.Start = DateTime.UtcNow.AddDays(1).Date;
- btn.IsEnabled = false;
- this.AsyncUI(() => _Calendar.Save(evnt), LoadEvents);
- };
- btn.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
- btn.Margin = new Thickness(0);
- grid.Children.Add(btn);
- Grid.SetColumn(btn, 1);
+ // var btn = new Button {
+ // Content = "Tomorrow"
+ // };
+ // btn.Click += (sender, ee) => {
+ // evnt.Start = DateTime.UtcNow.AddDays(1).Date;
+ // btn.IsEnabled = false;
+ // this.AsyncUI(() => _Calendar.Save(evnt), LoadEvents);
+ // };
+ // btn.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
+ // btn.Margin = new Thickness(0);
+ // grid.Children.Add(btn);
+ // Grid.SetColumn(btn, 1);
- var btn2 = new Button {
- Content = "Next Week"
- };
- btn2.Click += (sender, ee) => {
- evnt.Start = DateTime.UtcNow.AddDays(7).Date;
- btn2.IsEnabled = false;
- this.AsyncUI(() => _Calendar.Save(evnt), LoadEvents);
- };
- btn2.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
- btn2.Margin = new Thickness(0);
- grid.Children.Add(btn2);
- Grid.SetColumn(btn2, 2);
+ // var btn2 = new Button {
+ // Content = "Next Week"
+ // };
+ // btn2.Click += (sender, ee) => {
+ // evnt.Start = DateTime.UtcNow.AddDays(7).Date;
+ // btn2.IsEnabled = false;
+ // this.AsyncUI(() => _Calendar.Save(evnt), LoadEvents);
+ // };
+ // btn2.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
+ // btn2.Margin = new Thickness(0);
+ // grid.Children.Add(btn2);
+ // Grid.SetColumn(btn2, 2);
- lbEvents.Items.Add(grid);
- }
- });
+ // lbEvents.Items.Add(grid);
+ // }
+ //});
}
}
}
diff --git a/Demo.WPF/Properties/Resources.Designer.cs b/Demo.WPF/Properties/Resources.Designer.cs
index 7e330c6..e491474 100644
--- a/Demo.WPF/Properties/Resources.Designer.cs
+++ b/Demo.WPF/Properties/Resources.Designer.cs
@@ -1,62 +1,63 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17929
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace Demo.WPF.Properties {
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // 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", "4.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() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if ((resourceMan == null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo.WPF.Properties.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
- }
+namespace CalDav.WPF.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // 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() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [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("CalDav.WPF.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
}
diff --git a/Demo.WPF/Properties/Settings.Designer.cs b/Demo.WPF/Properties/Settings.Designer.cs
index 41e5749..ec997b9 100644
--- a/Demo.WPF/Properties/Settings.Designer.cs
+++ b/Demo.WPF/Properties/Settings.Designer.cs
@@ -1,26 +1,26 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17929
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace Demo.WPF.Properties {
-
-
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
- private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default {
- get {
- return defaultInstance;
- }
- }
- }
+namespace CalDav.WPF.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
}
diff --git a/OutlookClient/OutlookAlarm.cs b/OutlookClient/OutlookAlarm.cs
new file mode 100644
index 0000000..dfbbba7
--- /dev/null
+++ b/OutlookClient/OutlookAlarm.cs
@@ -0,0 +1,63 @@
+using System;
+using CalCli.API;
+using Outlook = Microsoft.Office.Interop.Outlook;
+using CalDav;
+namespace OutlookClient {
+ public class OutlookAlarm : IAlarm
+ {
+ public OutlookAlarm(Outlook.Application application)
+ {
+ this.application = application;
+ }
+
+ Outlook.Reminder reminder;
+ public AlarmActions Action
+ {
+ get
+ {
+ return AlarmActions.DISPLAY;
+ }
+
+ set
+ {
+ if(value != AlarmActions.DISPLAY)
+ throw new Exception("Outlook supports display type only.");
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ return reminder.Caption;
+ }
+
+ set
+ {
+ throw new Exception("Description cannot be set for Outlook alarm.");
+ }
+ }
+
+ private Trigger trigger;
+ private Outlook.Application application;
+
+ public ITrigger Trigger
+ {
+ get
+ {
+ if (trigger == null)
+ return new Trigger()
+ {
+ DateTime = reminder.OriginalReminderDate
+ };
+ else
+ return trigger;
+ }
+
+ set
+ {
+ trigger = (Trigger)value;
+ }
+ }
+ }
+}
diff --git a/OutlookClient/OutlookCalendar.cs b/OutlookClient/OutlookCalendar.cs
new file mode 100644
index 0000000..b57c9bb
--- /dev/null
+++ b/OutlookClient/OutlookCalendar.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Xml.Linq;
+using CalCli.API;
+using Outlook = Microsoft.Office.Interop.Outlook;
+using OutlookClient;
+using System.Runtime.InteropServices;
+
+namespace OutlookClient {
+ public class OutlookCalendar : ICalendar
+ {
+ private Outlook.Application application;
+ public OutlookCalendar(Outlook.Application app)
+ {
+ this.application = app;
+ }
+ public string Description
+ {
+ get
+ {
+ return "Outlook calendar.";
+ }
+
+ set
+ {
+ throw new Exception("Description for outlook calendar is readonly. ");
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return "Outlook calendar.";
+ }
+
+ set
+ {
+ throw new Exception("Name for outlook calendar is readonly. ");
+ }
+ }
+
+ public IAlarm createAlarm()
+ {
+ return new OutlookAlarm(application);
+ }
+
+ public IEvent createEvent()
+ {
+ return new OutlookEvent(application);
+ }
+
+ public IToDo createToDo()
+ {
+ return new OutlookToDo(application);
+ }
+
+ public ITrigger createTrigger()
+ {
+ return new CalDav.Trigger();
+ }
+
+ public void Save(IToDo t)
+ {
+ Outlook.TaskItem item = ((OutlookToDo)t).TaskItem;
+ item.Assign();
+ item.Save();
+ sync();
+ }
+
+ public void Save(IEvent e)
+ {
+ Outlook.AppointmentItem item = ((OutlookEvent)e).Appointment;
+ item.Save();
+ sync();
+ }
+
+ private void sync()
+ {
+
+ Outlook.NameSpace ns = application.GetNamespace("MAPI");
+ ns.SendAndReceive(false);
+ if (ns != null) Marshal.ReleaseComObject(ns);
+ }
+ }
+}
diff --git a/OutlookClient/OutlookClient.csproj b/OutlookClient/OutlookClient.csproj
new file mode 100644
index 0000000..f05a7b2
--- /dev/null
+++ b/OutlookClient/OutlookClient.csproj
@@ -0,0 +1,101 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {01AF789A-F9CE-47F7-A66C-D3BAE82AECC3}
+ Library
+ Properties
+ OutlookClient
+ OutlookClient
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+ ..\packages\Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory.4.0.209160138-alpha\lib\net45\Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory.dll
+ True
+
+
+ ..\packages\Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory.4.0.209160138-alpha\lib\net45\Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory.Platform.dll
+ True
+
+
+ ..\packages\Microsoft.Office.Interop.Outlook.15.0.4797.1003\lib\net20\Microsoft.Office.Interop.Outlook.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
+
+ {01a4c4cf-5ad1-4324-a391-dc922c84be1c}
+ CalDav
+
+
+
+
+
+
+
+
+ {00020430-0000-0000-C000-000000000046}
+ 2
+ 0
+ 0
+ primary
+ False
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/OutlookClient/OutlookConnection.cs b/OutlookClient/OutlookConnection.cs
new file mode 100644
index 0000000..126c065
--- /dev/null
+++ b/OutlookClient/OutlookConnection.cs
@@ -0,0 +1,14 @@
+using System.Net;
+using CalCli.API;
+//using Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory;
+
+namespace CalCli.Connections
+{
+ public class OutlookConnection : IConnection
+ {
+ public WebRequest Authorize(WebRequest request)
+ {
+ return request;
+ }
+ }
+}
diff --git a/OutlookClient/OutlookEvent.cs b/OutlookClient/OutlookEvent.cs
new file mode 100644
index 0000000..f2772cc
--- /dev/null
+++ b/OutlookClient/OutlookEvent.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CalCli.API;
+using CalDav;
+using Outlook = Microsoft.Office.Interop.Outlook;
+
+namespace OutlookClient {
+ public class OutlookEvent : IEvent
+ {
+ public Outlook.AppointmentItem Appointment { get { return appointment; } }
+ Outlook.Application application;
+ Outlook.AppointmentItem appointment;
+ public OutlookEvent(Outlook.Application app)
+ {
+ application = app;
+ appointment = app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem);
+ }
+ public ICollection Alarms
+ {
+ get
+ {
+ return new List {
+ new OutlookAlarm(application)
+ {
+ Action = AlarmActions.DISPLAY,
+ Trigger = new Trigger()
+ {
+ DateTime = appointment.Start.AddMinutes(-appointment.ReminderMinutesBeforeStart)
+ }
+
+ }
+ };
+ }
+
+ set
+ {
+ if (Alarms.Count > 1)
+ throw new Exception("Outlook doesn't support multiple alarms.");
+ else
+ {
+ if (Alarms.Count == 0)
+ appointment.ReminderSet = false;
+ else
+ {
+ appointment.ReminderSet = true;
+ if(value.First().Trigger.DateTime != null)
+ {
+ value.First().Trigger.Duration = value.First().Trigger.DateTime - appointment.Start;
+ }
+ appointment.ReminderMinutesBeforeStart = 1;// (int)value.First().Trigger.Duration.Value.TotalMinutes;
+ }
+ }
+ }
+ }
+
+ public ICollection Categories
+ {
+ get
+ {
+ return new List { appointment.Categories };
+ }
+
+ set
+ {
+ appointment.Categories = "";
+ foreach (string category in value)
+ {
+ appointment.Categories += value + ";";
+ }
+
+ }
+ }
+
+ public DateTime? Created
+ {
+ get
+ {
+ return appointment.CreationTime;
+ }
+
+ set
+ {
+ throw new Exception("Creation time is read only using outlook. It is automatically set. ");
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ return appointment.Body;
+ }
+
+ set
+ {
+ appointment.Body = value;
+ }
+ }
+
+ public DateTime? End
+ {
+ get
+ {
+ return appointment.End;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new Exception("End cannot be null.");
+ appointment.End = (DateTime)value;
+ }
+ }
+
+ public DateTime? Start
+ {
+ get
+ {
+ return appointment.Start;
+ }
+
+ set
+ {
+ if(value == null)
+ throw new Exception("Start cannot be null.");
+ appointment.Start = (DateTime)value;
+
+ }
+ }
+
+ public string Summary
+ {
+ get
+ {
+ return appointment.Subject;
+ }
+
+ set
+ {
+ appointment.Subject = value;
+ }
+ }
+
+ public string UID
+ {
+ get; set;
+ }
+
+ public Uri Url
+ {
+ get
+ {
+ throw new Exception("Url doesn't make sence for outlook calendar.");
+ }
+
+ set
+ {
+ throw new Exception("Url doesn't make sence for outlook calendar.");
+ }
+ }
+ }
+}
diff --git a/OutlookClient/OutlookServer.cs b/OutlookClient/OutlookServer.cs
new file mode 100644
index 0000000..6885282
--- /dev/null
+++ b/OutlookClient/OutlookServer.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using CalCli.API;
+using Outlook = Microsoft.Office.Interop.Outlook;
+
+namespace OutlookClient {
+ public class OutlookServer : IServer
+ {
+ Outlook.Application application = new Outlook.Application();
+ public IConnection Connection
+ {
+ get
+ {
+ return null;
+ }
+
+ set
+ {
+
+ }
+ }
+
+ public Uri Url
+ {
+ get
+ {
+ return null;
+ }
+
+ set
+ {
+
+ }
+ }
+
+ public void CreateCalendar(ICalendar calendar)
+ {
+ throw new Exception("Outlook doesn't support creating calendars.");
+ }
+
+ public ICalendar[] GetCalendars()
+ {
+ return new ICalendar[] { new OutlookCalendar(application) };
+ }
+ }
+}
diff --git a/OutlookClient/OutlookToDo.cs b/OutlookClient/OutlookToDo.cs
new file mode 100644
index 0000000..4fbe74c
--- /dev/null
+++ b/OutlookClient/OutlookToDo.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CalCli.API;
+using Outlook = Microsoft.Office.Interop.Outlook;
+
+namespace OutlookClient {
+ public class OutlookToDo : IToDo{
+ Outlook.TaskItem taskItem;
+
+ public ICollection Categories
+ {
+ get
+ {
+ return new List { taskItem.Categories };
+ }
+
+ set
+ {
+ taskItem.Categories = "";
+ foreach (string category in value)
+ {
+ taskItem.Categories += value + ";";
+ }
+
+ }
+ }
+
+ public DateTime? Completed
+ {
+ get
+ {
+ return taskItem.DateCompleted;
+ }
+
+ set
+ {
+ if(value == null)
+ throw new Exception("Completion date cannot be null.");
+ taskItem.DateCompleted = (DateTime)value;
+ }
+ }
+
+ public DateTime? Due
+ {
+ get
+ {
+ return taskItem.DueDate;
+ }
+
+ set
+ {
+
+ if (value == null)
+ throw new Exception("Due cannot be null.");
+ taskItem.DueDate = (DateTime)value;
+ }
+ }
+
+ public int? Priority
+ {
+ get
+ {
+ throw new Exception("Not supported for outlook.");
+ }
+
+ set
+ {
+ throw new Exception("Not supported for outlook.");
+ }
+ }
+
+ public int? Sequence
+ {
+ get
+ {
+ return (int)(taskItem.DueDate - taskItem.StartDate).TotalSeconds;
+ }
+
+ set
+ {
+ if(taskItem.DueDate != null && taskItem.StartDate != null)
+ {
+ throw new Exception("Dates are already set.");
+ }
+
+ }
+ }
+
+
+ public DateTime? Start
+ {
+ get
+ {
+ return taskItem.StartDate;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new Exception("Start cannot be null.");
+ taskItem.StartDate = (DateTime)value;
+
+ }
+ }
+
+ public Statuses? Status
+ {
+ get
+ {
+ if (taskItem.Complete)
+ return Statuses.COMPLETED;
+ else
+ return Statuses.NEEDS_ACTION;
+ }
+
+ set
+ {
+ taskItem.Complete = value == Statuses.COMPLETED;
+ }
+ }
+
+ public string Summary
+ {
+ get
+ {
+ return taskItem.Subject;
+ }
+
+ set
+ {
+ taskItem.Subject = value;
+ }
+ }
+
+ public string UID
+ {
+ get; set;
+ }
+ public Outlook.TaskItem TaskItem
+ {
+ get
+ {
+ return taskItem;
+ }
+ }
+
+ public OutlookToDo(Outlook.Application app) {
+ taskItem = app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olTaskItem);
+ }
+ }
+}
diff --git a/OutlookClient/Properties/AssemblyInfo.cs b/OutlookClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..cf045c2
--- /dev/null
+++ b/OutlookClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OutlookClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OutlookClient")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("01af789a-f9ce-47f7-a66c-d3bae82aecc3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OutlookClient/packages.config b/OutlookClient/packages.config
new file mode 100644
index 0000000..2c7ff9d
--- /dev/null
+++ b/OutlookClient/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f093b01
--- /dev/null
+++ b/README.md
@@ -0,0 +1,10 @@
+# CalDav
+CalDav server and client libraries. It supports Google, iCloud, Yahoo and Outlook calendars.
+
+# Installation
+
+It is hosted on [NuGet gallery](https://www.nuget.org/packages/CalCli/) and can be installed as is described there.
+
+# Development
+
+Any pull requests whould be appreciated.
diff --git a/Tests/IRLTests.cs b/Tests/IRLTests.cs
index 98539fa..4c13af6 100644
--- a/Tests/IRLTests.cs
+++ b/Tests/IRLTests.cs
@@ -10,7 +10,7 @@ public class IRLTests {
public void ParseFeed() {
var calendar = new CalDav.Calendar();
var serializer = new Serializer();
- var req = System.Net.HttpWebRequest.Create("http://www.nasa.gov/templateimages/redesign/calendar/iCal/nasa_calendar.ics");
+ var req = System.Net.HttpWebRequest.Create("https://canada-holidays.ca/ics");
using (var res = req.GetResponse())
using (var str = res.GetResponseStream())
using (var rdr = new System.IO.StreamReader(str))
@@ -24,13 +24,13 @@ public void ParseICal() {
//http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html
//http://blogs.nologin.es/rickyepoderi/index.php?/archives/15-Introducing-CalDAV-Part-II.html
- var server = new CalDav.Client.Server("https://www.google.com/calendar/dav/andy.edinborough@gmail.com/events/", "andy.edinborough@gmail.com", "Gboey6Emo!");
- var calendars = server.GetCalendars();
- calendars.ShouldNotBeEmpty();
+ //var server = new CalDav.Client.Server("https://www.google.com/calendar/dav/andy.edinborough@gmail.com/events/", "andy.edinborough@gmail.com", "Gboey6Emo!");
+ //var calendars = server.GetCalendars();
+ //calendars.ShouldNotBeEmpty();
- var calendar = calendars[0];
- var events = calendar.Search(CalendarQuery.SearchEvents(new DateTime(2012, 8, 1), new DateTime(2012, 8, 31))).ToArray();
- events.Length.ShouldBeGreaterThan(0);
+ //var calendar = calendars[0];
+ //var events = calendar.Search(CalendarQuery.SearchEvents(new DateTime(2012, 8, 1), new DateTime(2012, 8, 31))).ToArray();
+ //events.Length.ShouldBeGreaterThan(0);
}
}
diff --git a/Tests/ParsingBasic.cs b/Tests/ParsingBasic.cs
index 10acca5..6ba28c1 100644
--- a/Tests/ParsingBasic.cs
+++ b/Tests/ParsingBasic.cs
@@ -1,4 +1,5 @@
-using CalDav;
+using CalCli.API;
+using CalDav;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using System;
@@ -65,7 +66,7 @@ public void Trigger() {
text = "TRIGGER;RELATED=END:-P1W3DT2H3M45S";
trigger = Deserialize(text);
- trigger.Related.ShouldBe(CalDav.Trigger.Relateds.End);
+ trigger.Related.ShouldBe(Relateds.End);
trigger.Duration.ShouldBe(-(new TimeSpan(1 * 7 + 3, 2, 3, 45, 0)));
text2 = Serialize("TRIGGER", trigger);
text2.ShouldBe(text);
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 0c1ddd8..9683fc7 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -8,7 +8,7 @@
Properties
Tests
Tests
- v4.5
+ v4.8
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10.0
@@ -18,6 +18,7 @@
UnitTest
..\
true
+
true
@@ -63,6 +64,10 @@
+
+ {2c258fae-97ed-4916-b5a3-4723700d675d}
+ CalCli.API
+
{1b9b42a0-a34b-4bf6-a5d5-21c46ed0d9b3}
CalDav.Client
diff --git a/Tests/app.config b/Tests/app.config
index 56f696d..8e3607f 100644
--- a/Tests/app.config
+++ b/Tests/app.config
@@ -1,11 +1,11 @@
-
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/UpgradeLog.htm b/UpgradeLog.htm
new file mode 100644
index 0000000..728ea2b
Binary files /dev/null and b/UpgradeLog.htm differ