Skip to content

Commit

Permalink
Ics converter (#38)
Browse files Browse the repository at this point in the history
* feat(scheduler): ics-converter project

* chore(ics-converter): working example and readme file

* chore(scheduler): clean up unnecessary files, fix folder name, touch up readme

Co-authored-by: Marin Bratanov <[email protected]>
  • Loading branch information
svdimitr and marin-bratanov authored Jun 3, 2020
1 parent c05f671 commit 90e28fc
Show file tree
Hide file tree
Showing 31 changed files with 1,481 additions and 0 deletions.
25 changes: 25 additions & 0 deletions scheduler/ICS-data-convertion/ICS_Data_Convertion.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30028.174
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICS_Data_Convertion", "ICS_Data_Convertion\ICS_Data_Convertion.csproj", "{08EE7DC7-BE8A-42DA-B9C7-58482CE05656}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{08EE7DC7-BE8A-42DA-B9C7-58482CE05656}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08EE7DC7-BE8A-42DA-B9C7-58482CE05656}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08EE7DC7-BE8A-42DA-B9C7-58482CE05656}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08EE7DC7-BE8A-42DA-B9C7-58482CE05656}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FF50A80F-C083-4223-82F8-557652F30E94}
EndGlobalSection
EndGlobal
11 changes: 11 additions & 0 deletions scheduler/ICS-data-convertion/ICS_Data_Convertion/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ical.marudot.com//iCal Event Maker
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Helsinki
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Helsinki
X-LIC-LOCATION:Europe/Helsinki
BEGIN:DAYLIGHT
TZOFFSETFROM:+0200
TZOFFSETTO:+0300
TZNAME:EEST
DTSTART:19700329T030000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0300
TZOFFSETTO:+0200
TZNAME:EET
DTSTART:19701025T040000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20200602T045808Z
UID:20200602T045808Z[email protected]
DTSTART;TZID=Europe/Helsinki:20200608T050000
RRULE:FREQ=DAILY
DTEND;TZID=Europe/Helsinki:20200608T060000
SUMMARY:Morning run
DESCRIPTION:Some time to clear the head and exercise.
LOCATION:South Park
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20200602T045808Z
UID:20200602T045808Z[email protected]
DTSTART;TZID=Europe/Helsinki:20200608T120000
DTEND;TZID=Europe/Helsinki:20200608T120000
SUMMARY:Get photos
DESCRIPTION:Get the printed photos from last week's holiday.
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20200602T045808Z
UID:20200602T045808Z[email protected]
DTSTART;TZID=Europe/Helsinki:20200610T120000
DTEND;TZID=Europe/Helsinki:20200610T120000
SUMMARY:Interview with new recruit
DESCRIPTION:See if John will be a suitable match for our team.
LOCATION:Progress Office
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20200602T045808Z
UID:20200602T045808Z[email protected]
DTSTART;TZID=Europe/Helsinki:20200610T160000
DTEND;TZID=Europe/Helsinki:20200610T160000
SUMMARY:Brunch with HR
DESCRIPTION:Performance evaluation of the new recruit.
LOCATION:Progress Office
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20200602T045808Z
UID:20200602T045808Z[email protected]
DTSTART;TZID=Europe/Helsinki:20200612T130000
DTEND;TZID=Europe/Helsinki:20200612T130000
SUMMARY:Vet visit
DESCRIPTION:The cat needs vaccinations and her teeth checked.
END:VEVENT
END:VCALENDAR
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace ICS_Data_Convertion.Extensions
{
public static class ConverterExtensions
{
public static DateTime? ParseDateFromICalString(this string value)
{
var success = DateTime.TryParseExact(value, "yyyyMMddTHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTime date);

return success ? (DateTime?)date : null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Appointments\**" />
<Content Remove="Appointments\**" />
<EmbeddedResource Remove="Appointments\**" />
<None Remove="Appointments\**" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Telerik.UI.for.Blazor" Version="2.14.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using ICS_Data_Convertion.Extensions;
using ICS_Data_Convertion.Services;

namespace ICS_Data_Convertion.Models
{
public class CalendarAppointment
{
private string _dtStart { get; set; }
private string _dtEnd { get; set; }
public string DTStart
{
get
{
return _dtStart;
}
set
{
_dtStart = value;
//The ParseDateFromICalString extension method can be observed under the Extensions folder.
Start = value.ParseDateFromICalString();
}
}
public string DTEnd
{
get
{
return _dtEnd;
}
set
{
_dtEnd = value;
//The ParseDateFromICalString extension method can be observed under the Extensions folder.
End = value.ParseDateFromICalString();
}
}

public Guid? Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
public string RecurrenceRule { get; set; }
public Guid? RecurrenceId { get; set; }
public bool IsAllDay { get; set; }

public CalendarAppointment()
{
Id = new Guid();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@page "/"

@inject SchedulerAppointmentsService appointmentService

<TelerikScheduler Data="@Appointments"
@bind-Date="@StartDate"
@bind-View="@CurrView"
Height="600px"
Width="800px">
<SchedulerViews>
<SchedulerDayView StartTime="@DayStart" />
<SchedulerWeekView StartTime="@DayStart" />
<SchedulerMultiDayView StartTime="@DayStart" NumberOfDays="10" />
<SchedulerMonthView />
</SchedulerViews>
</TelerikScheduler>

@code {
public DateTime StartDate { get; set; } = new DateTime(2020, 6, 8);
public SchedulerView CurrView { get; set; } = SchedulerView.Month;
public DateTime DayStart { get; set; } = new DateTime(2020, 6, 7, 8, 0, 0);//the time portion is important
//We are populating this data source from a service
public List<CalendarAppointment> Appointments { get; set; }

protected override Task OnInitializedAsync()
{
Appointments = appointmentService.GetAppointments();
return base.OnInitializedAsync();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@page "/"
@namespace ICS_Data_Convertion.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ICS_Data_Convertion</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<script src="_content/Telerik.UI.for.Blazor/js/telerik-blazor.js" defer></script>
<link rel="stylesheet" href="_content/Telerik.UI.for.Blazor/css/kendo-theme-default/all.css" />
</head>
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

<script src="_framework/blazor.server.js"></script>
</body>
</html>
28 changes: 28 additions & 0 deletions scheduler/ICS-data-convertion/ICS_Data_Convertion/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ICS_Data_Convertion
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:21037",
"sslPort": 44361
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ICS_Data_Convertion": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json.Linq;
using ICS_Data_Convertion.Models;
using System.Text.RegularExpressions;
using System.Globalization;

namespace ICS_Data_Convertion.Services
{
public class SchedulerAppointmentsService
{
public string line;

//Replace this path with your actual path.
//When published this path should be taken from the hostingenvironment
//https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvironment.contentrootpath?view=aspnetcore-3.1
public static string path = Path.Combine(Directory.GetCurrentDirectory(), "Calendar\\myevents.ics");

public List<CalendarAppointment> GetAppointments()
{
return ReadICalAppointments();
}

public List<CalendarAppointment> ReadICalAppointments()
{
List<CalendarAppointment> calendarAppointments = new List<CalendarAppointment>();

StreamReader file = new StreamReader(path);

var data = file.ReadToEnd();
var appointments = Regex.Matches(data, @"BEGIN:VEVENT([\S\s]*?)END:VEVENT", RegexOptions.Multiline).Select(match => match.Value);

foreach (var appointment in appointments)
{
calendarAppointments.Add(ReadICalAppointment(appointment));
}

return calendarAppointments;
}

public CalendarAppointment ReadICalAppointment(string appointment)
{
CalendarAppointment calendarAppointment = new CalendarAppointment();

calendarAppointment.DTStart = Regex.Match(appointment, @"(?<=DTSTART([\S\s]*?):).*").Value;
calendarAppointment.DTEnd = Regex.Match(appointment, @"(?<=DTEND([\S\s]*?):).*").Value;
calendarAppointment.Title = Regex.Match(appointment, @"(?<=SUMMARY:).*").Value;
calendarAppointment.Description = Regex.Match(appointment, @"(?<=DESCRIPTION:).*").Value;
calendarAppointment.RecurrenceRule = Regex.Match(appointment, @"(?<=RRULE:).*").Value;

return calendarAppointment;
}
}
}
Loading

0 comments on commit 90e28fc

Please sign in to comment.