mirror of
https://github.com/avinal/avinal.github.io.git
synced 2026-07-04 15:50:08 +05:30
feat: use new theme for the website
Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com> rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
module Components.Footer exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class, href, src, target)
|
||||
import Utils.Constants exposing (IconLink, Link, footerLinks)
|
||||
import Html.Attributes exposing (rel)
|
||||
|
||||
|
||||
singleLink : Link -> Html msg
|
||||
singleLink link =
|
||||
Html.a
|
||||
[ href link.url
|
||||
, class "underline decoration-cyan-500 hover:decoration-pink-500 text-xl"
|
||||
, target "_blank"
|
||||
, rel "noopener noreferrer"
|
||||
]
|
||||
[ Html.text link.text ]
|
||||
|
||||
iconedLink : IconLink -> Html msg
|
||||
iconedLink iconLink =
|
||||
Html.a [ href iconLink.url, class "hover:text-pink-500 inline-flex text-2xl p-3 no-underline" ]
|
||||
[ Html.i [ class iconLink.icon ] []
|
||||
]
|
||||
|
||||
|
||||
footerLinksToSide : Html msg
|
||||
footerLinksToSide =
|
||||
Html.div [ class "fixed bottom-0 left-0 bg-neutral-900 p-4 w-full border-t border-cyan-500" ]
|
||||
[ Html.div [ class "mx-auto flex justify-center space-x-6 text-gray-400" ]
|
||||
(List.map singleLink <|
|
||||
{ text = "Home", url = "/" }
|
||||
:: footerLinks
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
iconLinkToCenter : Html msg
|
||||
iconLinkToCenter =
|
||||
Html.div [ class "flex justify-center flex-wrap" ] (List.map iconedLink Utils.Constants.iconLinks)
|
||||
|
||||
|
||||
avatarAndLinks : Html msg
|
||||
avatarAndLinks =
|
||||
Html.div []
|
||||
[ Html.div [ class "flex flex-col md:space-y-0 md:space-x-6 md:flex-row border-t border-neutral-700" ]
|
||||
[ Html.img
|
||||
[ class "self-center flex-shrink-0 w-24 h-24 border rounded-full md:justify-self-start"
|
||||
, src "https://github.com/avinal.png"
|
||||
]
|
||||
[]
|
||||
, Html.div [ class "flex flex-col self-center" ]
|
||||
[ Html.h4 [ class "text-xl font-semibold sm:justify-self-start" ] [ Html.text "Avinal Kumar" ]
|
||||
, Html.p [ class "text-gray-400" ]
|
||||
[ Html.text "I am a Associate Software Engineer at Red Hat and I work for Hybrid Cloud Engineering. I contribute to Open Source projects and write blogs in tech and literature."
|
||||
]
|
||||
]
|
||||
]
|
||||
, Html.div [ class "flex justify-center align-center text-neutral-700 text-xl" ] (List.map iconedLink Utils.Constants.iconLinks)
|
||||
]
|
||||
@@ -1,93 +0,0 @@
|
||||
module Layouts.Home exposing (Model, Msg, Props, layout)
|
||||
|
||||
import Components.Footer exposing (iconLinkToCenter)
|
||||
import Effect exposing (Effect)
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class, href, target, rel)
|
||||
import Layout exposing (Layout)
|
||||
import Route exposing (Route)
|
||||
import Shared
|
||||
import Utils.Constants exposing (..)
|
||||
import View exposing (View)
|
||||
import Html.Attributes exposing (target)
|
||||
|
||||
|
||||
type alias Props =
|
||||
{}
|
||||
|
||||
|
||||
layout : Props -> Shared.Model -> Route () -> Layout () Model Msg contentMsg
|
||||
layout props shared route =
|
||||
Layout.new
|
||||
{ init = init
|
||||
, update = update
|
||||
, view = view
|
||||
, subscriptions = subscriptions
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- MODEL
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
init : () -> ( Model, Effect Msg )
|
||||
init _ =
|
||||
( {}
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= ReplaceMe
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
ReplaceMe ->
|
||||
( model
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : { toContentMsg : Msg -> contentMsg, content : View contentMsg, model : Model } -> View contentMsg
|
||||
view { toContentMsg, model, content } =
|
||||
let
|
||||
footerLinkToCenter : Link -> Html msg
|
||||
footerLinkToCenter link =
|
||||
Html.a
|
||||
[ href link.url
|
||||
, class "underline decoration-cyan-500 hover:decoration-pink-500 inline-flex text-xl p-3"
|
||||
, target "_blank"
|
||||
, rel "noopener noreferrer"
|
||||
]
|
||||
[ Html.text link.text ]
|
||||
in
|
||||
{ title = content.title
|
||||
, body =
|
||||
[ Html.section [ class "flex items-center justify-center flex-col h-screen text-gray-400" ]
|
||||
[ Html.header [ class "object-cover object-center p-8" ] content.body
|
||||
, iconLinkToCenter
|
||||
, Html.div [ class "text-center text-xl p-2" ] [ Html.text "Avinal Kumar, Software Engineer II at Red Hat, Open Sourcerer" ]
|
||||
, Html.footer [ class "flex justify-center flex-wrap" ]
|
||||
(List.map footerLinkToCenter Utils.Constants.footerLinks)
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
module Pages.Home_ exposing (Model, Msg, page)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Effect exposing (Effect)
|
||||
import Html exposing (Html)
|
||||
import Html.Events exposing (onClick, onMouseLeave)
|
||||
import Layouts
|
||||
import Page exposing (Page)
|
||||
import Route exposing (Route)
|
||||
import Shared
|
||||
import Svg exposing (..)
|
||||
import Svg.Attributes as SA
|
||||
import Svg.Events as SE
|
||||
import Time
|
||||
import Utils.Constants exposing (nameMatrix)
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Route () -> Page Model Msg
|
||||
page _ _ =
|
||||
Page.new
|
||||
{ init = init
|
||||
, update = update
|
||||
, subscriptions = subscriptions
|
||||
, view = view
|
||||
}
|
||||
|> Page.withLayout layout
|
||||
|
||||
|
||||
|
||||
-- LAYOUT
|
||||
|
||||
|
||||
layout : Model -> Layouts.Layout Msg
|
||||
layout _ =
|
||||
Layouts.Home
|
||||
{}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type Cell
|
||||
= Alive
|
||||
| Dead
|
||||
|
||||
|
||||
type alias Universe a =
|
||||
{ space : Array a
|
||||
, width : Int
|
||||
, height : Int
|
||||
}
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ universe : Universe Cell
|
||||
, generations : Int
|
||||
, generating : Bool
|
||||
}
|
||||
|
||||
|
||||
cellSize : Int
|
||||
cellSize =
|
||||
10
|
||||
|
||||
|
||||
init : () -> ( Model, Effect Msg )
|
||||
init () =
|
||||
( { universe = bigBang 30 30 Dead
|
||||
, generating = False
|
||||
, generations = 0
|
||||
}
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= Ressurect Int Int
|
||||
| NextGeneration
|
||||
| LiveLife
|
||||
| Apocalypse
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
Ressurect x y ->
|
||||
( { model
|
||||
| universe =
|
||||
buildRelationship model.universe
|
||||
x
|
||||
y
|
||||
invertLife
|
||||
}
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
NextGeneration ->
|
||||
let
|
||||
universe =
|
||||
nextGeneration model.universe
|
||||
|
||||
generations =
|
||||
model.generations + 1
|
||||
|
||||
generating =
|
||||
model.generating && universe /= model.universe
|
||||
in
|
||||
( { model
|
||||
| universe = universe
|
||||
, generations = generations
|
||||
, generating = generating
|
||||
}
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
LiveLife ->
|
||||
( { model | generating = not model.generating }
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
Apocalypse ->
|
||||
( { model | generating = False }
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
if model.generating then
|
||||
Time.every 500 (always NextGeneration)
|
||||
|
||||
else
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Model -> View Msg
|
||||
view model =
|
||||
{ title = "Welcome to my website"
|
||||
, body = [ Html.div [ onClick LiveLife, onMouseLeave LiveLife ] [ universeSvg model ] ]
|
||||
}
|
||||
|
||||
|
||||
cellToSvg : Int -> Int -> Cell -> Svg Msg
|
||||
cellToSvg x y cell =
|
||||
let
|
||||
isName =
|
||||
if Array.get ((y - 12) * 24 + x - 3) nameMatrix == Just 1 && x >= 3 && x < 27 then
|
||||
True
|
||||
|
||||
else
|
||||
False
|
||||
|
||||
color =
|
||||
case cell of
|
||||
Alive ->
|
||||
if isName then
|
||||
"fill-cyan-500"
|
||||
|
||||
else
|
||||
"fill-pink-500"
|
||||
|
||||
Dead ->
|
||||
"fill-neutral-800"
|
||||
in
|
||||
rect
|
||||
[ SA.x (String.fromInt (x * cellSize))
|
||||
, SA.y (String.fromInt (y * cellSize))
|
||||
, SA.width (String.fromInt cellSize)
|
||||
, SA.height (String.fromInt cellSize)
|
||||
, SA.class color
|
||||
, SE.onMouseOver (Ressurect x y)
|
||||
]
|
||||
[]
|
||||
|
||||
|
||||
universeSvg : Model -> Html Msg
|
||||
universeSvg model =
|
||||
let
|
||||
svgWidth =
|
||||
String.fromInt (model.universe.width * cellSize)
|
||||
|
||||
svgHeight =
|
||||
String.fromInt (model.universe.height * cellSize)
|
||||
in
|
||||
svg
|
||||
[ SA.width "150"
|
||||
, SA.height "150"
|
||||
, SA.viewBox ("0 0 " ++ svgWidth ++ " " ++ svgHeight)
|
||||
, SA.class "stroke-0"
|
||||
]
|
||||
(stretchUniverseThin cellToSvg model.universe)
|
||||
|
||||
|
||||
|
||||
-- UTIL
|
||||
|
||||
|
||||
bigBang : Int -> Int -> a -> Universe a
|
||||
bigBang width height value =
|
||||
{ space = Array.repeat (width * height) value
|
||||
, width = width
|
||||
, height = height
|
||||
}
|
||||
|
||||
|
||||
stretchUniverseThin : (Int -> Int -> a -> b) -> Universe a -> List b
|
||||
stretchUniverseThin f universe =
|
||||
Array.toIndexedList universe.space
|
||||
|> List.map (\( i, cell ) -> f (modBy universe.width i) (i // universe.width) cell)
|
||||
|
||||
|
||||
nextGeneration : Universe Cell -> Universe Cell
|
||||
nextGeneration universe =
|
||||
{ universe
|
||||
| space =
|
||||
Array.indexedMap
|
||||
(decideFateOf universe)
|
||||
universe.space
|
||||
}
|
||||
|
||||
|
||||
decideFateOf : Universe Cell -> Int -> Cell -> Cell
|
||||
decideFateOf u i today =
|
||||
let
|
||||
aliveAtoms =
|
||||
countLiveAtoms i u
|
||||
in
|
||||
case today of
|
||||
Alive ->
|
||||
if aliveAtoms < 2 || aliveAtoms > 3 then
|
||||
Dead
|
||||
|
||||
else
|
||||
Alive
|
||||
|
||||
Dead ->
|
||||
if aliveAtoms == 3 then
|
||||
Alive
|
||||
|
||||
else
|
||||
Dead
|
||||
|
||||
|
||||
buildRelationship : Universe a -> Int -> Int -> (a -> a) -> Universe a
|
||||
buildRelationship universe x y fn =
|
||||
case getUniverseAt x y universe of
|
||||
Just cell ->
|
||||
setUniverseAt x y (fn cell) universe
|
||||
|
||||
Nothing ->
|
||||
universe
|
||||
|
||||
|
||||
getUniverseAt : Int -> Int -> Universe a -> Maybe a
|
||||
getUniverseAt x y u =
|
||||
Array.get (y * u.width + x) u.space
|
||||
|
||||
|
||||
setUniverseAt : Int -> Int -> a -> Universe a -> Universe a
|
||||
setUniverseAt x y value u =
|
||||
{ u | space = Array.set (y * u.width + x) value u.space }
|
||||
|
||||
|
||||
countLiveAtoms : Int -> Universe Cell -> Int
|
||||
countLiveAtoms i universe =
|
||||
let
|
||||
above =
|
||||
i - universe.width
|
||||
|
||||
below =
|
||||
i + universe.width
|
||||
|
||||
coordinate =
|
||||
[ above - 1
|
||||
, above
|
||||
, above + 1
|
||||
, i - 1
|
||||
, i + 1
|
||||
, below - 1
|
||||
, below
|
||||
, below + 1
|
||||
]
|
||||
in
|
||||
coordinate
|
||||
|> List.filter
|
||||
(\n ->
|
||||
abs
|
||||
(modBy universe.width n - modBy universe.width i)
|
||||
<= 1
|
||||
)
|
||||
|> List.map (\c -> universe.space |> Array.get c)
|
||||
|> List.filter (\c -> c == Just Alive)
|
||||
|> List.length
|
||||
|
||||
|
||||
invertLife : Cell -> Cell
|
||||
invertLife cell =
|
||||
case cell of
|
||||
Alive ->
|
||||
Dead
|
||||
|
||||
Dead ->
|
||||
Alive
|
||||
@@ -1,19 +0,0 @@
|
||||
module Pages.Meet exposing (page)
|
||||
|
||||
import Components.Footer exposing (footerLinksToSide)
|
||||
import Html
|
||||
import Html.Attributes exposing (class, id)
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : View msg
|
||||
page =
|
||||
{ title = "Schedule a meet with me"
|
||||
, body =
|
||||
[ Html.div [ class "flex items-center justify-center flex-col h-screen m-2" ]
|
||||
[ Html.node "cal-com" [ id "calcom-widget", class "w-full p-2" ] []
|
||||
]
|
||||
, Html.div [ class "py-16" ] []
|
||||
, footerLinksToSide
|
||||
]
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
module Pages.NotFound_ exposing (page)
|
||||
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class, href)
|
||||
import Utils.Utils exposing (errorView)
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : View msg
|
||||
page =
|
||||
{ title = "Not Found"
|
||||
, body =
|
||||
[ Html.div [ class "min-h-screen flex flex-col justify-center relative overflow-hidden" ]
|
||||
[ Html.div [ class "relative w-full bg-neutral md:max-w-3xl md:mx-auto lg:max-w-4xl lg:pb-28 space-2" ]
|
||||
[ errorView "Couldn't find what you are looking for. Please check back later"
|
||||
, Html.a [ class "float-right bg-transparent mr-auto hover:bg-pink-600 text-cyan-500 hover:text-white rounded border py-2 px-4 border-cyan-500 mt-2", href "/" ] [ Html.text "Return to Home!" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
module Pages.Pages.AboutMe exposing (Model, Msg, page)
|
||||
|
||||
import Components.Footer exposing (footerLinksToSide)
|
||||
import Effect exposing (Effect)
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class, datetime, href, src)
|
||||
import Http
|
||||
import Page exposing (Page)
|
||||
import Route exposing (Route)
|
||||
import Shared
|
||||
import Utils.JsonResume exposing (Education, Resume, Work, resumeDecoder)
|
||||
import Utils.Utils exposing (getFormattedDate)
|
||||
import View exposing (View)
|
||||
import Components.Footer exposing (iconLinkToCenter)
|
||||
|
||||
|
||||
page : Shared.Model -> Route () -> Page Model Msg
|
||||
page _ _ =
|
||||
Page.new
|
||||
{ init = init
|
||||
, update = update
|
||||
, view = view
|
||||
, subscriptions = subscriptions
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ resume : Maybe Resume
|
||||
, error : Maybe String
|
||||
}
|
||||
|
||||
|
||||
init : () -> ( Model, Effect Msg )
|
||||
init () =
|
||||
let
|
||||
cmd : Cmd Msg
|
||||
cmd =
|
||||
Http.get
|
||||
{ url = "/resume/resume.json"
|
||||
, expect = Http.expectJson GotResume resumeDecoder
|
||||
}
|
||||
in
|
||||
( { resume = Nothing, error = Nothing }, Effect.sendCmd cmd )
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= GotResume (Result Http.Error Resume)
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
GotResume (Ok resume) ->
|
||||
( { model | resume = Just resume }, Effect.none )
|
||||
|
||||
GotResume (Err err) ->
|
||||
( { model | error = Just (Utils.Utils.errorToString err) }, Effect.none )
|
||||
|
||||
|
||||
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Model -> View msg
|
||||
view model =
|
||||
{ title = "About Me"
|
||||
, body =
|
||||
let
|
||||
experience : List Work -> Html msg
|
||||
experience workList =
|
||||
Html.ol [ class "relative border-l border-cyan-700" ]
|
||||
(List.map
|
||||
(\work ->
|
||||
Html.li [ class "mb-10 ml-6 " ]
|
||||
[ Html.span [ class "absolute flex items-center justify-center w-6 h-6 bg-pink-600 ring-pink-900 rounded-full -left-3 ring-8" ]
|
||||
[ Html.text <| String.left 1 work.name ]
|
||||
, Html.h3 [ class "flex items-center mb-1 text-xl font-semibold" ] [ Html.text <| work.position ++ " at " ++ work.name ]
|
||||
, Html.time [ class "block mb-2 text font-normal leading-none text-gray-500", datetime work.startDate ]
|
||||
[ Html.text <| getFormattedDate work.startDate False ++ " - " ++ getFormattedDate work.endDate False ]
|
||||
, Html.p [ class "mb-4 text-base font-normal text-gray-400" ] [ Html.text work.summary ]
|
||||
, Html.p [ class "mb-4 text-lg font-normal text-gray-300" ] [ Html.text work.description ]
|
||||
, Html.p [ class "mb-4 text-lg font-normal text-gray-300 ml-8" ] [ listThings work.highlights ]
|
||||
]
|
||||
)
|
||||
workList
|
||||
)
|
||||
|
||||
education : List Education -> Html msg
|
||||
education eduList =
|
||||
Html.ol [ class "relative border-l border-cyan-700" ]
|
||||
(List.map
|
||||
(\edu ->
|
||||
Html.li [ class "mb-10 ml-6" ]
|
||||
[ Html.span [ class "absolute flex items-center justify-center w-6 h-6 bg-pink-600 ring-pink-900 rounded-full -left-3 ring-8" ]
|
||||
[ Html.text <| String.left 1 edu.institution ]
|
||||
, Html.h3 [ class "flex items-center mb-1 text-xl font-semibold" ] [ Html.text <| edu.studyType ++ " at " ++ edu.institution ]
|
||||
, Html.time [ class "block mb-2 text font-normal leading-none text-gray-500", datetime edu.startDate ]
|
||||
[ Html.text <| getFormattedDate edu.startDate False ++ " - " ++ getFormattedDate edu.endDate False ]
|
||||
, Html.p [ class "mb-4 text-base font-normal text-gray-400" ] [ Html.text edu.area ]
|
||||
]
|
||||
)
|
||||
eduList
|
||||
)
|
||||
in
|
||||
case model.resume of
|
||||
Just resume ->
|
||||
[ Html.section []
|
||||
[ Html.div [ class "text-white" ]
|
||||
[ Html.div [ class "container mx-auto flex flex-col items-start xl:flex-row my-12 xl:my-24" ]
|
||||
[ Html.div [ class "flex flex-col w-full sticky xl:top-36 xl:w-2/3 mt-2 xl:mt-12 px-8" ]
|
||||
[ Html.img [ class "w-full h-80 object-cover mx-auto mb-4", src resume.basics.image ] []
|
||||
, Html.p [ class "text-5xl lg:text-6xl 2xl:text-7xl leading-normal md:leading-relaxed" ] [ Html.text resume.basics.name ]
|
||||
, Html.p [ class "lg:text-xl md:text-md text-base text-cyan-500 uppercase tracking-lppse mb-2" ] [ Html.text resume.basics.label ]
|
||||
, Html.p [ class "md:text-base text-gray-50 mb-4 lg:text-xl" ] [ Html.text resume.basics.summary ]
|
||||
, iconLinkToCenter
|
||||
]
|
||||
, Html.div [ class "flex-row" ]
|
||||
[ Html.div [ class "ml-0 md:ml-12 lg:w-3/3 sticky" ]
|
||||
[ Html.div [ class "container mx-auto w-full h-full" ]
|
||||
[ Html.div [ class "relative wrap overflow-hidden p-10 h-full" ]
|
||||
[ experience resume.work ]
|
||||
]
|
||||
]
|
||||
, Html.div [ class "ml-0 md:ml-12 lg:w-3/3 sticky" ]
|
||||
[ Html.div [ class "container mx-auto w-full h-full" ]
|
||||
[ Html.h2 [ class "text-xl ml-2 text-cyan-500" ] [ Html.text "Education" ]
|
||||
, Html.div [ class "relative wrap overflow-hidden p-10 h-full" ]
|
||||
[ education resume.education ]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
, footerLinksToSide
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- simply list things
|
||||
|
||||
|
||||
listThings : List String -> Html msg
|
||||
listThings things =
|
||||
Html.ul []
|
||||
(List.map
|
||||
(\thing ->
|
||||
Html.li [ class "list-disc" ] [ Html.text thing ]
|
||||
)
|
||||
things
|
||||
)
|
||||
@@ -1,95 +0,0 @@
|
||||
module Pages.Pages.Projects exposing (Model, Msg, page)
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import Effect exposing (Effect)
|
||||
import Html exposing (div, img, section)
|
||||
import Html.Attributes exposing (class, src)
|
||||
import Page exposing (Page)
|
||||
import Route exposing (Route)
|
||||
import Route.Path
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Route () -> Page Model Msg
|
||||
page _ _ =
|
||||
Page.new
|
||||
{ init = init
|
||||
, update = update
|
||||
, subscriptions = subscriptions
|
||||
, view = view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
init : () -> ( Model, Effect Msg )
|
||||
init () =
|
||||
( {}
|
||||
, Effect.replaceRoute { path = Route.Path.NotFound_, query = Dict.empty, hash = Nothing }
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= ExampleMsgReplaceMe
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
ExampleMsgReplaceMe ->
|
||||
( model
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions _ =
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Model -> View Msg
|
||||
view _ =
|
||||
{ title = "My Projects"
|
||||
, body =
|
||||
[ section [ class "overflow-hidden" ]
|
||||
[ div
|
||||
[ class "px-5 py-2 mx-auto lg:pt-24 lg:px-32" ]
|
||||
[ div [ class "flex flex-wrap -m-1 md:-m-2" ]
|
||||
(List.repeat 8
|
||||
(div [ class "flex flex-wrap w-1/2" ]
|
||||
(List.repeat 2
|
||||
(div
|
||||
[ class "w-full p-1 md:p-2" ]
|
||||
[ img
|
||||
[ src "https://opengraph.githubassets.com/string/avinal/blowfish"
|
||||
, class "block object-cover object-center w-full h-full rounded-lg"
|
||||
]
|
||||
[]
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
module Utils.Constants exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Html exposing (Html)
|
||||
|
||||
|
||||
type alias Link =
|
||||
{ url : String
|
||||
, text : String
|
||||
}
|
||||
|
||||
|
||||
type alias IconLink =
|
||||
{ url : String
|
||||
, icon : String
|
||||
}
|
||||
|
||||
|
||||
type alias Job msg =
|
||||
{ title : String
|
||||
, company : String
|
||||
, from : String
|
||||
, to : String
|
||||
, body : Html msg
|
||||
}
|
||||
|
||||
|
||||
footerLinks : List Link
|
||||
footerLinks =
|
||||
[ { text = "About", url = "/pages/about-me" }
|
||||
, { text = "Blog", url = "https://avinal.space/posts" }
|
||||
, { text = "Projects", url = "/pages/projects" }
|
||||
, { text = "GSoC", url = "https://avinal.space/posts/category/gsoc" }
|
||||
]
|
||||
|
||||
|
||||
iconLinks : List IconLink
|
||||
iconLinks =
|
||||
[ { url = "https://github.com/avinal", icon = "fa-brands fa-github" }
|
||||
, { url = "https://www.linkedin.com/in/avinal", icon = "fa-brands fa-linkedin" }
|
||||
, { url = "https://twitter.com/Avinal_", icon = "fa-brands fa-twitter" }
|
||||
, { url = "mailto:ripple@avinal.space", icon = "fa-solid fa-envelope" }
|
||||
, { url = "/meet", icon = "fa-solid fa-video" }
|
||||
]
|
||||
|
||||
|
||||
months : Array String
|
||||
months =
|
||||
Array.fromList
|
||||
[ "January"
|
||||
, "February"
|
||||
, "March"
|
||||
, "April"
|
||||
, "May"
|
||||
, "June"
|
||||
, "July"
|
||||
, "August"
|
||||
, "September"
|
||||
, "October"
|
||||
, "November"
|
||||
, "December"
|
||||
]
|
||||
|
||||
|
||||
nameMatrix : Array Int
|
||||
nameMatrix =
|
||||
Array.fromList
|
||||
[ 0
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 0
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 1
|
||||
, 0
|
||||
, 1
|
||||
]
|
||||
@@ -1,435 +0,0 @@
|
||||
module Utils.JsonResume exposing (..)
|
||||
|
||||
import Json.Decode as Decode exposing (Decoder)
|
||||
import Json.Decode.Pipeline exposing (optional, required)
|
||||
|
||||
|
||||
|
||||
-- Main Resume type
|
||||
|
||||
|
||||
type alias Resume =
|
||||
{ basics : Basics
|
||||
, work : List Work
|
||||
, volunteer : List Volunteer
|
||||
, education : List Education
|
||||
, awards : List Award
|
||||
, certificates : List Certificate
|
||||
, publications : List Publication
|
||||
, skills : List Skill
|
||||
, languages : List Language
|
||||
, interests : List Interest
|
||||
, references : List Reference
|
||||
, projects : List Project
|
||||
, meta : Meta
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Basics
|
||||
|
||||
|
||||
type alias Basics =
|
||||
{ name : String
|
||||
, label : String
|
||||
, image : String
|
||||
, email : String
|
||||
, phone : String
|
||||
, url : String
|
||||
, summary : String
|
||||
, location : Location
|
||||
, profiles : List Profile
|
||||
}
|
||||
|
||||
|
||||
type alias Location =
|
||||
{ address : String
|
||||
, postalCode : String
|
||||
, city : String
|
||||
, countryCode : String
|
||||
, region : String
|
||||
}
|
||||
|
||||
|
||||
type alias Profile =
|
||||
{ network : String
|
||||
, username : String
|
||||
, url : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Work
|
||||
|
||||
|
||||
type alias Work =
|
||||
{ name : String
|
||||
, location : String
|
||||
, description : String
|
||||
, position : String
|
||||
, url : String
|
||||
, startDate : String
|
||||
, endDate : String
|
||||
, summary : String
|
||||
, highlights : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Volunteer
|
||||
|
||||
|
||||
type alias Volunteer =
|
||||
{ organization : String
|
||||
, position : String
|
||||
, url : String
|
||||
, startDate : String
|
||||
, endDate : String
|
||||
, summary : String
|
||||
, highlights : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Education
|
||||
|
||||
|
||||
type alias Education =
|
||||
{ institution : String
|
||||
, url : String
|
||||
, area : String
|
||||
, studyType : String
|
||||
, startDate : String
|
||||
, endDate : String
|
||||
, score : String
|
||||
, courses : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Awards
|
||||
|
||||
|
||||
type alias Award =
|
||||
{ title : String
|
||||
, date : String
|
||||
, awarder : String
|
||||
, summary : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Certificates
|
||||
|
||||
|
||||
type alias Certificate =
|
||||
{ name : String
|
||||
, date : String
|
||||
, url : String
|
||||
, issuer : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Publications
|
||||
|
||||
|
||||
type alias Publication =
|
||||
{ name : String
|
||||
, publisher : String
|
||||
, releaseDate : String
|
||||
, url : String
|
||||
, summary : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Skills
|
||||
|
||||
|
||||
type alias Skill =
|
||||
{ name : String
|
||||
, level : String
|
||||
, keywords : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Languages
|
||||
|
||||
|
||||
type alias Language =
|
||||
{ language : String
|
||||
, fluency : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Interests
|
||||
|
||||
|
||||
type alias Interest =
|
||||
{ name : String
|
||||
, keywords : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- References
|
||||
|
||||
|
||||
type alias Reference =
|
||||
{ name : String
|
||||
, reference : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Projects
|
||||
|
||||
|
||||
type alias Project =
|
||||
{ name : String
|
||||
, description : String
|
||||
, highlights : List String
|
||||
, keywords : List String
|
||||
, startDate : String
|
||||
, endDate : String
|
||||
, url : String
|
||||
, roles : List String
|
||||
, entity : String
|
||||
, type_ : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Meta
|
||||
|
||||
|
||||
type alias Meta =
|
||||
{ canonical : String
|
||||
, version : String
|
||||
, lastModified : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- JSON Decoders
|
||||
-- Resume Decoder
|
||||
|
||||
|
||||
resumeDecoder : Decoder Resume
|
||||
resumeDecoder =
|
||||
Decode.succeed Resume
|
||||
|> required "basics" basicsDecoder
|
||||
|> required "work" (Decode.list workDecoder)
|
||||
|> optional "volunteer" (Decode.list volunteerDecoder) []
|
||||
|> required "education" (Decode.list educationDecoder)
|
||||
|> optional "awards" (Decode.list awardDecoder) []
|
||||
|> optional "certificates" (Decode.list certificateDecoder) []
|
||||
|> optional "publications" (Decode.list publicationDecoder) []
|
||||
|> optional "skills" (Decode.list skillDecoder) []
|
||||
|> optional "languages" (Decode.list languageDecoder) []
|
||||
|> optional "interests" (Decode.list interestDecoder) []
|
||||
|> optional "references" (Decode.list referenceDecoder) []
|
||||
|> optional "projects" (Decode.list projectDecoder) []
|
||||
|> optional "meta" metaDecoder (Meta "" "" "")
|
||||
|
||||
|
||||
|
||||
-- Basics Decoder
|
||||
|
||||
|
||||
basicsDecoder : Decoder Basics
|
||||
basicsDecoder =
|
||||
Decode.succeed Basics
|
||||
|> required "name" Decode.string
|
||||
|> required "label" Decode.string
|
||||
|> optional "image" Decode.string ""
|
||||
|> required "email" Decode.string
|
||||
|> optional "phone" Decode.string ""
|
||||
|> required "url" Decode.string
|
||||
|> required "summary" Decode.string
|
||||
|> optional "location" locationDecoder (Location "" "" "" "" "")
|
||||
|> optional "profiles" (Decode.list profileDecoder) []
|
||||
|
||||
|
||||
locationDecoder : Decoder Location
|
||||
locationDecoder =
|
||||
Decode.succeed Location
|
||||
|> optional "address" Decode.string ""
|
||||
|> optional "postalCode" Decode.string ""
|
||||
|> required "city" Decode.string
|
||||
|> required "countryCode" Decode.string
|
||||
|> optional "region" Decode.string ""
|
||||
|
||||
|
||||
profileDecoder : Decoder Profile
|
||||
profileDecoder =
|
||||
Decode.succeed Profile
|
||||
|> required "network" Decode.string
|
||||
|> required "username" Decode.string
|
||||
|> required "url" Decode.string
|
||||
|
||||
|
||||
workDecoder : Decoder Work
|
||||
workDecoder =
|
||||
Decode.succeed Work
|
||||
|> required "name" Decode.string
|
||||
|> optional "location" Decode.string ""
|
||||
|> optional "description" Decode.string ""
|
||||
|> required "position" Decode.string
|
||||
|> optional "url" Decode.string ""
|
||||
|> required "startDate" Decode.string
|
||||
|> required "endDate" Decode.string
|
||||
|> required "summary" Decode.string
|
||||
|> optional "highlights" (Decode.list Decode.string) []
|
||||
|
||||
|
||||
|
||||
-- Volunteer Decoder
|
||||
|
||||
|
||||
volunteerDecoder : Decoder Volunteer
|
||||
volunteerDecoder =
|
||||
Decode.succeed Volunteer
|
||||
|> required "organization" Decode.string
|
||||
|> required "position" Decode.string
|
||||
|> required "url" Decode.string
|
||||
|> required "startDate" Decode.string
|
||||
|> required "endDate" Decode.string
|
||||
|> required "summary" Decode.string
|
||||
|> optional "highlights" (Decode.list Decode.string) []
|
||||
|
||||
|
||||
|
||||
-- Education Decoder
|
||||
|
||||
|
||||
educationDecoder : Decoder Education
|
||||
educationDecoder =
|
||||
Decode.succeed Education
|
||||
|> required "institution" Decode.string
|
||||
|> optional "url" Decode.string ""
|
||||
|> required "area" Decode.string
|
||||
|> required "studyType" Decode.string
|
||||
|> required "startDate" Decode.string
|
||||
|> required "endDate" Decode.string
|
||||
|> optional "score" Decode.string ""
|
||||
|> optional "courses" (Decode.list Decode.string) []
|
||||
|
||||
|
||||
|
||||
-- Award Decoder
|
||||
|
||||
|
||||
awardDecoder : Decoder Award
|
||||
awardDecoder =
|
||||
Decode.succeed Award
|
||||
|> required "title" Decode.string
|
||||
|> required "date" Decode.string
|
||||
|> required "awarder" Decode.string
|
||||
|> required "summary" Decode.string
|
||||
|
||||
|
||||
|
||||
-- Certificate Decoder
|
||||
|
||||
|
||||
certificateDecoder : Decoder Certificate
|
||||
certificateDecoder =
|
||||
Decode.succeed Certificate
|
||||
|> required "name" Decode.string
|
||||
|> required "date" Decode.string
|
||||
|> required "url" Decode.string
|
||||
|> required "issuer" Decode.string
|
||||
|
||||
|
||||
|
||||
-- Publication Decoder
|
||||
|
||||
|
||||
publicationDecoder : Decoder Publication
|
||||
publicationDecoder =
|
||||
Decode.succeed Publication
|
||||
|> required "name" Decode.string
|
||||
|> required "publisher" Decode.string
|
||||
|> required "releaseDate" Decode.string
|
||||
|> required "url" Decode.string
|
||||
|> required "summary" Decode.string
|
||||
|
||||
|
||||
|
||||
-- Skill Decoder
|
||||
|
||||
|
||||
skillDecoder : Decoder Skill
|
||||
skillDecoder =
|
||||
Decode.succeed Skill
|
||||
|> required "name" Decode.string
|
||||
|> optional "level" Decode.string ""
|
||||
|> optional "keywords" (Decode.list Decode.string) []
|
||||
|
||||
|
||||
|
||||
-- Language Decoder
|
||||
|
||||
|
||||
languageDecoder : Decoder Language
|
||||
languageDecoder =
|
||||
Decode.succeed Language
|
||||
|> required "language" Decode.string
|
||||
|> required "fluency" Decode.string
|
||||
|
||||
|
||||
|
||||
-- Interest Decoder
|
||||
|
||||
|
||||
interestDecoder : Decoder Interest
|
||||
interestDecoder =
|
||||
Decode.succeed Interest
|
||||
|> required "name" Decode.string
|
||||
|> required "keywords" (Decode.list Decode.string)
|
||||
|
||||
|
||||
|
||||
-- Reference Decoder
|
||||
|
||||
|
||||
referenceDecoder : Decoder Reference
|
||||
referenceDecoder =
|
||||
Decode.succeed Reference
|
||||
|> required "name" Decode.string
|
||||
|> required "reference" Decode.string
|
||||
|
||||
|
||||
|
||||
-- Project Decoder
|
||||
|
||||
|
||||
projectDecoder : Decoder Project
|
||||
projectDecoder =
|
||||
Decode.succeed Project
|
||||
|> required "name" Decode.string
|
||||
|> required "description" Decode.string
|
||||
|> optional "highlights" (Decode.list Decode.string) []
|
||||
|> optional "keywords" (Decode.list Decode.string) []
|
||||
|> required "startDate" Decode.string
|
||||
|> optional "endDate" Decode.string ""
|
||||
|> required "url" Decode.string
|
||||
|> optional "roles" (Decode.list Decode.string) []
|
||||
|> optional "entity" Decode.string ""
|
||||
|> optional "type_" Decode.string ""
|
||||
|
||||
|
||||
|
||||
-- Meta Decoder
|
||||
|
||||
|
||||
metaDecoder : Decoder Meta
|
||||
metaDecoder =
|
||||
Decode.succeed Meta
|
||||
|> required "canonical" Decode.string
|
||||
|> required "version" Decode.string
|
||||
|> required "lastModified" Decode.string
|
||||
@@ -1,154 +0,0 @@
|
||||
module Utils.Utils exposing (..)
|
||||
|
||||
import Array
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class, href, target)
|
||||
import Http exposing (Error(..))
|
||||
import Parser exposing (..)
|
||||
import Utils.Constants exposing (..)
|
||||
|
||||
|
||||
type alias DateTime =
|
||||
{ year : Int
|
||||
, month : Int
|
||||
, day : Int
|
||||
, hour : Int
|
||||
, minute : Int
|
||||
}
|
||||
|
||||
|
||||
getFormattedDate : String -> Bool -> String
|
||||
getFormattedDate dateString time =
|
||||
case Parser.run dateParser dateString of
|
||||
Ok date ->
|
||||
(Maybe.withDefault "Month" <| Array.get (date.month - 1) months)
|
||||
++ " "
|
||||
++ String.fromInt date.day
|
||||
++ ", "
|
||||
++ String.fromInt date.year
|
||||
++ (if time then
|
||||
", "
|
||||
++ String.fromInt date.hour
|
||||
++ ":"
|
||||
++ String.fromInt date.minute
|
||||
++ " IST"
|
||||
|
||||
else
|
||||
""
|
||||
)
|
||||
|
||||
Err _ ->
|
||||
if time then
|
||||
"Invalid date!!"
|
||||
|
||||
else
|
||||
"Today"
|
||||
|
||||
|
||||
dateParser : Parser DateTime
|
||||
dateParser =
|
||||
oneOf
|
||||
[ succeed Tuple.pair
|
||||
|= datePart
|
||||
|= optional timePart
|
||||
]
|
||||
|> map toDateTime
|
||||
|
||||
|
||||
datePart : Parser ( Int, Int, Int )
|
||||
datePart =
|
||||
succeed (\y m d -> ( y, m, d ))
|
||||
|= int
|
||||
|. token "-"
|
||||
|. chompWhile (\c -> c == '0')
|
||||
|= int
|
||||
|. token "-"
|
||||
|. chompWhile (\c -> c == '0')
|
||||
|= int
|
||||
|
||||
|
||||
timePart : Parser ( Int, Int )
|
||||
timePart =
|
||||
succeed (\h m -> ( h, m ))
|
||||
|. token "T"
|
||||
|. chompWhile (\c -> c == '0')
|
||||
|= int
|
||||
|. token ":"
|
||||
|. chompWhile (\c -> c == '0')
|
||||
|= int
|
||||
|. chompUntilEndOr "\n"
|
||||
|. end
|
||||
|
||||
|
||||
toDateTime : ( ( Int, Int, Int ), Maybe ( Int, Int ) ) -> DateTime
|
||||
toDateTime ( ( y, m, d ), maybeTime ) =
|
||||
case maybeTime of
|
||||
Just ( h, min ) ->
|
||||
DateTime y m d h min
|
||||
|
||||
Nothing ->
|
||||
DateTime y m d 0 0
|
||||
|
||||
|
||||
optional : Parser a -> Parser (Maybe a)
|
||||
optional parser =
|
||||
oneOf
|
||||
[ succeed Just |= parser
|
||||
, succeed Nothing
|
||||
]
|
||||
|
||||
|
||||
categoryNtags : String -> List String -> Html msg
|
||||
categoryNtags category tags =
|
||||
Html.span [ class "flex flex-wrap py-6 space-x-2" ]
|
||||
(Html.a [ class "px-3 py-1 m-1 rounded-sm hover:underline bg-pink-400 text-gray-900 font-bold", href <| "/posts/" ++ category, target "_blank" ]
|
||||
[ Html.text category
|
||||
]
|
||||
:: List.map
|
||||
(\tag ->
|
||||
Html.i [ class "px-3 py-1 m-1 rounded-sm hover:underline bg-cyan-500 text-gray-900" ]
|
||||
[ Html.text <| "#" ++ tag
|
||||
]
|
||||
)
|
||||
tags
|
||||
)
|
||||
|
||||
|
||||
contentUrl : { category : String, post : String } -> String
|
||||
contentUrl { category, post } =
|
||||
"/content/posts/" ++ category ++ "/" ++ post ++ ".md"
|
||||
|
||||
|
||||
errorToString : Http.Error -> String
|
||||
errorToString error =
|
||||
case error of
|
||||
BadUrl url ->
|
||||
"The URL " ++ url ++ " was invalid"
|
||||
|
||||
Timeout ->
|
||||
"Unable to reach the server, try again"
|
||||
|
||||
NetworkError ->
|
||||
"Unable to reach the server, check your network connection"
|
||||
|
||||
BadStatus 500 ->
|
||||
"The server had a problem, try again later"
|
||||
|
||||
BadStatus 400 ->
|
||||
"Verify your information and try again"
|
||||
|
||||
BadStatus _ ->
|
||||
"The content can't be found, please check your url"
|
||||
|
||||
BadBody errorMessage ->
|
||||
errorMessage
|
||||
|
||||
|
||||
errorView : String -> Html msg
|
||||
errorView error =
|
||||
Html.div
|
||||
[ class "border border-red-400 text-red-700 px-4 py-3 rounded relative" ]
|
||||
[ Html.strong [ class "text-red-400" ] [ Html.text "Something bad has happened!" ]
|
||||
, Html.br [] []
|
||||
, Html.text ("Error: " ++ error)
|
||||
]
|
||||
@@ -1,76 +0,0 @@
|
||||
module View exposing
|
||||
( View, map
|
||||
, none, fromString
|
||||
, toBrowserDocument
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs View, map
|
||||
@docs none, fromString
|
||||
@docs toBrowserDocument
|
||||
|
||||
-}
|
||||
|
||||
import Browser
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes exposing (class)
|
||||
import Route exposing (Route)
|
||||
import Shared.Model
|
||||
|
||||
|
||||
type alias View msg =
|
||||
{ title : String
|
||||
, body : List (Html msg)
|
||||
}
|
||||
|
||||
|
||||
{-| Used internally by Elm Land to create your application
|
||||
so it works with Elm's expected `Browser.Document msg` type.
|
||||
-}
|
||||
toBrowserDocument :
|
||||
{ shared : Shared.Model.Model
|
||||
, route : Route ()
|
||||
, view : View msg
|
||||
}
|
||||
-> Browser.Document msg
|
||||
toBrowserDocument { view } =
|
||||
{ title = view.title ++ " | Avinal's personal website"
|
||||
, body =
|
||||
[ Html.main_ [ class "container mx-auto bg-neutral-800" ]
|
||||
view.body
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
{-| Used internally by Elm Land to connect your pages together.
|
||||
-}
|
||||
map : (msg1 -> msg2) -> View msg1 -> View msg2
|
||||
map fn view =
|
||||
{ title = view.title
|
||||
, body = List.map (Html.map fn) view.body
|
||||
}
|
||||
|
||||
|
||||
{-| Used internally by Elm Land whenever transitioning between
|
||||
authenticated pages.
|
||||
-}
|
||||
none : View msg
|
||||
none =
|
||||
{ title = "Avinal Kumar | Personal Website"
|
||||
, body = []
|
||||
}
|
||||
|
||||
|
||||
{-| If you customize the `View` module, anytime you run `elm-land add page`,
|
||||
the generated page will use this when adding your `view` function.
|
||||
|
||||
That way your app will compile after adding new pages, and you can see
|
||||
the new page working in the web browser!
|
||||
|
||||
-}
|
||||
fromString : String -> View msg
|
||||
fromString moduleName =
|
||||
{ title = moduleName
|
||||
, body = []
|
||||
}
|
||||
-270
@@ -1,270 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* PrismJS 1.29.0
|
||||
https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript+bash+basic+brainfuck+c+cpp+cmake+diff+docker+elm+git+go+go-module+graphql+haskell+http+java+json+json5+jsonp+makefile+markdown+matlab+mermaid+powershell+protobuf+python+rest+rust+shell-session+sql+toml+typescript+vim+wasm+yaml&plugins=line-numbers+toolbar+match-braces+diff-highlight */
|
||||
code[class*=language-],
|
||||
pre[class*=language-] {
|
||||
color: #f8f8f2;
|
||||
background: 0 0;
|
||||
text-shadow: 0 1px rgba(0, 0, 0, .3);
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none
|
||||
}
|
||||
|
||||
pre[class*=language-] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
border-radius: .3em
|
||||
}
|
||||
|
||||
:not(pre)>code[class*=language-],
|
||||
pre[class*=language-] {
|
||||
background: #0b0b0b
|
||||
}
|
||||
|
||||
:not(pre)>code[class*=language-] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal
|
||||
}
|
||||
|
||||
.token.cdata,
|
||||
.token.comment,
|
||||
.token.doctype,
|
||||
.token.prolog {
|
||||
color: #8292a2
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #f8f8f2
|
||||
}
|
||||
|
||||
.token.namespace {
|
||||
opacity: .7
|
||||
}
|
||||
|
||||
.token.constant,
|
||||
.token.deleted,
|
||||
.token.property,
|
||||
.token.symbol,
|
||||
.token.tag {
|
||||
color: #f92672
|
||||
}
|
||||
|
||||
.token.boolean,
|
||||
.token.number {
|
||||
color: #ae81ff
|
||||
}
|
||||
|
||||
.token.attr-name,
|
||||
.token.builtin,
|
||||
.token.char,
|
||||
.token.inserted,
|
||||
.token.selector,
|
||||
.token.string {
|
||||
color: #a6e22e
|
||||
}
|
||||
|
||||
.language-css .token.string,
|
||||
.style .token.string,
|
||||
.token.entity,
|
||||
.token.operator,
|
||||
.token.url,
|
||||
.token.variable {
|
||||
color: #f8f8f2
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.class-name,
|
||||
.token.function {
|
||||
color: #e6db74
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #66d9ef
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.regex {
|
||||
color: #fd971f
|
||||
}
|
||||
|
||||
.token.bold,
|
||||
.token.important {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help
|
||||
}
|
||||
|
||||
pre[class*=language-].line-numbers {
|
||||
position: relative;
|
||||
padding-left: 3.8em;
|
||||
counter-reset: linenumber
|
||||
}
|
||||
|
||||
pre[class*=language-].line-numbers>code {
|
||||
position: relative;
|
||||
white-space: inherit
|
||||
}
|
||||
|
||||
.line-numbers .line-numbers-rows {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
font-size: 100%;
|
||||
left: -3.8em;
|
||||
width: 3em;
|
||||
letter-spacing: -1px;
|
||||
border-right: 1px solid #999;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none
|
||||
}
|
||||
|
||||
.line-numbers-rows>span {
|
||||
display: block;
|
||||
counter-increment: linenumber
|
||||
}
|
||||
|
||||
.line-numbers-rows>span:before {
|
||||
content: counter(linenumber);
|
||||
color: #999;
|
||||
display: block;
|
||||
padding-right: .8em;
|
||||
text-align: right
|
||||
}
|
||||
|
||||
div.code-toolbar {
|
||||
position: relative
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: .3em;
|
||||
right: .2em;
|
||||
transition: opacity .3s ease-in-out;
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
div.code-toolbar:hover>.toolbar {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
div.code-toolbar:focus-within>.toolbar {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar>.toolbar-item {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar>.toolbar-item>a {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar>.toolbar-item>button {
|
||||
background: 0 0;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar>.toolbar-item>a,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>button,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>span {
|
||||
color: #bbb;
|
||||
font-size: .8em;
|
||||
padding: 0 .5em;
|
||||
background: #f5f2f0;
|
||||
background: rgba(224, 224, 224, .2);
|
||||
box-shadow: 0 2px 0 0 rgba(0, 0, 0, .2);
|
||||
border-radius: .5em
|
||||
}
|
||||
|
||||
div.code-toolbar>.toolbar>.toolbar-item>a:focus,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>a:hover,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>button:focus,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>button:hover,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>span:focus,
|
||||
div.code-toolbar>.toolbar>.toolbar-item>span:hover {
|
||||
color: inherit;
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.token.punctuation.brace-hover,
|
||||
.token.punctuation.brace-selected {
|
||||
outline: solid 1px
|
||||
}
|
||||
|
||||
.rainbow-braces .token.punctuation.brace-level-1,
|
||||
.rainbow-braces .token.punctuation.brace-level-5,
|
||||
.rainbow-braces .token.punctuation.brace-level-9 {
|
||||
color: #e50;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.rainbow-braces .token.punctuation.brace-level-10,
|
||||
.rainbow-braces .token.punctuation.brace-level-2,
|
||||
.rainbow-braces .token.punctuation.brace-level-6 {
|
||||
color: #0b3;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.rainbow-braces .token.punctuation.brace-level-11,
|
||||
.rainbow-braces .token.punctuation.brace-level-3,
|
||||
.rainbow-braces .token.punctuation.brace-level-7 {
|
||||
color: #26f;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.rainbow-braces .token.punctuation.brace-level-12,
|
||||
.rainbow-braces .token.punctuation.brace-level-4,
|
||||
.rainbow-braces .token.punctuation.brace-level-8 {
|
||||
color: #e0e;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
pre.diff-highlight>code .token.deleted:not(.prefix),
|
||||
pre>code.diff-highlight .token.deleted:not(.prefix) {
|
||||
background-color: rgba(255, 0, 0, .1);
|
||||
color: inherit;
|
||||
display: block
|
||||
}
|
||||
|
||||
pre.diff-highlight>code .token.inserted:not(.prefix),
|
||||
pre>code.diff-highlight .token.inserted:not(.prefix) {
|
||||
background-color: rgba(0, 255, 128, .1);
|
||||
color: inherit;
|
||||
display: block
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import "./web-components/Calcom.js";
|
||||
|
||||
export const onReady = ({ app, env }) => { };
|
||||
@@ -1,55 +0,0 @@
|
||||
customElements.define(
|
||||
"cal-com",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
(function (C, A, L) {
|
||||
let p = function (a, ar) {
|
||||
a.q.push(ar);
|
||||
};
|
||||
let d = C.document;
|
||||
C.Cal =
|
||||
C.Cal ||
|
||||
function () {
|
||||
let cal = C.Cal;
|
||||
let ar = arguments;
|
||||
if (!cal.loaded) {
|
||||
cal.ns = {};
|
||||
cal.q = cal.q || [];
|
||||
d.head.appendChild(d.createElement("script")).src = A;
|
||||
cal.loaded = true;
|
||||
}
|
||||
if (ar[0] === L) {
|
||||
const api = function () {
|
||||
p(api, arguments);
|
||||
};
|
||||
const namespace = ar[1];
|
||||
api.q = api.q || [];
|
||||
typeof namespace === "string"
|
||||
? (cal.ns[namespace] = api) && p(api, ar)
|
||||
: p(cal, ar);
|
||||
return;
|
||||
}
|
||||
p(cal, ar);
|
||||
};
|
||||
})(window, "https://app.cal.com/embed/embed.js", "init");
|
||||
Cal("init", { origin: "https://app.cal.com" });
|
||||
|
||||
Cal("inline", {
|
||||
elementOrSelector: "#calcom-widget",
|
||||
calLink: "avinal",
|
||||
});
|
||||
Cal("ui", {
|
||||
theme: "dark",
|
||||
styles: {
|
||||
branding: { brandColor: "#009fb1" },
|
||||
},
|
||||
hideEventTypeDetails: false,
|
||||
});
|
||||
console.log("These errors are not produced by the Elm app :)");
|
||||
}
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user