diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail.elm b/modules/webapp/src/main/elm/Comp/ItemDetail.elm index ec9917f2..7e320da8 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail.elm @@ -38,6 +38,6 @@ update = Comp.ItemDetail.Update.update -view2 : Texts -> ItemNav -> UiSettings -> Model -> Html Msg +view2 : Texts -> Flags -> ItemNav -> UiSettings -> Model -> Html Msg view2 = Comp.ItemDetail.View2.view diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm index de3affe7..2a9336e5 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm @@ -18,7 +18,10 @@ module Comp.ItemDetail.Model exposing , ViewMode(..) , emptyModel , initSelectViewModel + , initShowQrModel , isEditNotes + , isShowQrAttach + , isShowQrItem , personMatchesOrg , resultModel , resultModelCmd @@ -40,7 +43,6 @@ import Api.Model.SentMails exposing (SentMails) import Api.Model.Tag exposing (Tag) import Api.Model.TagList exposing (TagList) import Comp.AttachmentMeta -import Comp.ConfirmModal import Comp.CustomFieldMultiInput import Comp.DatePicker import Comp.DetailEdit @@ -118,9 +120,33 @@ type alias Model = , attachmentDropdownOpen : Bool , editMenuTabsOpen : Set String , viewMode : ViewMode + , showQrModel : ShowQrModel } +type alias ShowQrModel = + { item : Bool + , attach : Bool + } + + +initShowQrModel : ShowQrModel +initShowQrModel = + { item = False + , attach = False + } + + +isShowQrItem : ShowQrModel -> Bool +isShowQrItem model = + model.item + + +isShowQrAttach : ShowQrModel -> Bool +isShowQrAttach model = + model.attach + + type ConfirmModalValue = ConfirmModalReprocessItem Msg | ConfirmModalReprocessFile Msg @@ -230,6 +256,7 @@ emptyModel = , attachmentDropdownOpen = False , editMenuTabsOpen = Set.empty , viewMode = SimpleView + , showQrModel = initShowQrModel } @@ -340,6 +367,9 @@ type Msg | ReprocessItemConfirmed | ToggleSelectView | RestoreItem + | ToggleShowQrItem String + | ToggleShowQrAttach String + | PrintElement String type SaveNameState diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/ShowQrCode.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/ShowQrCode.elm new file mode 100644 index 00000000..2b649ed5 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/ShowQrCode.elm @@ -0,0 +1,117 @@ +{- + Copyright 2020 Docspell Contributors + + SPDX-License-Identifier: GPL-3.0-or-later +-} + + +module Comp.ItemDetail.ShowQrCode exposing (UrlId(..), qrCodeElementId, view, view1) + +import Api +import Comp.Basic as B +import Comp.ItemDetail.Model exposing (Model, Msg(..), isShowQrAttach, isShowQrItem) +import Comp.MenuBar as MB +import Data.Flags exposing (Flags) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import QRCode +import Styles as S + + +view : Flags -> String -> Model -> UrlId -> Html Msg +view flags classes model urlId = + case urlId of + Attach _ -> + if isShowQrAttach model.showQrModel then + view1 flags classes urlId + + else + span [ class "hidden" ] [] + + Item _ -> + if isShowQrItem model.showQrModel then + view1 flags classes urlId + + else + span [ class "hidden" ] [] + + +view1 : Flags -> String -> UrlId -> Html Msg +view1 flags classes urlId = + let + docUrl = + case urlId of + Attach str -> + flags.config.baseUrl ++ Api.fileURL str + + Item str -> + flags.config.baseUrl ++ "/app/item/" ++ str + + elementId = + qrCodeElementId urlId + + toggleShowQr = + case urlId of + Attach id -> + ToggleShowQrAttach id + + Item id -> + ToggleShowQrItem id + in + div + [ class "flex flex-col py-2 px-2 items-center" + , class classes + ] + [ MB.view + { start = + [ MB.PrimaryButton + { tagger = PrintElement elementId + , title = "Print this QR code" + , icon = Just "fa fa-print" + , label = "Print" + } + ] + , end = + [ MB.SecondaryButton + { tagger = toggleShowQr + , title = "Close" + , icon = Just "fa fa-times" + , label = "Close" + } + ] + , rootClasses = "w-full mt-2 mb-4" + } + , div [ class "flex flex-col sm:flex-row sm:space-x-2" ] + [ div + [ class S.border + , class S.qrCode + , id elementId + ] + [ qrCodeView docUrl + ] + ] + ] + + +qrCodeElementId : UrlId -> String +qrCodeElementId urlId = + case urlId of + Attach str -> + "qr-attach-" ++ str + + Item str -> + "qr-item-" ++ str + + +type UrlId + = Attach String + | Item String + + +qrCodeView : String -> Html msg +qrCodeView message = + QRCode.encode message + |> Result.map QRCode.toSvg + |> Result.withDefault + (text "Error generating QR code") diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm index 0838a985..26dea7a9 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm @@ -11,8 +11,19 @@ import Api import Api.Model.Attachment exposing (Attachment) import Comp.AttachmentMeta import Comp.ItemDetail.ConfirmModalView -import Comp.ItemDetail.Model exposing (Model, Msg(..), NotesField(..), SaveNameState(..), ViewMode(..)) +import Comp.ItemDetail.Model + exposing + ( Model + , Msg(..) + , NotesField(..) + , SaveNameState(..) + , ViewMode(..) + , isShowQrAttach + ) +import Comp.ItemDetail.ShowQrCode import Comp.MenuBar as MB +import Data.Flags exposing (Flags) +import Data.Icons as Icons import Data.UiSettings exposing (UiSettings) import Dict import Html exposing (..) @@ -27,8 +38,8 @@ import Util.Size import Util.String -view : Texts -> UiSettings -> Model -> Int -> Attachment -> Html Msg -view texts settings model pos attach = +view : Texts -> Flags -> UiSettings -> Model -> Int -> Attachment -> Html Msg +view texts flags settings model pos attach = let fileUrl = Api.fileURL attach.id @@ -61,6 +72,11 @@ view texts settings model pos attach = Nothing -> span [ class "hidden" ] [] + else if isShowQrAttach model.showQrModel then + Comp.ItemDetail.ShowQrCode.view1 flags + "border-r border-l border-b dark:border-bluegray-600 h-full" + (Comp.ItemDetail.ShowQrCode.Attach attach.id) + else div [ class "flex flex-col relative px-2 pt-2 h-full" @@ -269,6 +285,13 @@ attachHeader texts settings model _ attach = , href "#" ] } + , { icon = Icons.showQr + , label = texts.showQrCode + , attrs = + [ onClick (ToggleShowQrAttach attach.id) + , href "#" + ] + } , { icon = "fa fa-trash" , label = texts.deleteThisFile , attrs = diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm index d3574835..1289a52f 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm @@ -42,7 +42,10 @@ import Comp.ItemDetail.Model , UpdateResult , ViewMode(..) , initSelectViewModel + , initShowQrModel , isEditNotes + , isShowQrAttach + , isShowQrItem , resultModel , resultModelCmd , resultModelCmdSub @@ -66,6 +69,7 @@ import Dict import Html5.DragDrop as DD import Http import Page exposing (Page(..)) +import Ports import Set exposing (Set) import Throttle import Time @@ -1607,6 +1611,29 @@ update key flags inav settings msg model = RestoreItem -> resultModelCmd ( model, Api.restoreItem flags model.item.id SaveResp ) + ToggleShowQrItem id -> + let + sqm = + model.showQrModel + + next = + { sqm | item = not sqm.item } + in + resultModel { model | showQrModel = next } + + ToggleShowQrAttach id -> + let + sqm = + model.showQrModel + + next = + { sqm | attach = not sqm.attach } + in + resultModel { model | attachmentDropdownOpen = False, showQrModel = next } + + PrintElement id -> + resultModelCmd ( model, Ports.printElement id ) + --- Helper diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm index 0b4f7559..addfe0a0 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm @@ -19,12 +19,15 @@ import Comp.ItemDetail.Model , Msg(..) , NotesField(..) , SaveNameState(..) + , isShowQrItem ) import Comp.ItemDetail.Notes +import Comp.ItemDetail.ShowQrCode import Comp.ItemDetail.SingleAttachment import Comp.ItemMail import Comp.MenuBar as MB import Comp.SentMails +import Data.Flags exposing (Flags) import Data.Icons as Icons import Data.ItemNav exposing (ItemNav) import Data.UiSettings exposing (UiSettings) @@ -36,12 +39,12 @@ import Page exposing (Page(..)) import Styles as S -view : Texts -> ItemNav -> UiSettings -> Model -> Html Msg -view texts inav settings model = +view : Texts -> Flags -> ItemNav -> UiSettings -> Model -> Html Msg +view texts flags inav settings model = div [ class "flex flex-col h-full" ] [ header texts settings model , menuBar texts inav settings model - , body texts inav settings model + , body texts flags inav settings model , itemModal texts model ] @@ -146,7 +149,7 @@ menuBar texts inav settings model = [ ( "bg-gray-200 dark:bg-bluegray-600", model.addFilesOpen ) ] , if model.addFilesOpen then - title "Close" + title texts.close else title texts.addMoreFiles @@ -156,6 +159,22 @@ menuBar texts inav settings model = ] [ Icons.addFilesIcon2 "" ] + , MB.CustomElement <| + a + [ classList + [ ( "bg-gray-200 dark:bg-bluegray-600", isShowQrItem model.showQrModel ) + ] + , if isShowQrItem model.showQrModel then + title texts.close + + else + title texts.showQrCode + , onClick (ToggleShowQrItem model.item.id) + , class S.secondaryBasicButton + , href "#" + ] + [ Icons.showQrIcon "" + ] , MB.CustomElement <| a [ class S.primaryButton @@ -214,20 +233,24 @@ menuBar texts inav settings model = } -body : Texts -> ItemNav -> UiSettings -> Model -> Html Msg -body texts _ settings model = +body : Texts -> Flags -> ItemNav -> UiSettings -> Model -> Html Msg +body texts flags _ settings model = div [ class "grid gap-2 grid-cols-1 md:grid-cols-3 h-full" ] - [ leftArea texts settings model - , rightArea texts settings model + [ leftArea texts flags settings model + , rightArea texts flags settings model ] -leftArea : Texts -> UiSettings -> Model -> Html Msg -leftArea texts settings model = +leftArea : Texts -> Flags -> UiSettings -> Model -> Html Msg +leftArea texts flags settings model = div [ class "w-full md:order-first md:mr-2 flex flex-col" ] [ addDetailForm texts settings model , sendMailForm texts settings model , Comp.ItemDetail.AddFilesForm.view texts.addFilesForm model + , Comp.ItemDetail.ShowQrCode.view flags + (S.border ++ " mb-4") + model + (Comp.ItemDetail.ShowQrCode.Item model.item.id) , Comp.ItemDetail.Notes.view texts.notes model , div [ classList @@ -245,15 +268,15 @@ leftArea texts settings model = ] -rightArea : Texts -> UiSettings -> Model -> Html Msg -rightArea texts settings model = +rightArea : Texts -> Flags -> UiSettings -> Model -> Html Msg +rightArea texts flags settings model = div [ class "md:col-span-2 h-full" ] - (attachmentsBody texts settings model) + (attachmentsBody texts flags settings model) -attachmentsBody : Texts -> UiSettings -> Model -> List (Html Msg) -attachmentsBody texts settings model = - List.indexedMap (Comp.ItemDetail.SingleAttachment.view texts.singleAttachment settings model) +attachmentsBody : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +attachmentsBody texts flags settings model = + List.indexedMap (Comp.ItemDetail.SingleAttachment.view texts.singleAttachment flags settings model) model.item.attachments diff --git a/modules/webapp/src/main/elm/Comp/SourceManage.elm b/modules/webapp/src/main/elm/Comp/SourceManage.elm index 1753eb31..cfa7f501 100644 --- a/modules/webapp/src/main/elm/Comp/SourceManage.elm +++ b/modules/webapp/src/main/elm/Comp/SourceManage.elm @@ -279,9 +279,6 @@ viewLinks2 texts flags _ source = styleUrl = "truncate px-2 py-2 border-0 border-t border-b border-r font-mono text-sm my-auto rounded-r border-gray-400 dark:border-bluegray-500" - - styleQr = - "max-w-min dark:bg-bluegray-400 bg-gray-50 mx-auto md:mx-0" in div [] @@ -350,7 +347,7 @@ viewLinks2 texts flags _ source = , div [ class "py-2" ] [ div [ class S.border - , class styleQr + , class S.qrCode ] [ qrCodeView texts appUrl ] @@ -386,7 +383,7 @@ viewLinks2 texts flags _ source = , div [ class "py-2" ] [ div [ class S.border - , class styleQr + , class S.qrCode ] [ qrCodeView texts apiUrl ] diff --git a/modules/webapp/src/main/elm/Data/Icons.elm b/modules/webapp/src/main/elm/Data/Icons.elm index f0fd4976..76a0ab7f 100644 --- a/modules/webapp/src/main/elm/Data/Icons.elm +++ b/modules/webapp/src/main/elm/Data/Icons.elm @@ -6,9 +6,7 @@ module Data.Icons exposing - ( addFiles - , addFiles2 - , addFilesIcon + ( addFiles2 , addFilesIcon2 , concerned , concerned2 @@ -60,6 +58,8 @@ module Data.Icons exposing , personIcon2 , search , searchIcon + , showQr + , showQrIcon , source , source2 , sourceIcon @@ -321,26 +321,26 @@ editNotesIcon = i [ class editNotes ] [] -addFiles : String -addFiles = - "file plus icon" - - addFiles2 : String addFiles2 = "fa fa-file-upload" -addFilesIcon : Html msg -addFilesIcon = - i [ class addFiles ] [] - - addFilesIcon2 : String -> Html msg addFilesIcon2 classes = i [ class addFiles2, class classes ] [] +showQr : String +showQr = + "fa fa-qrcode" + + +showQrIcon : String -> Html msg +showQrIcon classes = + i [ class showQr, class classes ] [] + + tag : String tag = "tag icon" diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm index dda86e66..f64eadb7 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm @@ -55,6 +55,8 @@ type alias Texts = , sendingMailNow : String , formatDateTime : Int -> String , mailSendSuccessful : String + , showQrCode : String + , close : String } @@ -89,6 +91,8 @@ gb = , sendingMailNow = "Sending e-mail…" , formatDateTime = DF.formatDateTimeLong Messages.UiLanguage.English , mailSendSuccessful = "Mail sent." + , showQrCode = "Show the URL to this page as QR code" + , close = "Close" } @@ -123,4 +127,6 @@ de = , sendingMailNow = "E-Mail wird gesendet…" , formatDateTime = DF.formatDateTimeLong Messages.UiLanguage.German , mailSendSuccessful = "E-Mail wurde versendet." + , showQrCode = "Den Link zu dieser Seite als QR code anzeigen" + , close = "Schließen" } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm index b26acff6..ef8a57db 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm @@ -31,6 +31,7 @@ type alias Texts = , selectModeTitle : String , exitSelectMode : String , deleteAttachments : String + , showQrCode : String } @@ -51,6 +52,7 @@ gb = , selectModeTitle = "Select Mode" , exitSelectMode = "Exit Select Mode" , deleteAttachments = "Delete attachments" + , showQrCode = "Show URL as QR code" } @@ -71,4 +73,5 @@ de = , selectModeTitle = "Auswahlmodus" , exitSelectMode = "Auswahlmodus beenden" , deleteAttachments = "Anhänge löschen" + , showQrCode = "Link als QR Code anzeigen" } diff --git a/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm b/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm index 1c0d574b..7b5158a0 100644 --- a/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm +++ b/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm @@ -61,11 +61,11 @@ viewSidebar texts visible flags settings model = viewContent : Texts -> ItemNav -> Flags -> UiSettings -> Model -> Html Msg -viewContent texts inav _ settings model = +viewContent texts inav flags settings model = div [ id "content" , class S.content ] [ Html.map ItemDetailMsg - (Comp.ItemDetail.view2 texts.itemDetail inav settings model.detail) + (Comp.ItemDetail.view2 texts.itemDetail flags inav settings model.detail) ] diff --git a/modules/webapp/src/main/elm/Ports.elm b/modules/webapp/src/main/elm/Ports.elm index 7fd14f39..51438dfa 100644 --- a/modules/webapp/src/main/elm/Ports.elm +++ b/modules/webapp/src/main/elm/Ports.elm @@ -8,6 +8,7 @@ port module Ports exposing ( checkSearchQueryString , initClipboard + , printElement , receiveCheckQueryResult , receiveUiSettings , removeAccount @@ -48,6 +49,12 @@ port receiveUiSettings : (StoredUiSettings -> msg) -> Sub msg port requestUiSettings : AuthResult -> Cmd msg +{-| Creates a new window/tab, writes the contents of the given element +and calls the print dialog. +-} +port printElement : String -> Cmd msg + + setUiTheme : UiTheme -> Cmd msg setUiTheme theme = internalSetUiTheme (Data.UiTheme.toString theme) diff --git a/modules/webapp/src/main/elm/Styles.elm b/modules/webapp/src/main/elm/Styles.elm index e92b29fe..c73865fa 100644 --- a/modules/webapp/src/main/elm/Styles.elm +++ b/modules/webapp/src/main/elm/Styles.elm @@ -351,3 +351,8 @@ tableMain = tableRow : String tableRow = "border-t dark:border-bluegray-600" + + +qrCode : String +qrCode = + "max-w-min dark:bg-bluegray-400 bg-gray-50 mx-auto md:mx-0" diff --git a/modules/webapp/src/main/webjar/docspell.js b/modules/webapp/src/main/webjar/docspell.js index d13f6889..a5518163 100644 --- a/modules/webapp/src/main/webjar/docspell.js +++ b/modules/webapp/src/main/webjar/docspell.js @@ -105,3 +105,31 @@ elmApp.ports.checkSearchQueryString.subscribe(function(args) { elmApp.ports.receiveCheckQueryResult.send(answer); } }); + +elmApp.ports.printElement.subscribe(function(id) { + if (id) { + var el = document.getElementById(id); + var head = document.getElementsByTagName('head'); + if (head && head.length > 0) { + head = head[0]; + } + if (el) { + var w = window.open(); + w.document.write(''); + if (head) { + w.document.write('
'); + ['title', 'meta'].forEach(function(el) { + var headEls = head.getElementsByTagName(el); + for (var i=0; i