diff --git a/src/Handler/Admin/Test.hs b/src/Handler/Admin/Test.hs index 6c9c64a47..5346c6aa9 100644 --- a/src/Handler/Admin/Test.hs +++ b/src/Handler/Admin/Test.hs @@ -10,6 +10,7 @@ module Handler.Admin.Test import Import import Utils.Print +import Utils.Print.Letters import Handler.Utils import Jobs diff --git a/src/Utils/Print.hs b/src/Utils/Print.hs index 0c8e9c4f7..08ab95edc 100644 --- a/src/Utils/Print.hs +++ b/src/Utils/Print.hs @@ -5,13 +5,10 @@ {-# OPTIONS_GHC -fno-warn-unused-top-binds #-} module Utils.Print - ( pdfRenewal - , sendLetter, sendLetter' + ( pdfRenewal, sendLetter' -- only used for test-letters triggered in route PrintSendR , sendEmailOrLetter , encryptPDF , sanitizeCmdArg, validCmdArgument - , templateDIN5008 - , templateRenewal -- , compileTemplate, makePDF , _Meta, addMeta , toMeta, mbMeta -- single values @@ -68,40 +65,42 @@ import Utils.Print.RenewQualification -- This is a hack to allow variable interpolation within a document. -- Pandoc currently only allows interpolation within templates. -- An alternative Route would be to use Builders, but this prevents User-edited Markup Templates -reTemplateLetter :: P.PandocMonad m => P.Meta -> StoredMarkup -> m Text -reTemplateLetter meta StoredMarkup{..} = do - tmpl <- compileTemplate strictMarkupInput - doc <- areader readerOpts strictMarkupInput - let writerOpts = def { P.writerExtensions = P.pandocExtensions - , P.writerTemplate = Just tmpl } - P.writeMarkdown writerOpts - $ appMeta setIsDeFromLang - $ addMeta meta doc - where - strictMarkupInput = toStrict markupInput - readerOpts = def { P.readerExtensions = P.pandocExtensions - , P.readerStripComments = True - } - -- reader :: (P.PandocMonad m, P.ToSources a) => P.ReaderOptions -> a -> m P.Pandoc - areader = case markupInputFormat of - MarkupHtml -> P.readHtml - MarkupMarkdown -> P.readMarkdown - MarkupPlaintext -> P.readMarkdown +-- reTemplateLetter :: P.PandocMonad m => P.Meta -> StoredMarkup -> m Text +-- reTemplateLetter meta StoredMarkup{..} = do +-- tmpl <- compileTemplate strictMarkupInput +-- doc <- areader readerOpts strictMarkupInput +-- let writerOpts = def { P.writerExtensions = P.pandocExtensions +-- , P.writerTemplate = Just tmpl } +-- P.writeMarkdown writerOpts +-- $ appMeta setIsDeFromLang +-- $ addMeta meta doc +-- where +-- strictMarkupInput = toStrict markupInput +-- readerOpts = def { P.readerExtensions = P.pandocExtensions +-- , P.readerStripComments = True +-- } +-- -- reader :: (P.PandocMonad m, P.ToSources a) => P.ReaderOptions -> a -> m P.Pandoc +-- areader = case markupInputFormat of +-- MarkupHtml -> P.readHtml +-- MarkupMarkdown -> P.readMarkdown +-- MarkupPlaintext -> P.readMarkdown -reTemplateLetter' :: P.PandocMonad m => P.Meta -> Text -> m Text -reTemplateLetter' meta md = do - tmpl <- compileTemplate md - doc <- P.readMarkdown readerOpts md - let writerOpts = def { P.writerExtensions = P.pandocExtensions - , P.writerTemplate = Just tmpl } - P.writeMarkdown writerOpts - $ appMeta setIsDeFromLang - $ addMeta meta doc - where - readerOpts = def { P.readerExtensions = P.pandocExtensions - , P.readerStripComments = True - } +-- reTemplateLetter' :: P.PandocMonad m => P.Meta -> Text -> m Text +-- reTemplateLetter' meta md = do +-- tmpl <- compileTemplate md +-- doc <- P.readMarkdown readerOpts md +-- let writerOpts = def { P.writerExtensions = P.pandocExtensions +-- , P.writerTemplate = Just tmpl } +-- P.writeMarkdown writerOpts +-- $ appMeta setIsDeFromLang +-- $ addMeta meta doc +-- where +-- readerOpts = def { P.readerExtensions = P.pandocExtensions +-- , P.readerStripComments = True +-- } + +-- | read and writes markdown, applying it as its own template to apply meta mdTemplating :: Text -> P.Meta -> HandlerFor UniWorX (Either P.PandocError Text) mdTemplating template meta = runExceptT $ do let readerOpts = def { P.readerExtensions = P.pandocExtensions @@ -179,7 +178,7 @@ mdRenewal meta = runExceptT $ do $ addMeta meta doc --- | combines 'mdRenewal' and 'pdfDIN5008' +-- | combines 'mdRenewal' and 'pdfDIN5008'; only user in PrintSendR Test Handler pdfRenewal :: P.Meta -> HandlerFor UniWorX (Either Text LBS.ByteString) pdfRenewal meta = do e_txt <- mdRenewal' meta @@ -187,27 +186,47 @@ pdfRenewal meta = do result <- actRight e_txt $ pdfDIN5008 meta return $ over _Left P.renderError result +{- -- | like pdfRenewal but without caching pdfRenewal' :: P.Meta -> P.PandocIO LBS.ByteString pdfRenewal' meta = do doc <- reTemplateLetter' meta templateRenewal pdfDIN5008' meta doc +-} -- Generic Version -pdfLetter :: Text -> P.Meta -> HandlerFor UniWorX (Either Text LBS.ByteString) +pdfLetter :: Text -> P.Meta -> Handler (Either Text LBS.ByteString) pdfLetter md meta = do e_txt <- mdTemplating md meta result <- actRight e_txt $ pdfDIN5008 meta return $ over _Left P.renderError result +renderLetter :: (MDLetter l) => User -> l -> Handler (Either Text LBS.ByteString) +renderLetter rcvr mdl = do + now <- liftIO getCurrentTime + formatter@DateTimeFormatter{ format } <- getDateTimeFormatterUser' rcvr + let lang = selectDeEn $ rcvr & userLanguages -- select either German or English only, default de; see Utils.Lang + tmpl = getTemplate $ pure mdl + meta = letterMeta mdl formatter lang + <> mkMeta + [ toMeta "paper" ("TODO"::Text) -- TODO continue here + , toMeta "printid" ("TODO"::Text) + , toMeta "lang" lang + , toMeta "date" $ format SelFormatDate now + , toMeta "rcvr-name" $ rcvr & userDisplayName + , toMeta "address" $ fromMaybe [rcvr & userDisplayName] $ getPostalAddress rcvr + --, toMeta "rcvr-email" $ rcvr & userDisplayEmail -- note that some templates use "email" already otherwise + ] + pdfLetter tmpl meta + --------------- -- PrintJobs -- --------------- --- DEPRECATED +-- Only used in print-test-handler for PrintSendR sendLetter' :: Text -> LBS.ByteString -> (Maybe UserId, Maybe UserId) -> Maybe CourseId -> Maybe QualificationId -> Maybe LmsIdent -> DB (Either Text (Text, FilePath)) sendLetter' printJobName pdf (printJobRecipient, printJobSender) printJobCourse printJobQualification printJobLmsUser = sendLetter pdf PrintJobIdentification diff --git a/src/Utils/Print/Letters.hs b/src/Utils/Print/Letters.hs index d3fb9ab54..1f6459e48 100644 --- a/src/Utils/Print/Letters.hs +++ b/src/Utils/Print/Letters.hs @@ -42,12 +42,33 @@ import Text.Hamlet -- Hardcoded Templates -- ------------------------- -templateRenewal :: Text -templateRenewal = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal.md") +data LetterKind = Din5008 -- scrlttr2: Standard postal letter with address field, expects peprinted FraportLogo + | PinLetter -- Like Din5008, but for special paper with a protected pin field + | Plain -- scrartcl: Empty, expects empty paper with no preprints + | PlainLogo -- Like plain, but expects to be printed on paper with Logo + -- | Logo -- Like plain, but prints Fraport Logo in the upper right corner + deriving (Eq, Show) + +templateLatex :: LetterKind -> Text +templateLatex = + let + tDin5008 = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008.latex") + tPinLetter = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008with_pin.latex") + tPlain = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/plain_article.latex") + in \case + PinLetter -> tPinLetter + Din5008 -> tDin5008 + PlainLogo -> tPlain + Plain -> tPlain + +-- | DEPRECATED TODO: remove templateDIN5008 :: Text templateDIN5008 = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008.latex") +templateRenewal :: Text +templateRenewal = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal.md") + --------------- diff --git a/templates/letter/din5008.latex b/templates/letter/din5008.latex index 9ad2d8280..1660f2d11 100644 --- a/templates/letter/din5008.latex +++ b/templates/letter/din5008.latex @@ -80,7 +80,7 @@ $endif$ %\usepackage[a4paper, bottom=8cm, top=3cm]{geometry} %%% THIS HAD NO EFFECT AT ALL -\usepackage{parskip} +%\usepackage{parskip}% might be useful for pandoc tightlist \usepackage{graphics} \usepackage{xcolor} @@ -120,7 +120,11 @@ $endif$ } \setkomavar{fromphone}{$phone$} \setkomavar{fromemail}{$email$} - \setkomavar{signature}{$author$} + %if there is a handwritten signature + %\setkomavar{signature}{$author$} + %if there is no handwritten signature + \setkomavar{signature}{} + \setplength{sigbeforevskip}{-\baselineskip} \setkomavar{date}{$date$} \setkomavar{place}{$place$} @@ -143,19 +147,9 @@ $endif$ \opening{$en-opening$} $endif$ - \begin{textblock}{65}(84,232)%hpos,vpos - \textcolor{black!39}{ - \begin{labeling}{Password:} - $if(is-de)$ - \item[Benutzer:] \texttt{$login$} - \item[Passwort:] \texttt{$pin$} - $else$ - \item[User:] \texttt{$login$} - \item[Password:] \texttt{$pin$} - $endif$ - \end{labeling} - ~} - \end{textblock} + \begin{textblock}{65}(142,21)%hpos,vpos + \textcolor{white!0}{:::$paper$:::$printid$:::}% + \end{textblock} $body$ diff --git a/templates/letter/din5008with_pin.latex b/templates/letter/din5008with_pin.latex new file mode 100644 index 000000000..c22e1c5c2 --- /dev/null +++ b/templates/letter/din5008with_pin.latex @@ -0,0 +1,182 @@ +%Based upon https://github.com/benedictdudel/pandoc-letter-din5008 +\documentclass[ + paper=A4, + foldmarks=BTm, % show foldmarks top, middle, bottom + foldmarks=false, % don't print foldmarks + fromalign=left, % letter head on the right + fromphone=true, % show phone number + fromemail=true, % show email + fromlogo=false, % don't show logo in letter head + version=last, % latest version of KOMA letter + pagenumber=botright, % show pagenumbers on bottom right + firstfoot=false % first-page footer +]{scrlttr2} + +\PassOptionsToPackage{hyphens}{url} +\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ +$if(title-meta)$ + pdftitle={$title-meta$}, +$endif$ +$if(author-meta)$ + pdfauthor={$author-meta$}, +$endif$ +$if(lang)$ + pdflang={$lang$}, +$endif$ +$if(subject)$ + pdfsubject={$subject$}, +$endif$ +$if(keywords)$ + pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$}, +$endif$ +} +\usepackage{url} + +\usepackage{iftex} + +%\usepackage[ngerman]{babel} +$if(lang)$ +\ifLuaTeX +\usepackage[bidi=basic]{babel} +\else +\usepackage[bidi=default]{babel} +\fi +\babelprovide[main,import]{$babel-lang$} +$for(babel-otherlangs)$ +\babelprovide[import]{$babel-otherlangs$} +$endfor$ +% get rid of language-specific shorthands (see #6817): +\let\LanguageShortHands\languageshorthands +\def\languageshorthands#1{} +$endif$ + +\ifLuaTeX + \usepackage{selnolig} % disable illegal ligatures +\fi + +\ifPDFTeX + \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage{textcomp} % provide euro and other symbols + \usepackage{DejaVuSansMono} % better monofont +\else + % if luatex or xetex + \usepackage{fontspec} + \setmonofont{DejaVu Sans Mono} +\fi + +$if(mathspec)$ + \ifXeTeX + \usepackage{mathspec} + \else + \usepackage{unicode-math} + \fi +$else$ + \usepackage{unicode-math} +$endif$ + +%\usepackage[a4paper, bottom=8cm, top=3cm]{geometry} %%% THIS HAD NO EFFECT AT ALL + +%\usepackage{parskip}% might be useful for pandoc tightlist + +\usepackage{graphics} +\usepackage{xcolor} + +\usepackage{booktabs} +\usepackage{longtable} + +\usepackage[right]{eurosym} + +\usepackage{enumitem} + +\makeatletter + \setplength{firstheadvpos}{1.8cm} + \setplength{toaddrvpos}{5.5cm} + \setlength{\@tempskipa}{-1.2cm}% + \@addtoplength{toaddrheight}{\@tempskipa} +\makeatother + +\setlength{\oddsidemargin}{\useplength{toaddrhpos}} +\addtolength{\oddsidemargin}{-1in} +\setlength{\textwidth}{\useplength{firstheadwidth}} + +\usepackage[absolute,quiet,overlay]{textpos}%,showboxes +\setlength{\TPHorizModule}{1mm} +\setlength{\TPVertModule}{1mm} + +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} + +\begin{document}% + \setkomavar{fromname}{$author$}% + \renewcommand*{\raggedsignature}{\raggedright}% + \setkomavar{fromaddress}{% + $for(return-address)$% + $return-address$$sep$\\ + $endfor$ + } + \setkomavar{fromphone}{$phone$} + \setkomavar{fromemail}{$email$} + %if there is a handwritten signature + %\setkomavar{signature}{$author$} + %if there is no handwritten signature + \setkomavar{signature}{} + \setplength{sigbeforevskip}{-\baselineskip} + + \setkomavar{date}{$date$} + \setkomavar{place}{$place$} + + $if(is-de)$ + \setkomavar{subject}{$de-subject$} + $else$ + \setkomavar{subject}{$en-subject$} + $endif$ + + \begin{letter}{% + $for(address)$ + $address$$sep$\\ + $endfor$ + } + + $if(is-de)$ + \opening{$de-opening$} + $else$ + \opening{$en-opening$} + $endif$ + + \begin{textblock}{65}(142,21)%hpos,vpos + \textcolor{white!0}{:::$paper$:::$printid$:::}% + \end{textblock} + \begin{textblock}{65}(84,232)%hpos,vpos + \textcolor{black!39}{ + \begin{labeling}{Password:} + $if(is-de)$ + \item[Benutzer:] \texttt{$login$} + \item[Passwort:] \texttt{$pin$} + $else$ + \item[User:] \texttt{$login$} + \item[Password:] \texttt{$pin$} + $endif$ + \end{labeling} + ~} + \end{textblock} + + $body$ + + $if(is-de)$ + \closing{$de-closing$} + $else$ + \closing{$en-closing$} + $endif$ + + %\ps $postskriptum$ + + $if(encludes)$ + \setkomavar*{enclseparator}{Anlage} + \encl{$encludes$} + $endif$ + \end{letter} +\end{document} diff --git a/templates/letter/fraport_renewal.md b/templates/letter/fraport_renewal.md index 07978d9ed..08d2148ac 100644 --- a/templates/letter/fraport_renewal.md +++ b/templates/letter/fraport_renewal.md @@ -12,10 +12,10 @@ return-address: de-opening: Liebe Fahrberechtigungsinhaber, en-opening: Dear driver, de-closing: | - Mit freundlichen Grüßen, + Mit freundlichen Grüßen, Ihre Fahrerausbildung en-closing: | - With kind regards, + With kind regards, Your Fraport Driver Training encludes: hyperrefoptions: hidelinks @@ -29,11 +29,12 @@ lang: de-de is-de: true login: 123456 pin: abcdef +paper: pin # Emfpänger -examinee: E. M. Pfänger +examinee: P. Rüfling address: - - Musterfirma GmbH - E. M. Pfänger + - Musterfirma GmbH - Musterstraße 11 - 12345 Musterstadt ... diff --git a/templates/letter/plain_article.latex b/templates/letter/plain_article.latex new file mode 100644 index 000000000..baab246d9 --- /dev/null +++ b/templates/letter/plain_article.latex @@ -0,0 +1,105 @@ +%Based upon https://github.com/benedictdudel/pandoc-letter-din5008 +\documentclass[ + paper=A4, + firstfoot=false % first-page footer +]{scrlttr2} + +\PassOptionsToPackage{hyphens}{url} +\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ +$if(title-meta)$ + pdftitle={$title-meta$}, +$endif$ +$if(author-meta)$ + pdfauthor={$author-meta$}, +$endif$ +$if(lang)$ + pdflang={$lang$}, +$endif$ +$if(subject)$ + pdfsubject={$subject$}, +$endif$ +$if(keywords)$ + pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$}, +$endif$ +} +\usepackage{url} + +\usepackage{iftex} + +%\usepackage[ngerman]{babel} +$if(lang)$ +\ifLuaTeX +\usepackage[bidi=basic]{babel} +\else +\usepackage[bidi=default]{babel} +\fi +\babelprovide[main,import]{$babel-lang$} +$for(babel-otherlangs)$ +\babelprovide[import]{$babel-otherlangs$} +$endfor$ +% get rid of language-specific shorthands (see #6817): +\let\LanguageShortHands\languageshorthands +\def\languageshorthands#1{} +$endif$ + +\ifLuaTeX + \usepackage{selnolig} % disable illegal ligatures +\fi + +\ifPDFTeX + \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage{textcomp} % provide euro and other symbols + \usepackage{DejaVuSansMono} % better monofont +\else + % if luatex or xetex + \usepackage{fontspec} + \setmonofont{DejaVu Sans Mono} +\fi + +$if(mathspec)$ + \ifXeTeX + \usepackage{mathspec} + \else + \usepackage{unicode-math} + \fi +$else$ + \usepackage{unicode-math} +$endif$ + +%\usepackage[a4paper, bottom=8cm, top=3cm]{geometry} %%% THIS HAD NO EFFECT AT ALL + +%\usepackage{parskip}% might be useful for pandoc tightlist + +\usepackage{graphics} +\usepackage{xcolor} + +\usepackage{booktabs} +\usepackage{longtable} + +\usepackage[right]{eurosym} + +\usepackage{enumitem} + +\setlength{\oddsidemargin}{\useplength{toaddrhpos}} +\addtolength{\oddsidemargin}{-1in} +\setlength{\textwidth}{\useplength{firstheadwidth}} + +\usepackage[absolute,quiet,overlay]{textpos}%,showboxes +\setlength{\TPHorizModule}{1mm} +\setlength{\TPVertModule}{1mm} + +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} + +\begin{document}% + \begin{textblock}{65}(142,21)%hpos,vpos + \textcolor{white!0}{:::$paper$:::$printid$:::}% + \end{textblock} + + $body$ + +\end{document}