mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-02 21:42:52 +00:00
Merge pull request #213 from eikek/item-notes-placement
Item notes placement
This commit is contained in:
commit
0883637e89
@ -305,14 +305,16 @@ loginInfo model =
|
||||
footer : Model -> Html Msg
|
||||
footer model =
|
||||
div [ class "ui footer" ]
|
||||
[ a [ href "https://github.com/eikek/docspell" ]
|
||||
[ i [ class "ui github icon" ] []
|
||||
]
|
||||
, span []
|
||||
[ text "Docspell "
|
||||
, text model.version.version
|
||||
, text " (#"
|
||||
, String.left 8 model.version.gitCommit |> text
|
||||
, text ")"
|
||||
[ div [ class "ui center aligned container" ]
|
||||
[ a [ href "https://github.com/eikek/docspell" ]
|
||||
[ i [ class "ui github icon" ] []
|
||||
]
|
||||
, span []
|
||||
[ text "Docspell "
|
||||
, text model.version.version
|
||||
, text " (#"
|
||||
, String.left 8 model.version.gitCommit |> text
|
||||
, text ")"
|
||||
]
|
||||
]
|
||||
]
|
||||
|
File diff suppressed because it is too large
Load Diff
173
modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm
Normal file
173
modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm
Normal file
@ -0,0 +1,173 @@
|
||||
module Comp.ItemDetail.Model exposing
|
||||
( AttachmentRename
|
||||
, Model
|
||||
, NotesField(..)
|
||||
, emptyModel
|
||||
, isEditNotes
|
||||
)
|
||||
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
import Api.Model.FolderItem exposing (FolderItem)
|
||||
import Api.Model.IdName exposing (IdName)
|
||||
import Api.Model.ItemDetail exposing (ItemDetail)
|
||||
import Api.Model.ItemProposals exposing (ItemProposals)
|
||||
import Api.Model.Tag exposing (Tag)
|
||||
import Comp.AttachmentMeta
|
||||
import Comp.DatePicker
|
||||
import Comp.DetailEdit
|
||||
import Comp.Dropdown
|
||||
import Comp.Dropzone
|
||||
import Comp.ItemMail
|
||||
import Comp.MarkdownInput
|
||||
import Comp.SentMails
|
||||
import Comp.YesNoDimmer
|
||||
import Data.Direction exposing (Direction)
|
||||
import DatePicker exposing (DatePicker)
|
||||
import Dict exposing (Dict)
|
||||
import File exposing (File)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html5.DragDrop as DD
|
||||
import Page exposing (Page(..))
|
||||
import Set exposing (Set)
|
||||
import Util.Tag
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ item : ItemDetail
|
||||
, visibleAttach : Int
|
||||
, menuOpen : Bool
|
||||
, tagModel : Comp.Dropdown.Model Tag
|
||||
, directionModel : Comp.Dropdown.Model Direction
|
||||
, corrOrgModel : Comp.Dropdown.Model IdName
|
||||
, corrPersonModel : Comp.Dropdown.Model IdName
|
||||
, concPersonModel : Comp.Dropdown.Model IdName
|
||||
, concEquipModel : Comp.Dropdown.Model IdName
|
||||
, folderModel : Comp.Dropdown.Model IdName
|
||||
, allFolders : List FolderItem
|
||||
, nameModel : String
|
||||
, notesModel : Maybe String
|
||||
, notesField : NotesField
|
||||
, deleteItemConfirm : Comp.YesNoDimmer.Model
|
||||
, itemDatePicker : DatePicker
|
||||
, itemDate : Maybe Int
|
||||
, itemProposals : ItemProposals
|
||||
, dueDate : Maybe Int
|
||||
, dueDatePicker : DatePicker
|
||||
, itemMail : Comp.ItemMail.Model
|
||||
, mailOpen : Bool
|
||||
, mailSending : Bool
|
||||
, mailSendResult : Maybe BasicResult
|
||||
, sentMails : Comp.SentMails.Model
|
||||
, sentMailsOpen : Bool
|
||||
, attachMeta : Dict String Comp.AttachmentMeta.Model
|
||||
, attachMetaOpen : Bool
|
||||
, pdfNativeView : Maybe Bool
|
||||
, deleteAttachConfirm : Comp.YesNoDimmer.Model
|
||||
, addFilesOpen : Bool
|
||||
, addFilesModel : Comp.Dropzone.Model
|
||||
, selectedFiles : List File
|
||||
, completed : Set String
|
||||
, errored : Set String
|
||||
, loading : Set String
|
||||
, attachDD : DD.Model String String
|
||||
, modalEdit : Maybe Comp.DetailEdit.Model
|
||||
, attachRename : Maybe AttachmentRename
|
||||
}
|
||||
|
||||
|
||||
type NotesField
|
||||
= ViewNotes
|
||||
| EditNotes Comp.MarkdownInput.Model
|
||||
|
||||
|
||||
type alias AttachmentRename =
|
||||
{ id : String
|
||||
, newName : String
|
||||
}
|
||||
|
||||
|
||||
isEditNotes : NotesField -> Bool
|
||||
isEditNotes field =
|
||||
case field of
|
||||
EditNotes _ ->
|
||||
True
|
||||
|
||||
ViewNotes ->
|
||||
False
|
||||
|
||||
|
||||
emptyModel : Model
|
||||
emptyModel =
|
||||
{ item = Api.Model.ItemDetail.empty
|
||||
, visibleAttach = 0
|
||||
, menuOpen = False
|
||||
, tagModel =
|
||||
Util.Tag.makeDropdownModel
|
||||
, directionModel =
|
||||
Comp.Dropdown.makeSingleList
|
||||
{ makeOption =
|
||||
\entry ->
|
||||
{ value = Data.Direction.toString entry
|
||||
, text = Data.Direction.toString entry
|
||||
, additional = ""
|
||||
}
|
||||
, options = Data.Direction.all
|
||||
, placeholder = "Choose a direction…"
|
||||
, selected = Nothing
|
||||
}
|
||||
, corrOrgModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name, additional = "" }
|
||||
, placeholder = ""
|
||||
}
|
||||
, corrPersonModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name, additional = "" }
|
||||
, placeholder = ""
|
||||
}
|
||||
, concPersonModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name, additional = "" }
|
||||
, placeholder = ""
|
||||
}
|
||||
, concEquipModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name, additional = "" }
|
||||
, placeholder = ""
|
||||
}
|
||||
, folderModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name, additional = "" }
|
||||
, placeholder = ""
|
||||
}
|
||||
, allFolders = []
|
||||
, nameModel = ""
|
||||
, notesModel = Nothing
|
||||
, notesField = ViewNotes
|
||||
, deleteItemConfirm = Comp.YesNoDimmer.emptyModel
|
||||
, itemDatePicker = Comp.DatePicker.emptyModel
|
||||
, itemDate = Nothing
|
||||
, itemProposals = Api.Model.ItemProposals.empty
|
||||
, dueDate = Nothing
|
||||
, dueDatePicker = Comp.DatePicker.emptyModel
|
||||
, itemMail = Comp.ItemMail.emptyModel
|
||||
, mailOpen = False
|
||||
, mailSending = False
|
||||
, mailSendResult = Nothing
|
||||
, sentMails = Comp.SentMails.init
|
||||
, sentMailsOpen = False
|
||||
, attachMeta = Dict.empty
|
||||
, attachMetaOpen = False
|
||||
, pdfNativeView = Nothing
|
||||
, deleteAttachConfirm = Comp.YesNoDimmer.emptyModel
|
||||
, addFilesOpen = False
|
||||
, addFilesModel = Comp.Dropzone.init Comp.Dropzone.defaultSettings
|
||||
, selectedFiles = []
|
||||
, completed = Set.empty
|
||||
, errored = Set.empty
|
||||
, loading = Set.empty
|
||||
, attachDD = DD.init
|
||||
, modalEdit = Nothing
|
||||
, attachRename = Nothing
|
||||
}
|
1317
modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm
Normal file
1317
modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm
Normal file
File diff suppressed because it is too large
Load Diff
1147
modules/webapp/src/main/elm/Comp/ItemDetail/View.elm
Normal file
1147
modules/webapp/src/main/elm/Comp/ItemDetail/View.elm
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,11 @@ module Comp.MarkdownInput exposing
|
||||
, init
|
||||
, update
|
||||
, view
|
||||
, viewCheatLink
|
||||
, viewContent
|
||||
, viewEditLink
|
||||
, viewPreviewLink
|
||||
, viewSplitLink
|
||||
)
|
||||
|
||||
import Html exposing (..)
|
||||
@ -26,7 +31,7 @@ type alias Model =
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ display = Split
|
||||
{ display = Edit
|
||||
, cheatSheetUrl = "https://www.markdownguide.org/cheat-sheet"
|
||||
}
|
||||
|
||||
@ -46,59 +51,96 @@ update txt msg model =
|
||||
( { model | display = dsp }, txt )
|
||||
|
||||
|
||||
viewContent : String -> Model -> Html Msg
|
||||
viewContent txt model =
|
||||
case model.display of
|
||||
Edit ->
|
||||
editDisplay txt
|
||||
|
||||
Preview ->
|
||||
previewDisplay txt
|
||||
|
||||
Split ->
|
||||
splitDisplay txt
|
||||
|
||||
|
||||
viewEditLink : (Bool -> Attribute Msg) -> Model -> Html Msg
|
||||
viewEditLink classes model =
|
||||
a
|
||||
[ onClick (SetDisplay Edit)
|
||||
, classes (model.display == Edit)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Edit"
|
||||
]
|
||||
|
||||
|
||||
viewPreviewLink : (Bool -> Attribute Msg) -> Model -> Html Msg
|
||||
viewPreviewLink classes model =
|
||||
a
|
||||
[ onClick (SetDisplay Preview)
|
||||
, classes (model.display == Preview)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Preview"
|
||||
]
|
||||
|
||||
|
||||
viewSplitLink : (Bool -> Attribute Msg) -> Model -> Html Msg
|
||||
viewSplitLink classes model =
|
||||
a
|
||||
[ onClick (SetDisplay Split)
|
||||
, classes (model.display == Split)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Split"
|
||||
]
|
||||
|
||||
|
||||
viewCheatLink : String -> Model -> Html msg
|
||||
viewCheatLink classes model =
|
||||
a
|
||||
[ class classes
|
||||
, target "_new"
|
||||
, href model.cheatSheetUrl
|
||||
]
|
||||
[ i [ class "ui help icon" ] []
|
||||
, text "Supports Markdown"
|
||||
]
|
||||
|
||||
|
||||
view : String -> Model -> Html Msg
|
||||
view txt model =
|
||||
div []
|
||||
[ div [ class "ui top attached tabular mini menu" ]
|
||||
[ a
|
||||
[ classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", model.display == Edit )
|
||||
]
|
||||
, onClick (SetDisplay Edit)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Edit"
|
||||
]
|
||||
, a
|
||||
[ classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", model.display == Preview )
|
||||
]
|
||||
, onClick (SetDisplay Preview)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Preview"
|
||||
]
|
||||
, a
|
||||
[ classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", model.display == Split )
|
||||
]
|
||||
, onClick (SetDisplay Split)
|
||||
, href "#"
|
||||
]
|
||||
[ text "Split"
|
||||
]
|
||||
, a
|
||||
[ class "ui right floated help-link link item"
|
||||
, target "_new"
|
||||
, href model.cheatSheetUrl
|
||||
]
|
||||
[ i [ class "ui help icon" ] []
|
||||
, text "Supports Markdown"
|
||||
]
|
||||
[ viewEditLink
|
||||
(\act ->
|
||||
classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", act )
|
||||
]
|
||||
)
|
||||
model
|
||||
, viewPreviewLink
|
||||
(\act ->
|
||||
classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", act )
|
||||
]
|
||||
)
|
||||
model
|
||||
, viewSplitLink
|
||||
(\act ->
|
||||
classList
|
||||
[ ( "ui link item", True )
|
||||
, ( "active", act )
|
||||
]
|
||||
)
|
||||
model
|
||||
, viewCheatLink "ui right floated help-link link item" model
|
||||
]
|
||||
, div [ class "ui bottom attached segment" ]
|
||||
[ case model.display of
|
||||
Edit ->
|
||||
editDisplay txt
|
||||
|
||||
Preview ->
|
||||
previewDisplay txt
|
||||
|
||||
Split ->
|
||||
splitDisplay txt
|
||||
[ viewContent txt model
|
||||
]
|
||||
]
|
||||
|
||||
@ -108,6 +150,7 @@ editDisplay txt =
|
||||
textarea
|
||||
[ class "markdown-editor"
|
||||
, onInput SetText
|
||||
, placeholder "Add notes here…"
|
||||
]
|
||||
[ text txt ]
|
||||
|
||||
|
@ -12,7 +12,7 @@ import Comp.ColorTagger
|
||||
import Comp.IntField
|
||||
import Data.Color exposing (Color)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Data.UiSettings exposing (Pos(..), UiSettings)
|
||||
import Dict exposing (Dict)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
@ -29,6 +29,7 @@ type alias Model =
|
||||
, nativePdfPreview : Bool
|
||||
, itemSearchNoteLength : Maybe Int
|
||||
, searchNoteLengthModel : Comp.IntField.Model
|
||||
, itemDetailNotesPosition : Pos
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +55,7 @@ init flags settings =
|
||||
(Just flags.config.maxNoteLength)
|
||||
False
|
||||
"Max. Note Length"
|
||||
, itemDetailNotesPosition = settings.itemDetailNotesPosition
|
||||
}
|
||||
, Api.getTags flags "" GetTagsResp
|
||||
)
|
||||
@ -65,6 +67,7 @@ type Msg
|
||||
| GetTagsResp (Result Http.Error TagList)
|
||||
| TogglePdfPreview
|
||||
| NoteLengthMsg Comp.IntField.Msg
|
||||
| SetNotesPosition Pos
|
||||
|
||||
|
||||
|
||||
@ -106,6 +109,17 @@ update sett msg model =
|
||||
in
|
||||
( model_, nextSettings )
|
||||
|
||||
SetNotesPosition pos ->
|
||||
let
|
||||
model_ =
|
||||
{ model | itemDetailNotesPosition = pos }
|
||||
in
|
||||
if model_.itemDetailNotesPosition == sett.itemDetailNotesPosition then
|
||||
( model_, Nothing )
|
||||
|
||||
else
|
||||
( model_, Just { sett | itemDetailNotesPosition = model_.itemDetailNotesPosition } )
|
||||
|
||||
TagColorMsg lm ->
|
||||
let
|
||||
( m_, d_ ) =
|
||||
@ -207,6 +221,31 @@ view flags _ model =
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "grouped fields" ]
|
||||
[ label [] [ text "Position of item notes" ]
|
||||
, div [ class "field" ]
|
||||
[ div [ class "ui radio checkbox" ]
|
||||
[ input
|
||||
[ type_ "radio"
|
||||
, checked (model.itemDetailNotesPosition == Top)
|
||||
, onCheck (\_ -> SetNotesPosition Top)
|
||||
]
|
||||
[]
|
||||
, label [] [ text "Top" ]
|
||||
]
|
||||
]
|
||||
, div [ class "field" ]
|
||||
[ div [ class "ui radio checkbox" ]
|
||||
[ input
|
||||
[ type_ "radio"
|
||||
, checked (model.itemDetailNotesPosition == Bottom)
|
||||
, onCheck (\_ -> SetNotesPosition Bottom)
|
||||
]
|
||||
[]
|
||||
, label [] [ text "Bottom" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "ui dividing header" ]
|
||||
[ text "Tag Category Colors"
|
||||
]
|
||||
|
@ -1,9 +1,12 @@
|
||||
module Data.UiSettings exposing
|
||||
( StoredUiSettings
|
||||
( Pos(..)
|
||||
, StoredUiSettings
|
||||
, UiSettings
|
||||
, defaults
|
||||
, merge
|
||||
, mergeDefaults
|
||||
, posFromString
|
||||
, posToString
|
||||
, tagColor
|
||||
, tagColorString
|
||||
, toStoredUiSettings
|
||||
@ -27,6 +30,7 @@ type alias StoredUiSettings =
|
||||
, tagCategoryColors : List ( String, String )
|
||||
, nativePdfPreview : Bool
|
||||
, itemSearchNoteLength : Maybe Int
|
||||
, itemDetailNotesPosition : Maybe String
|
||||
}
|
||||
|
||||
|
||||
@ -42,15 +46,45 @@ type alias UiSettings =
|
||||
, tagCategoryColors : Dict String Color
|
||||
, nativePdfPreview : Bool
|
||||
, itemSearchNoteLength : Int
|
||||
, itemDetailNotesPosition : Pos
|
||||
}
|
||||
|
||||
|
||||
type Pos
|
||||
= Top
|
||||
| Bottom
|
||||
|
||||
|
||||
posToString : Pos -> String
|
||||
posToString pos =
|
||||
case pos of
|
||||
Top ->
|
||||
"top"
|
||||
|
||||
Bottom ->
|
||||
"bottom"
|
||||
|
||||
|
||||
posFromString : String -> Maybe Pos
|
||||
posFromString str =
|
||||
case str of
|
||||
"top" ->
|
||||
Just Top
|
||||
|
||||
"bottom" ->
|
||||
Just Bottom
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
defaults : UiSettings
|
||||
defaults =
|
||||
{ itemSearchPageSize = 60
|
||||
, tagCategoryColors = Dict.empty
|
||||
, nativePdfPreview = False
|
||||
, itemSearchNoteLength = 0
|
||||
, itemDetailNotesPosition = Top
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +103,9 @@ merge given fallback =
|
||||
, nativePdfPreview = given.nativePdfPreview
|
||||
, itemSearchNoteLength =
|
||||
choose given.itemSearchNoteLength fallback.itemSearchNoteLength
|
||||
, itemDetailNotesPosition =
|
||||
choose (Maybe.andThen posFromString given.itemDetailNotesPosition)
|
||||
fallback.itemDetailNotesPosition
|
||||
}
|
||||
|
||||
|
||||
@ -85,6 +122,7 @@ toStoredUiSettings settings =
|
||||
|> Dict.toList
|
||||
, nativePdfPreview = settings.nativePdfPreview
|
||||
, itemSearchNoteLength = Just settings.itemSearchNoteLength
|
||||
, itemDetailNotesPosition = Just (posToString settings.itemDetailNotesPosition)
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ module Page.ItemDetail.Data exposing (Model, Msg(..), emptyModel)
|
||||
|
||||
import Api.Model.ItemDetail exposing (ItemDetail)
|
||||
import Comp.ItemDetail
|
||||
import Comp.ItemDetail.Update
|
||||
import Http
|
||||
|
||||
|
||||
@ -18,5 +19,5 @@ emptyModel =
|
||||
|
||||
type Msg
|
||||
= Init String
|
||||
| ItemDetailMsg Comp.ItemDetail.Msg
|
||||
| ItemDetailMsg Comp.ItemDetail.Update.Msg
|
||||
| ItemResp (Result Http.Error ItemDetail)
|
||||
|
@ -3,6 +3,7 @@ module Page.ItemDetail.Update exposing (update)
|
||||
import Api
|
||||
import Browser.Navigation as Nav
|
||||
import Comp.ItemDetail
|
||||
import Comp.ItemDetail.Update
|
||||
import Data.Flags exposing (Flags)
|
||||
import Page.ItemDetail.Data exposing (Model, Msg(..))
|
||||
|
||||
@ -13,7 +14,7 @@ update key flags next msg model =
|
||||
Init id ->
|
||||
let
|
||||
( lm, lc, ls ) =
|
||||
Comp.ItemDetail.update key flags next Comp.ItemDetail.Init model.detail
|
||||
Comp.ItemDetail.update key flags next Comp.ItemDetail.Update.Init model.detail
|
||||
in
|
||||
( { model | detail = lm }
|
||||
, Cmd.batch [ Api.itemDetail flags id ItemResp, Cmd.map ItemDetailMsg lc ]
|
||||
@ -33,7 +34,7 @@ update key flags next msg model =
|
||||
ItemResp (Ok item) ->
|
||||
let
|
||||
lmsg =
|
||||
Comp.ItemDetail.SetItem item
|
||||
Comp.ItemDetail.Update.SetItem item
|
||||
in
|
||||
update key flags next (ItemDetailMsg lmsg) model
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
.default-layout .main-content {
|
||||
margin-top: 45px;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
.default-layout .top-menu {
|
||||
@ -67,13 +68,6 @@
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.default-layout .ui.segment .item-notes {
|
||||
padding: 0 1em;
|
||||
}
|
||||
.default-layout .ui.segment.item-notes-display {
|
||||
background: rgba(246, 255, 158, 0.4);
|
||||
}
|
||||
|
||||
.default-layout .extracted-text {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
@ -128,7 +122,7 @@ textarea.markdown-editor {
|
||||
max-height: 300px;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
min-height: 10em;
|
||||
min-height: 5em;
|
||||
}
|
||||
|
||||
.default-layout .job-log {
|
||||
@ -265,7 +259,6 @@ label span.muted {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Datepicker
|
||||
From: https://github.com/CurrySoftware/elm-datepicker/blob/3.1.0/css/elm-datepicker.css
|
||||
License: BSD-3-Clause
|
||||
|
Loading…
x
Reference in New Issue
Block a user