aboutsummaryrefslogtreecommitdiff
path: root/src/View
diff options
context:
space:
mode:
authorJoris Guyonvarch2014-04-06 22:55:16 +0200
committerJoris2019-05-01 15:34:22 +0200
commit0fe906ae7453aa684e998bbcc7a78b62d84f0206 (patch)
treed3968af830b964193349187fb6fc583780cd0ce3 /src/View
parent8b11c4be2b3ac354fa14534662dbd92374617a3e (diff)
Show resume and projects from a configuration file
Diffstat (limited to 'src/View')
-rw-r--r--src/View/Git.hs37
-rw-r--r--src/View/Header.hs42
-rw-r--r--src/View/Icon.hs17
-rw-r--r--src/View/Interval.hs39
-rw-r--r--src/View/LaTeX/Resume.hs148
-rw-r--r--src/View/NotFound.hs26
-rw-r--r--src/View/Page.hs33
-rw-r--r--src/View/Project.hs66
-rw-r--r--src/View/Resume.hs140
9 files changed, 548 insertions, 0 deletions
diff --git a/src/View/Git.hs b/src/View/Git.hs
new file mode 100644
index 0000000..abf5226
--- /dev/null
+++ b/src/View/Git.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Git
+ ( renderGit
+ , renderGitIcon
+ ) where
+
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5.Attributes
+import qualified Text.Blaze.Html5 as H
+
+import Conf (Conf)
+import qualified Conf as Conf
+
+import View.Icon (renderIcon)
+
+renderGit :: Conf -> String -> Html
+renderGit conf ref =
+ H.div
+ ! class_ "git"
+ $ H.a
+ ! href (fromString $ gitLink conf ref)
+ $ do
+ renderIcon "git-square"
+ fromString ref
+
+renderGitIcon :: Conf -> String -> Html
+renderGitIcon conf ref =
+ H.a
+ ! class_ "git"
+ ! href (fromString $ gitLink conf ref)
+ $ renderIcon "git-square"
+
+gitLink :: Conf -> String -> String
+gitLink conf ref = (Conf.git conf) ++ ref
diff --git a/src/View/Header.hs b/src/View/Header.hs
new file mode 100644
index 0000000..a29b9a3
--- /dev/null
+++ b/src/View/Header.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Header
+ ( renderHeader
+ ) where
+
+import Control.Monad (forM_)
+
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5
+import Text.Blaze.Html5.Attributes
+import qualified Text.Blaze.Html5 as H
+
+import Model.Header
+import Model.Translation.Language
+import Model.Translation.Message
+
+renderHeader :: Language -> Maybe Header -> Html
+renderHeader language mbCurrentHeader =
+ H.div ! class_ "header" $
+ ul $
+ forM_ allHeaders (headerItem language mbCurrentHeader)
+
+headerItem :: Language -> Maybe Header -> Header -> Html
+headerItem language mbCurrentHeader pageHeader =
+ li $ a
+ ! class_ (fromString $ (headerClass pageHeader) ++ " " ++ (if mbCurrentHeader == Just pageHeader then "currentHeader" else ""))
+ ! href (fromString . headerLink $ pageHeader) $ do
+ i ! class_ (fromString $ "fa fa-lg " ++ (headerIcon pageHeader)) $ ""
+ H.span
+ ! class_ "text"
+ $ fromString (getMessage (headerKey pageHeader) language)
+
+headerClass :: Header -> String
+headerClass Resume = "resume"
+headerClass Projects = "projects"
+
+headerIcon :: Header -> String
+headerIcon Resume = "fa-user"
+headerIcon Projects = "fa-flask"
diff --git a/src/View/Icon.hs b/src/View/Icon.hs
new file mode 100644
index 0000000..67db0a9
--- /dev/null
+++ b/src/View/Icon.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Icon
+ ( renderIcon
+ ) where
+
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5
+import Text.Blaze.Html5.Attributes
+
+renderIcon :: String -> Html
+renderIcon iconName =
+ i
+ ! class_ (fromString $ "fa fa-fw fa-" ++ iconName)
+ $ ""
diff --git a/src/View/Interval.hs b/src/View/Interval.hs
new file mode 100644
index 0000000..05cb62c
--- /dev/null
+++ b/src/View/Interval.hs
@@ -0,0 +1,39 @@
+module View.Interval
+ ( renderDurationAndInterval
+ , renderYearInterval
+ , renderDuration
+ ) where
+
+import Data.Maybe (fromMaybe)
+
+import Model.Date
+import Model.Translation.Language
+import qualified Model.Translation.Key as K
+import Model.Translation.Message
+
+renderDurationAndInterval :: Language -> Date -> Date -> Maybe Date -> String
+renderDurationAndInterval language currentDate beginDate mbEndDate =
+ let duration = renderDuration language beginDate (fromMaybe currentDate mbEndDate)
+ interval = renderYearInterval language beginDate mbEndDate
+ in duration ++ ", " ++ interval
+
+renderDuration :: Language -> Date -> Date -> String
+renderDuration language d1 d2 =
+ let (years, months) = yearAndMonthDiff d1 d2
+ renderYears = (show years) ++ " " ++ (getMessage (K.YearText years) language)
+ renderMonths = (show months) ++ " " ++ (getMessage (K.MonthText months) language)
+ spaceAnd = " " ++ (getMessage K.And language) ++ " "
+ in if years > 0 then
+ renderYears ++ (if months > 0 then spaceAnd ++ renderMonths else "")
+ else
+ renderMonths
+
+renderYearInterval :: Language -> Date -> (Maybe Date) -> String
+renderYearInterval language beginDate Nothing =
+ (getMessage K.Since language) ++ " " ++ (show . year $ beginDate)
+renderYearInterval language beginDate (Just endDate) =
+ let beginYear = year beginDate
+ endYear = year endDate
+ in if beginYear == endYear
+ then show beginYear
+ else (show beginYear) ++ " " ++ (getMessage K.To language) ++ " " ++ (show endYear)
diff --git a/src/View/LaTeX/Resume.hs b/src/View/LaTeX/Resume.hs
new file mode 100644
index 0000000..6ec717f
--- /dev/null
+++ b/src/View/LaTeX/Resume.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.LaTeX.Resume
+ ( resumeLaTeX
+ ) where
+
+import Text.LaTeX
+import Text.LaTeX.Base.Syntax (LaTeX (TeXComm), TeXArg (FixArg))
+
+import Data.Maybe (fromMaybe, listToMaybe)
+
+import Conf (Conf)
+import qualified Conf as Conf
+
+import Model (Model)
+import qualified Model as M
+import qualified Model.Company as C
+import Model.Date (Date)
+import Model.Degree (Degree)
+import qualified Model.Degree as D
+import Model.Identity (Identity)
+import qualified Model.Identity as I
+import Model.Job (Job)
+import qualified Model.Job as J
+import qualified Model.School as S
+import Model.SkillType (SkillType)
+import qualified Model.SkillType as ST
+
+import Model.Translated
+import Model.Translation.Key (Key)
+import qualified Model.Translation.Key as K
+import Model.Translation.Language
+import Model.Translation.Message
+
+import View.Interval (renderDurationAndInterval)
+
+import Utils.String
+
+resumeLaTeX :: Conf -> Language -> Date -> Model -> LaTeX
+resumeLaTeX conf language currentDate model =
+ preamble
+ <> document (body conf language currentDate model)
+
+preamble :: LaTeX
+preamble = documentclass [] "resume"
+
+body :: Conf -> Language -> Date -> Model -> LaTeX
+body conf language currentDate model =
+ identityLaTeX conf language (M.identity model) (M.jobs model)
+ <> jobsLaTeX language currentDate (M.jobs model)
+ <> degreesLaTeX language (M.degrees model)
+ <> skillTypesLaTeX language (M.skillTypes model)
+ <> interestsLaTeX language (M.interests model)
+
+identityLaTeX :: Conf -> Language -> Identity -> [Job] -> LaTeX
+identityLaTeX conf language identity jobs =
+ TeXComm "header"
+ [ FixArg (fromString $ I.name identity)
+ , FixArg (fromString . fromMaybe "" . (fmap (getTranslation language . J.name)) . listToMaybe $ jobs)
+ , FixArg (fromString $ I.website identity)
+ , FixArg (fromString $ Conf.git conf)
+ , FixArg (fromString $ I.git identity)
+ ]
+
+jobsLaTeX :: Language -> Date -> [Job] -> LaTeX
+jobsLaTeX language currentDate jobs =
+ translatedSection K.Experience language
+ <> mconcat (map (jobLaTeX language currentDate) jobs)
+
+jobLaTeX :: Language -> Date -> Job -> LaTeX
+jobLaTeX language currentDate job =
+ customCommand "position"
+ [ fromString . getTranslation language $ J.name job
+ , fromString $ renderDurationAndInterval language currentDate (J.beginDate job) (J.endDate job)
+ , fromString $ ((C.name . J.company) job) ++ ", " ++ ((C.location . J.company) job)
+ , (fromString . getTranslation language . J.description $ job)
+ , case J.details job of
+ Just details@(_:_) -> translatedBullets language details
+ _ -> mempty
+ , case J.technos job of
+ Just ts -> technos ts
+ _ -> mempty
+ ]
+
+degreesLaTeX :: Language -> [Degree] -> LaTeX
+degreesLaTeX language degrees =
+ translatedSection K.EducationalBackground language
+ <> mconcat (map (degreeLaTeX language) degrees)
+
+degreeLaTeX :: Language -> Degree -> LaTeX
+degreeLaTeX language degree =
+ customCommand "position"
+ [ fromString . getTranslation language $ D.name degree
+ , fromString . show . D.year $ degree
+ , fromString $ S.name school ++ (fromMaybe "" (((++) ", ") <$> S.location school))
+ , mempty
+ , translatedBullets language $ D.topics degree
+ , mempty
+ ]
+ where school = D.school degree
+
+skillTypesLaTeX :: Language -> [SkillType] -> LaTeX
+skillTypesLaTeX language skillTypes =
+ translatedSection K.Skills language
+ <> (mconcat . map (skillTypeLaTeX language) $ skillTypes)
+
+skillTypeLaTeX :: Language -> SkillType -> LaTeX
+skillTypeLaTeX language skillType =
+ subsection (fromString . capitalizeFirstWord . getTranslation language . ST.name $ skillType)
+ <> translatedBullets language (ST.skills skillType)
+
+interestsLaTeX :: Language -> [Translated] -> LaTeX
+interestsLaTeX language interests =
+ translatedSection K.Interests language
+ <> translatedBullets language interests
+
+translatedBullets :: Language -> [Translated] -> LaTeX
+translatedBullets language = itemsEnv "bullets" . map (getTranslation language)
+
+itemsEnv :: String -> [String] -> LaTeX
+itemsEnv name items =
+ environment name . mconcat . concat . map getItem $ items
+ where getItem i =
+ [ item Nothing
+ , fromString . capitalizeFirstWord $ i
+ ]
+
+technos :: [String] -> LaTeX
+technos names =
+ environment "technos" . mconcat . concat . map getItem $ names
+ where getItem name =
+ [ item Nothing
+ , TeXComm "techno" [ FixArg (fromString name) ]
+ ]
+
+translatedSection :: Key -> Language -> LaTeX
+translatedSection key language =
+ section (fromString . capitalizeWords $ getMessage key language)
+
+customCommand :: String -> [LaTeX] -> LaTeX
+customCommand commandName commandParameters =
+ TeXComm commandName (map FixArg commandParameters)
+
+environment :: String -> LaTeX -> LaTeX
+environment name inside =
+ (TeXComm "begin" [ FixArg (fromString name) ])
+ <> inside
+ <> (TeXComm "end" [ FixArg (fromString name) ])
diff --git a/src/View/NotFound.hs b/src/View/NotFound.hs
new file mode 100644
index 0000000..c16eb6c
--- /dev/null
+++ b/src/View/NotFound.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.NotFound
+ ( renderNotFound
+ ) where
+
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5
+import Text.Blaze.Html5.Attributes
+import qualified Text.Blaze.Html5 as H
+
+import Model.Translation.Language
+import qualified Model.Translation.Key as K
+import Model.Translation.Message
+
+import View.Header (renderHeader)
+
+renderNotFound :: Language -> Html
+renderNotFound language =
+ H.div $ do
+ renderHeader language Nothing
+ H.div ! class_ "notFoundPage" $ do
+ h1 "404"
+ p .fromString $ getMessage K.PageNotFound language
diff --git a/src/View/Page.hs b/src/View/Page.hs
new file mode 100644
index 0000000..b7267e8
--- /dev/null
+++ b/src/View/Page.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Page
+ ( renderPage
+ ) where
+
+import Data.Text.Internal.Lazy
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5
+import Text.Blaze.Html5.Attributes
+import qualified Text.Blaze.Html5 as H
+import Text.Blaze.Html.Renderer.Text (renderHtml)
+
+import qualified Model as M
+import qualified Model.Identity as I
+
+renderPage :: M.Model -> Html -> Text
+renderPage model page =
+ renderHtml $ do
+ docTypeHtml $ do
+ H.head $ do
+ H.title $ fromString . I.name . M.identity $ model
+ meta ! charset "UTF-8"
+ meta ! name "viewport" ! content "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"
+ meta ! name "author" ! content (toValue $ I.name . M.identity $ model)
+ meta ! name "description" ! content (toValue $ M.description model)
+ link ! rel "stylesheet" ! type_ "text/css" ! href "/stylesheets/reset.css"
+ link ! rel "stylesheet" ! href "/stylesheets/font-awesome-4.2.0/css/font-awesome.min.css"
+ link ! rel "stylesheet" ! type_ "text/css" ! href "/design"
+ link ! rel "icon" ! type_ "image/png" ! href "/images/icon.png"
+ H.body page
diff --git a/src/View/Project.hs b/src/View/Project.hs
new file mode 100644
index 0000000..a5aaf2c
--- /dev/null
+++ b/src/View/Project.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Project
+ ( renderProjects
+ ) where
+
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5
+import Text.Blaze.Html5.Attributes
+import qualified Text.Blaze.Html5 as H
+
+import Conf (Conf)
+
+import Model.Header (Header(Projects))
+import qualified Model.Project as P
+import Model.Translated
+import Model.Translation.Language
+
+import View.Header (renderHeader)
+import View.Git (renderGitIcon)
+
+renderProjects :: Conf -> Language -> [P.Project] -> Html
+renderProjects conf language projects =
+ H.div $ do
+ renderHeader language (Just Projects)
+ H.div ! class_ "projectsPage" $
+ mapM_ (renderProject conf language) projects
+
+renderProject :: Conf -> Language -> P.Project -> Html
+renderProject conf language project =
+ H.div ! class_ "project" $ do
+ renderTitle conf project
+ H.div ! class_ "body" $ do
+ renderTechnologies (P.technologies project)
+ case P.pageLink project of
+ Just pageLink -> renderPageLink pageLink
+ Nothing -> fromString ""
+ case P.description project of
+ Just description -> renderDescription language description
+ Nothing -> H.div ""
+
+renderTitle :: Conf -> P.Project -> Html
+renderTitle conf project =
+ h1 $ do
+ toHtml (P.name project)
+ H.span ! class_ "separator" $ fromString " − "
+ renderGitIcon conf (P.git project)
+
+renderTechnologies :: [String] -> Html
+renderTechnologies technologies =
+ H.div ! class_ "technologies" $ do
+ ul $ mapM_ (H.li . fromString) technologies
+
+renderPageLink :: String -> Html
+renderPageLink pageLink =
+ H.div ! class_ "pageLink" $ do
+ H.a
+ ! href (fromString pageLink)
+ $ toHtml pageLink
+
+renderDescription :: Language -> Translated -> Html
+renderDescription language description =
+ H.div ! class_ "description" $ do
+ fromString . getTranslation language $ description
diff --git a/src/View/Resume.hs b/src/View/Resume.hs
new file mode 100644
index 0000000..ffd5c8c
--- /dev/null
+++ b/src/View/Resume.hs
@@ -0,0 +1,140 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module View.Resume
+ ( renderResume
+ ) where
+
+import Data.Maybe
+import Data.String (fromString)
+
+import Text.Blaze.Html
+import Text.Blaze.Html5 hiding (details)
+import qualified Text.Blaze.Html5 as H
+import Text.Blaze.Html5.Attributes
+
+import Conf (Conf)
+
+import qualified Model as M
+import qualified Model.Company as C
+import Model.Date
+import qualified Model.Degree as D
+import Model.Header (Header (Resume))
+import qualified Model.Identity as I
+import qualified Model.Job as J
+import qualified Model.School as S
+import qualified Model.SkillType as ST
+import Model.Translated
+import Model.Translation.Key (Key)
+import qualified Model.Translation.Key as K
+import Model.Translation.Language
+import Model.Translation.Message
+
+import View.Git (renderGit)
+import View.Header (renderHeader)
+import View.Icon (renderIcon)
+import View.Interval (renderDurationAndInterval)
+
+import Resume (resumePath)
+
+renderResume :: Conf -> Language -> Date -> M.Model -> Html
+renderResume conf language currentDate model =
+ H.div $ do
+ renderHeader language (Just Resume)
+ H.div ! class_ "resumePage" $ do
+ renderIdentity conf language model
+ renderJobs language currentDate . M.jobs $ model
+ renderDegrees language . M.degrees $ model
+ renderSkillTypes language . M.skillTypes $ model
+ renderInterests language . M.interests $ model
+
+renderIdentity :: Conf -> Language -> M.Model -> Html
+renderIdentity conf language model =
+ let identity = M.identity model
+ in H.div ! class_ "section" $ do
+ H.div ! class_ "identity" $ do
+ h1 (fromString (I.name identity))
+ renderGit conf (I.git identity)
+ a ! href (fromString $ resumePath model language) ! class_ "pdf" ! target "_blank" $
+ renderIcon "print"
+
+renderJobs :: Language -> Date -> [J.Job] -> Html
+renderJobs language currentDate jobs =
+ H.div ! class_ "section" $ do
+ sectionTitle K.Experience language
+ mapM_ (renderJob language currentDate) jobs
+
+renderJob :: Language -> Date -> J.Job -> Html
+renderJob language currentDate job =
+ H.div ! class_ "item" $ do
+
+ H.div ! class_ "title" $ do
+ H.div ! class_ "text" $
+ fromString . getTranslation language . J.name $ job
+ H.div ! class_ "date" $
+ fromString $ renderDurationAndInterval language currentDate (J.beginDate job) (J.endDate job)
+
+ H.div ! class_ "location" $ do
+ let company = J.company job
+ companyName = C.name company
+ companyLocation = C.location company
+ fromString $ companyName ++ ", " ++ companyLocation
+
+ H.div ! class_ "description" $ do
+ _ <- fromString . getTranslation language . J.description $ job
+ case J.details job of
+ Just details ->
+ ul ! class_ "bullets detail" $
+ mapM_ (\detail -> li . fromString . getTranslation language $ detail) details
+ Nothing ->
+ fromString ""
+ renderTechnos $ fromMaybe [] (J.technos job)
+
+renderTechnos :: [String] -> Html
+renderTechnos = (ul ! class_ "technos") . mapM_ ((li ! class_ "techno") . fromString)
+
+renderDegrees :: Language -> [D.Degree] -> Html
+renderDegrees language degrees =
+ H.div ! class_ "section" $ do
+ sectionTitle K.EducationalBackground language
+ mapM_ (renderDegree language) degrees
+
+renderDegree :: Language -> D.Degree -> Html
+renderDegree language degree =
+ H.div ! class_ "item" $ do
+
+ H.div ! class_ "title" $ do
+ H.div ! class_ "text " $
+ fromString . getTranslation language . D.name $ degree
+ H.div ! class_ "date" $
+ fromString . show . D.year $ degree
+
+ H.div ! class_ "location" $
+ let school = D.school degree
+ location = fromMaybe "" $ fmap (", " ++ ) (S.location school)
+ in fromString $ (S.name school) ++ location
+
+ ul ! class_ "bullets itemList" $
+ mapM_ (\topic -> li . fromString . getTranslation language $ topic) (D.topics degree)
+
+renderSkillTypes :: Language -> [ST.SkillType] -> Html
+renderSkillTypes language skillTypes =
+ H.div ! class_ "section" $ do
+ sectionTitle K.Skills language
+ mapM_ (renderSkillType language) skillTypes
+
+renderSkillType :: Language -> ST.SkillType -> Html
+renderSkillType language skillType =
+ H.div ! class_ "item" $ do
+ H.div ! class_ "title skills" $ H.div ! class_ "text" $
+ fromString . getTranslation language . ST.name $ skillType
+ ul ! class_ "bullets itemList" $
+ mapM_ (\skill -> li . fromString . getTranslation language $ skill) (ST.skills skillType)
+
+renderInterests :: Language -> [Translated] -> Html
+renderInterests language interests =
+ H.div ! class_ "section" $ do
+ sectionTitle K.Interests language
+ ul ! class_ "bullets" $ mapM_ (\interest -> li . fromString . getTranslation language $ interest) interests
+
+sectionTitle :: Key -> Language -> Html
+sectionTitle key language = h1 . fromString $ getMessage key language