Skip to content
This repository was archived by the owner on Feb 15, 2022. It is now read-only.

Added World Map to Academic Excellence Page #513

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
},
"dependencies": {
"bs-platform": "^9.0.2",
"leaflet": "^1.7.1",
"next": "^11.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"react-leaflet": "^3.2.0"
},
"dependenciesDescription": {
"bs-platform": "This a regular dependency because the included standard libraries are used during runtime"
Expand Down
55 changes: 36 additions & 19 deletions pages/[lang]/principles/academic.res
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ open! Import

module T = {
type t = {acads: array<Ood.Academic_institution.t>}

let s = React.string
include Jsonable.Unsafe
//PageBasicDetail Module
let map: React.component<{
"props": Map.props,
}> = Next.Dynamic.dynamic(
() => Next.Dynamic.import_("../../../src/Map.js"),
Next.Dynamic.options(~ssr=false, ~loading=() => <p> {s("loading...")} </p>, ()),
)
module PageBasic = {
@react.component
let make = (~lang) => <>
Expand Down Expand Up @@ -125,31 +131,42 @@ module T = {
</>
}
}
//TODO: Implement Map
module Map = {
@react.component
let make = (~marginBottom=?) => <>
<SectionContainer.MediumCentered ?marginBottom paddingX="px-12">
<h2 className="mb-16 text-grey-900 text-3xl mb-5 lg:text-4xl font-bold text-center">
{React.string("OCaml Courses around the World")}
</h2>
</SectionContainer.MediumCentered>
<SectionContainer.ResponsiveCentered ?marginBottom>
// TODO: try switching to a grid
<div className="bg-white flex flex-wrap justify-center lg:justify-between ">
<img src={`/static/worldmap.jpg`} alt="" />
</div>
</SectionContainer.ResponsiveCentered>
</>
}

module Params = Pages.Params.Lang

@react.component
let make = (~content, ~params as {Params.lang: lang}) => <>
<PageBasic lang />
<University marginBottom={Tailwind.Breakpoint.make(#mb10, ~lg=#mb32, ())} content />
<Map marginBottom={Tailwind.Breakpoint.make(#mb10, ~lg=#mb32, ())} />
{React.createElement(
map,
Map.makeProps(
~props={
"marginBottom": Some({Tailwind.Breakpoint.make(#mb10, ~lg=#mb32, ())}),
"zoom": 0.5,
"center": {
Mapbinding.LatLng.lat: 0.0,
lng: 0.0,
},
"position": content.acads,
"maxBound": {
Mapbinding.LatLng.mib: {
lat: 85.0511,
lng: -180.0,
},
Mapbinding.LatLng.mab: {
lat: -85.0511,
lng: 180.0,
},
},
"minZoom": 1.9,
"scrollWheelZoom": true,
"attribution": "<a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors",
"url": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
},
(),
),
)}
</>

let contentEn = {
Expand Down
Binary file added public/static/marker-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/users/r2c.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions src/Map.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
let s = React.string
module MapContainer = Mapbinding.MapContainer
module TileLayer = Mapbinding.TileLayer
module Popup = Mapbinding.Popup
module Marker = Mapbinding.Marker

module MarkArray = {
type t = {
positions: Mapbinding.LatLng.t,
name: string,
}
}

type props = {
"marginBottom": option<Tailwind.Breakpoint.t<Tailwind.Margin.Bottom.t>>,
"zoom": float,
"minZoom": float,
"center": Mapbinding.LatLng.t,
"position": array<Ood.Academic_institution.t>,
"scrollWheelZoom": bool,
"attribution": string,
"url": string,
"maxBound": Mapbinding.LatLng.bound,
}
@react.component
let make = (~props: props) => {
let marginBottom = props["marginBottom"]
let zoom = props["zoom"]
let center = props["center"]
let acads = props["position"]
let minZoom = props["minZoom"]
let attribution = props["attribution"]
let url = props["url"]
let maxBound = props["maxBound"]
let scrollWheelZoom = props["scrollWheelZoom"]
let options = {
Mapbinding.iconUrl: "/static/marker-icon.png",
iconSize: {
x: 25.0,
y: 46.0,
},
iconAnchor: {
x: 13.0,
y: 46.0,
},
}
let icon = Mapbinding.icon(Mapbinding.leaflet, ~options)
let p = acads->Belt.Array.map((c: Ood.Academic_institution.t) => {
MarkArray.name: c.Ood.Academic_institution.name,
MarkArray.positions: {
Mapbinding.LatLng.lat: switch c.Ood.Academic_institution.location {
| None => 0.0
| Some(location) => location.lat
},
lng: switch c.Ood.Academic_institution.location {
| None => 0.0
| Some(location) => location.long
},
},
})

<>
<SectionContainer.MediumCentered ?marginBottom paddingX="px-12">
<h2 className="mb-16 text-grey-900 text-3xl mb-5 lg:text-4xl font-bold text-center">
{s("OCaml Courses around the World")}
</h2>
</SectionContainer.MediumCentered>
<SectionContainer.ResponsiveCentered ?marginBottom>
// TODO: try switching to a grid
<div className="bg-white flex-wrap justify-center lg:justify-between m-8 ">
<MapContainer center zoom scrollWheelZoom maxBounds=maxBound minZoom className="h-160">
<TileLayer attribution url noWrap=true />
{p
|> Array.map(c =>
<Marker key={c.name} position=c.MarkArray.positions icon>
<Popup className="h-16 font-bold text-md text-center ">
{React.string(c.name)}
</Popup>
</Marker>
)
|> React.array}
</MapContainer>
</div>
</SectionContainer.ResponsiveCentered>
</>
}
let default = make
21 changes: 21 additions & 0 deletions src/Map.resi
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module MarkArray: {
type t = {
positions: Mapbinding.LatLng.t,
name: string,
}
}
type props = {
"marginBottom": option<Tailwind.Breakpoint.t<Tailwind.Margin.Bottom.t>>,
"zoom": float,
"minZoom": float,
"center": Mapbinding.LatLng.t,
"position": array<Ood.Academic_institution.t>,
"scrollWheelZoom": bool,
"attribution": string,
"url": string,
"maxBound": Mapbinding.LatLng.bound,
}

@react.component
let make: (~props: props) => React.element
let default: {"props": props} => React.element
72 changes: 72 additions & 0 deletions src/Mapbinding.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
module LatLng = {
type t = {
lat: float,
lng: float,
}
type bound = {
mib: t,
mab: t,
}
}
module Point = {
type t = {
x: float,
y: float,
}
}
module MapContainer = {
@module("react-leaflet") @react.component
external make: (
~className: string=?,
~center: LatLng.t,
~zoom: float,
~zoomControl: bool=?,
~scrollWheelZoom: bool,
~id: string=?,
~minZoom: float,
~maxBounds: LatLng.bound,
~children: React.element,
) => React.element = "MapContainer"
}
module TileLayer = {
@module("react-leaflet") @react.component
external make: (~attribution: string=?, ~noWrap: bool, ~url: string) => React.element =
"TileLayer"
}
//Abstract Icon type
type icon

type iconOptions = {iconUrl: string, iconSize: Point.t, iconAnchor: Point.t}

// Abstract Leaflet Object type
type leaflet

// Binding to the Leaflet function `icon` which creates an Icon object
@send external icon: (leaflet, ~options: iconOptions) => icon = "icon"
@val external leaflet: leaflet = "L"

module Marker = {
@module("react-leaflet") @react.component
external make: (~position: LatLng.t, ~icon: icon=?, ~children: React.element=?) => React.element =
"Marker"
}

module Popup = {
@module("react-leaflet") @react.component
external make: (
~maxWidth: int=?,
~minWidth: int=?,
~maxHeight: int=?,
~autoPan: bool=?,
~autoPanPaddingTopLeft: Point.t=?,
~autoPanPaddingBottomRight: Point.t=?,
~autoPanPadding: Point.t=?,
~keepInView: bool=?,
~closeButton: bool=?,
~autoClose: bool=?,
~closeOnEscapeKey: bool=?,
~closeOnClick: bool=?,
~className: string=?,
~children: React.element=?,
) => React.element = "Popup"
}
70 changes: 70 additions & 0 deletions src/Mapbinding.resi
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module LatLng: {
type t = {
lat: float,
lng: float,
}
type bound = {
mib: t,
mab: t,
}
}
module Point: {
type t = {
x: float,
y: float,
}
}
module MapContainer: {
@react.component
let make: (
~className: string=?,
~center: LatLng.t,
~zoom: float,
~zoomControl: bool=?,
~scrollWheelZoom: bool,
~id: string=?,
~minZoom: float,
~maxBounds: LatLng.bound,
~children: React.element,
) => React.element
}
module TileLayer: {
@react.component
let make: (~attribution: string=?, ~noWrap: bool, ~url: string) => React.element
}
//Abstract Icon type
type icon

type iconOptions = {iconUrl: string, iconSize: Point.t, iconAnchor: Point.t}

// Abstract Leaflet Object type
type leaflet

// Binding to the Leaflet function `icon` which creates an Icon object
@send external icon: (leaflet, ~options: iconOptions) => icon = "icon"
@val external leaflet: leaflet = "L"

module Marker: {
@react.component
let make: (~position: LatLng.t, ~icon: icon=?, ~children: React.element=?) => React.element
}

module Popup: {
@react.component
let make: (
~maxWidth: int=?,
~minWidth: int=?,
~maxHeight: int=?,
~autoPan: bool=?,
~autoPanPaddingTopLeft: Point.t=?,
~autoPanPaddingBottomRight: Point.t=?,
~autoPanPadding: Point.t=?,
~keepInView: bool=?,
~closeButton: bool=?,
~autoClose: bool=?,
~closeOnEscapeKey: bool=?,
~closeOnClick: bool=?,
~className: string=?,
~children: React.element=?,
) => React.element
}
15 changes: 15 additions & 0 deletions src/Next.res
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,18 @@ module Head = {
@module("next/head") @react.component
external make: (~children: React.element) => React.element = "default"
}

module Dynamic = {
@deriving(abstract)
type options = {
@optional
ssr: bool,
@optional
loading: unit => React.element,
}

@module("next/dynamic")
external dynamic: (unit => Js.Promise.t<'a>, options) => 'a = "default"

@val external import_: string => Js.Promise.t<'a> = "import"
}
14 changes: 14 additions & 0 deletions src/Next.resi
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,17 @@ module Head: {
@react.component
let make: (~children: React.element) => React.element
}
module Dynamic: {
@deriving(abstract)
type options = {
@optional
ssr: bool,
@optional
loading: unit => React.element,
}

@module("next/dynamic")
external dynamic: (unit => Js.Promise.t<'a>, options) => 'a = "default"

@val external import_: string => Js.Promise.t<'a> = "import"
}
5 changes: 5 additions & 0 deletions styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
@import "./_hljs.css";
@import "./_fonts.css";

@import 'leaflet/dist/leaflet.css';

@tailwind utilities;


nav.toc {
@apply hidden lg:sticky lg:self-start lg:top-2 lg:flex lg:flex-col lg:col-span-2 border-r border-gray-200 pt-5 pb-4 overflow-y-auto
}
Expand All @@ -30,3 +33,5 @@ nav.toc > ul > li > ul > li {
nav.toc > ul > li > ul > li > ul > li {
@apply pl-8
}


Loading