Skip to content

Instantly share code, notes, and snippets.

@ptrelford
Last active April 23, 2016 16:36
Show Gist options
  • Save ptrelford/75fdf3f4c5dc9254736d88d35551c116 to your computer and use it in GitHub Desktop.
Save ptrelford/75fdf3f4c5dc9254736d88d35551c116 to your computer and use it in GitHub Desktop.
Generates a responsive timeline of F# meetups around the world
#r @"packages/FSharp.Data/lib/net40/FSharp.Data.dll"
#load "FsHtml.fs" // "paket-files/ptrelford/FsHtml/src/FsHtml.fs"
open System
open FSharp.Data
open FsHtml
type Events = JsonProvider<"https://api.meetup.com/fsharplondon/events?&sign=true&photo-host=public&page=200&status=past,upcoming">
let meetups = [
"fsharplondon";"FSharpBristol";"Cambridge-F-Community";"F-Coventry"
"fsharpsydney";"Auckland-F-Programming-Meetup";"FSharpKorea"
"Gauteng-F-Programming-Meetup";"FSharp-Toronto";
"Chennai-F-User-Group";"Bangalore-fsharp-Programming-Meetup"
"MoedegruppeFunktionelleKoebenhavnere";"OsloFSharp";"FSharpHelsinki"
"zurich-fsharp-users";"Functional-Programming-in-F";"fsharp-toulouse"
"F-un-and-More-Rhein-Main";"FSharp-Vienna";"fsharpminsk";"Kyiv-FSharp-Group"
"Athens-FSharp";"FSharp-Italia";"FSharp-Milano"
"madrid-fsharp";"FSharp-Barcelona"
"FSharp-Bogota";"F-Programming-User-Group-Oaxaca"
"Chicago-F-Users";"Dallas-F-User-Group";"Houston-FSharp-User-Group"
"Austin-F-Meetup";"nashfsharp";"IndianapolisFSharpDevelopers"
"slc-fsharp";"Columbus-F-Sharp-User-Group"
"sfsharp"; "Silicon-Valley-FSharp"; "Portland-F-Meetup-Group";"FSharpSeattle"
"nyc-fsharp";"DC-fsharp";"Detroit-F-Meetup";"Philly-FSharp";
"New-England-F-Users-Group"
]
type Event<'a> = {
StartTime : DateTime
Link : string
Title : string
Summary : string
Location : string
Venue : 'a
}
let events =
[|for meetup in meetups |> Seq.distinct do
let events = Events.Load(sprintf "https://api.meetup.com/%s/events?&sign=true&photo-host=public&page=200&status=past,upcoming" meetup)
for event in events ->
let epoch = System.DateTime(1970,1,1)
let startTime = epoch.AddMilliseconds(float event.Time + float event.UtcOffset)
let city =
match event.Venue with
| Some venue -> venue.City
| None -> event.Group.Name
{ StartTime=startTime; Link=event.Link; Title=event.Name; Summary=event.Description; Location=city; Venue=event.Venue}
|]
|> Array.where (fun x -> x.StartTime < DateTime.Now.AddMonths(1))
|> Array.sortByDescending (fun x -> x.StartTime)
let blocks = [
for event in events ->
div [
"itemscope"%=""
"itemtype"%="http://schema.org/Event"
"class"%="cd-timeline-block"
// Location
a [
yield! ["itemprop"%="location";"itemscope"%="";"itemtype"%="https://schema.org/Place"]
yield "target"%="_blank"
match event.Venue with
| Some venue ->
yield "href"%=(sprintf "https://www.google.com/maps/@%M,%M,8z" venue.Lat venue.Lon)
//yield "href"%=(sprintf "https://www.google.com/maps/?q=%M,%M" venue.Lat venue.Lon) // with pin
yield "title"%=(venue.Name+", "+venue.City)
| None ->
yield "href"%=event.Link
yield div [
yield "class"%="cd-timeline-img"
yield img ["src"%="img/cd-icon-location.svg"]
]
// Location name
match event.Venue with
| Some venue ->
yield meta ["itemprop"%="name";"content"%=venue.Name]
| None ->
yield meta ["itemprop"%="name";"content"%=event.Location]
// Postal Adress
yield span [
yield! ["itemprop"%="address";"itemscope"%="";"itemtype"%="https://schema.org/PostalAddress"]
match event.Venue with
| Some venue ->
yield meta ["itemprop"%="addressLocality";"content"%=venue.City]
yield meta ["itemprop"%="addressCountry";"content"%=venue.Country.ToUpper()]
| None ->
yield meta ["itemprop"%="name";"content"%=event.Location]
]
]
// Content
div [
"class"%="cd-timeline-content"
div [
h2 %event.Location
]
br []
a [
"itemprop"%="url";
"href"%=(event.Link);
span ["itemprop"%="name";Text event.Title]
]
br []
span [
"itemprop"%="startDate"
"class"%="cd-date"
Text (event.StartTime.ToString("D"))
]
]
]
]
let timeline = section ("id"%="cd-timeline"::"class"%="cd-container"::blocks)
// Based on CodyHouse Vertical Timeline sample: https://codyhouse.co/gem/vertical-timeline/
let html =
"""<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href='http://fonts.googleapis.com/css?family=Droid+Serif|Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/reset.css"> <!-- CSS reset -->
<link rel="stylesheet" href="css/style.css"> <!-- Resource style -->
<script src="js/modernizr.js"></script> <!-- Modernizr -->
<title>F# Meetup Timeline</title>
</head>
<body>
<header>
<h1>F# Meetup Timeline</h1>
</header>
{timeline}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="js/main.js"></script> <!-- Resource jQuery -->
</body>
</html>""".Replace("{timeline}", timeline.ToString())
open System.IO
let path = Path.Combine(__SOURCE_DIRECTORY__,@"vertical-timeline\vertical-timeline\index.html")
System.IO.File.WriteAllText(path, html)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment