diff options
author | Joris Guyonvarch | 2014-04-06 22:55:16 +0200 |
---|---|---|
committer | Joris | 2019-05-01 15:34:22 +0200 |
commit | 0fe906ae7453aa684e998bbcc7a78b62d84f0206 (patch) | |
tree | d3968af830b964193349187fb6fc583780cd0ce3 /src/View | |
parent | 8b11c4be2b3ac354fa14534662dbd92374617a3e (diff) |
Show resume and projects from a configuration file
Diffstat (limited to 'src/View')
-rw-r--r-- | src/View/Git.hs | 37 | ||||
-rw-r--r-- | src/View/Header.hs | 42 | ||||
-rw-r--r-- | src/View/Icon.hs | 17 | ||||
-rw-r--r-- | src/View/Interval.hs | 39 | ||||
-rw-r--r-- | src/View/LaTeX/Resume.hs | 148 | ||||
-rw-r--r-- | src/View/NotFound.hs | 26 | ||||
-rw-r--r-- | src/View/Page.hs | 33 | ||||
-rw-r--r-- | src/View/Project.hs | 66 | ||||
-rw-r--r-- | src/View/Resume.hs | 140 |
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 |