mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-23 10:58:26 +00:00
Initial version.
Features: - Upload PDF files let them analyze - Manage meta data and items - See processing in webapp
This commit is contained in:
10
modules/webapp/src/main/elm/Util/Address.elm
Normal file
10
modules/webapp/src/main/elm/Util/Address.elm
Normal file
@ -0,0 +1,10 @@
|
||||
module Util.Address exposing (..)
|
||||
|
||||
import Api.Model.Address exposing (Address)
|
||||
|
||||
toString: Address -> String
|
||||
toString a =
|
||||
[ a.street, a.zip, a.city, a.country ]
|
||||
|> List.filter (String.isEmpty >> not)
|
||||
|> List.intersperse ", "
|
||||
|> String.concat
|
9
modules/webapp/src/main/elm/Util/Contact.elm
Normal file
9
modules/webapp/src/main/elm/Util/Contact.elm
Normal file
@ -0,0 +1,9 @@
|
||||
module Util.Contact exposing (..)
|
||||
|
||||
import Api.Model.Contact exposing (Contact)
|
||||
|
||||
toString: List Contact -> String
|
||||
toString contacts =
|
||||
List.map (\c -> c.kind ++ ": " ++ c.value) contacts
|
||||
|> List.intersperse ", "
|
||||
|> String.concat
|
47
modules/webapp/src/main/elm/Util/Duration.elm
Normal file
47
modules/webapp/src/main/elm/Util/Duration.elm
Normal file
@ -0,0 +1,47 @@
|
||||
module Util.Duration exposing (Duration, toHuman)
|
||||
|
||||
-- 486ms -> 12s -> 1:05 -> 59:45 -> 1:02:12
|
||||
|
||||
type alias Duration = Int
|
||||
|
||||
toHuman: Duration -> String
|
||||
toHuman dur =
|
||||
fromMillis dur
|
||||
|
||||
|
||||
-- implementation
|
||||
|
||||
fromMillis: Int -> String
|
||||
fromMillis ms =
|
||||
case ms // 1000 of
|
||||
0 ->
|
||||
(String.fromInt ms) ++ "ms"
|
||||
n ->
|
||||
fromSeconds n
|
||||
|
||||
fromSeconds: Int -> String
|
||||
fromSeconds sec =
|
||||
case sec // 60 of
|
||||
0 ->
|
||||
(String.fromInt sec) ++ "s"
|
||||
n ->
|
||||
let
|
||||
s = sec - (n * 60)
|
||||
in
|
||||
(fromMinutes n) ++ ":" ++ (num s)
|
||||
|
||||
fromMinutes: Int -> String
|
||||
fromMinutes min =
|
||||
case min // 60 of
|
||||
0 ->
|
||||
(num min)
|
||||
n ->
|
||||
let
|
||||
m = min - (n * 60)
|
||||
in
|
||||
(num n) ++ ":" ++ (num m)
|
||||
|
||||
num: Int -> String
|
||||
num n =
|
||||
String.fromInt n
|
||||
|> (++) (if n < 10 then "0" else "")
|
9
modules/webapp/src/main/elm/Util/File.elm
Normal file
9
modules/webapp/src/main/elm/Util/File.elm
Normal file
@ -0,0 +1,9 @@
|
||||
module Util.File exposing (..)
|
||||
|
||||
import File exposing (File)
|
||||
import Util.String
|
||||
|
||||
makeFileId: File -> String
|
||||
makeFileId file =
|
||||
(File.name file) ++ "-" ++ (File.size file |> String.fromInt)
|
||||
|> Util.String.crazyEncode
|
40
modules/webapp/src/main/elm/Util/Html.elm
Normal file
40
modules/webapp/src/main/elm/Util/Html.elm
Normal file
@ -0,0 +1,40 @@
|
||||
module Util.Html exposing (..)
|
||||
|
||||
import Html exposing (Attribute)
|
||||
import Html.Attributes exposing (class)
|
||||
import Html.Events exposing (on, keyCode)
|
||||
import Json.Decode as Decode
|
||||
|
||||
type KeyCode
|
||||
= Up
|
||||
| Down
|
||||
| Left
|
||||
| Right
|
||||
| Enter
|
||||
|
||||
intToKeyCode: Int -> Maybe KeyCode
|
||||
intToKeyCode code =
|
||||
case code of
|
||||
38 -> Just Up
|
||||
40 -> Just Down
|
||||
39 -> Just Right
|
||||
37 -> Just Left
|
||||
13 -> Just Enter
|
||||
_ -> Nothing
|
||||
|
||||
onKeyUp : (Int -> msg) -> Attribute msg
|
||||
onKeyUp tagger =
|
||||
on "keyup" (Decode.map tagger keyCode)
|
||||
|
||||
|
||||
onClickk : msg -> Attribute msg
|
||||
onClickk msg =
|
||||
Html.Events.preventDefaultOn "click" (Decode.map alwaysPreventDefault (Decode.succeed msg))
|
||||
|
||||
alwaysPreventDefault : msg -> ( msg, Bool )
|
||||
alwaysPreventDefault msg =
|
||||
( msg, True )
|
||||
|
||||
classActive: Bool -> String -> Attribute msg
|
||||
classActive active classes =
|
||||
class (classes ++ (if active then " active" else ""))
|
@ -14,6 +14,7 @@ authReq: {url: String
|
||||
,headers: List Http.Header
|
||||
,body: Http.Body
|
||||
,expect: Http.Expect msg
|
||||
,tracker: Maybe String
|
||||
} -> Cmd msg
|
||||
authReq req =
|
||||
Http.request
|
||||
@ -23,7 +24,7 @@ authReq req =
|
||||
, expect = req.expect
|
||||
, body = req.body
|
||||
, timeout = Nothing
|
||||
, tracker = Nothing
|
||||
, tracker = req.tracker
|
||||
}
|
||||
|
||||
authPost: {url: String
|
||||
@ -39,6 +40,40 @@ authPost req =
|
||||
, expect = req.expect
|
||||
, method = "POST"
|
||||
, headers = []
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
authPostTrack: {url: String
|
||||
,account: AuthResult
|
||||
,body: Http.Body
|
||||
,expect: Http.Expect msg
|
||||
,tracker: String
|
||||
} -> Cmd msg
|
||||
authPostTrack req =
|
||||
authReq
|
||||
{ url = req.url
|
||||
, account = req.account
|
||||
, body = req.body
|
||||
, expect = req.expect
|
||||
, method = "POST"
|
||||
, headers = []
|
||||
, tracker = Just req.tracker
|
||||
}
|
||||
|
||||
authPut: {url: String
|
||||
,account: AuthResult
|
||||
,body: Http.Body
|
||||
,expect: Http.Expect msg
|
||||
} -> Cmd msg
|
||||
authPut req =
|
||||
authReq
|
||||
{ url = req.url
|
||||
, account = req.account
|
||||
, body = req.body
|
||||
, expect = req.expect
|
||||
, method = "PUT"
|
||||
, headers = []
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
authGet: {url: String
|
||||
@ -53,6 +88,22 @@ authGet req =
|
||||
, expect = req.expect
|
||||
, method = "GET"
|
||||
, headers = []
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
authDelete: {url: String
|
||||
,account: AuthResult
|
||||
,expect: Http.Expect msg
|
||||
} -> Cmd msg
|
||||
authDelete req =
|
||||
authReq
|
||||
{ url = req.url
|
||||
, account = req.account
|
||||
, body = Http.emptyBody
|
||||
, expect = req.expect
|
||||
, method = "DELETE"
|
||||
, headers = []
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
|
||||
|
53
modules/webapp/src/main/elm/Util/List.elm
Normal file
53
modules/webapp/src/main/elm/Util/List.elm
Normal file
@ -0,0 +1,53 @@
|
||||
module Util.List exposing ( find
|
||||
, findIndexed
|
||||
, get
|
||||
, distinct
|
||||
, findNext
|
||||
, findPrev
|
||||
)
|
||||
|
||||
get: List a -> Int -> Maybe a
|
||||
get list index =
|
||||
if index < 0 then Nothing
|
||||
else case list of
|
||||
[] ->
|
||||
Nothing
|
||||
x :: xs ->
|
||||
if index == 0
|
||||
then Just x
|
||||
else get xs (index - 1)
|
||||
|
||||
find: (a -> Bool) -> List a -> Maybe a
|
||||
find pred list =
|
||||
findIndexed pred list |> Maybe.map Tuple.first
|
||||
|
||||
findIndexed: (a -> Bool) -> List a -> Maybe (a, Int)
|
||||
findIndexed pred list =
|
||||
findIndexed1 pred list 0
|
||||
|
||||
findIndexed1: (a -> Bool) -> List a -> Int -> Maybe (a, Int)
|
||||
findIndexed1 pred list index =
|
||||
case list of
|
||||
[] -> Nothing
|
||||
x :: xs ->
|
||||
if pred x then Just (x, index)
|
||||
else findIndexed1 pred xs (index + 1)
|
||||
|
||||
distinct: List a -> List a
|
||||
distinct list =
|
||||
List.reverse <|
|
||||
List.foldl (\a -> \r -> if (List.member a r) then r else a :: r) [] list
|
||||
|
||||
findPrev: (a -> Bool) -> List a -> Maybe a
|
||||
findPrev pred list =
|
||||
findIndexed pred list
|
||||
|> Maybe.map Tuple.second
|
||||
|> Maybe.map (\i -> i - 1)
|
||||
|> Maybe.andThen (get list)
|
||||
|
||||
findNext: (a -> Bool) -> List a -> Maybe a
|
||||
findNext pred list =
|
||||
findIndexed pred list
|
||||
|> Maybe.map Tuple.second
|
||||
|> Maybe.map (\i -> i + 1)
|
||||
|> Maybe.andThen (get list)
|
23
modules/webapp/src/main/elm/Util/Maybe.elm
Normal file
23
modules/webapp/src/main/elm/Util/Maybe.elm
Normal file
@ -0,0 +1,23 @@
|
||||
module Util.Maybe exposing (..)
|
||||
|
||||
nonEmpty: Maybe a -> Bool
|
||||
nonEmpty ma =
|
||||
Maybe.map (\_ -> True) ma
|
||||
|> Maybe.withDefault False
|
||||
|
||||
isEmpty: Maybe a -> Bool
|
||||
isEmpty ma =
|
||||
not (nonEmpty ma)
|
||||
|
||||
withDefault: Maybe a -> Maybe a -> Maybe a
|
||||
withDefault ma1 ma2 =
|
||||
if isEmpty ma2 then ma1 else ma2
|
||||
|
||||
or: List (Maybe a) -> Maybe a
|
||||
or listma =
|
||||
case listma of
|
||||
[] -> Nothing
|
||||
el :: els ->
|
||||
case el of
|
||||
Just _ -> el
|
||||
Nothing -> or els
|
24
modules/webapp/src/main/elm/Util/Size.elm
Normal file
24
modules/webapp/src/main/elm/Util/Size.elm
Normal file
@ -0,0 +1,24 @@
|
||||
module Util.Size exposing (..)
|
||||
|
||||
type SizeUnit = G|M|K|B
|
||||
|
||||
prettyNumber: Float -> String
|
||||
prettyNumber n =
|
||||
let
|
||||
parts = String.split "." (String.fromFloat n)
|
||||
in
|
||||
case parts of
|
||||
n0 :: d :: [] -> n0 ++ "." ++ (String.left 2 d)
|
||||
_ -> String.join "." parts
|
||||
|
||||
bytesReadable: SizeUnit -> Float -> String
|
||||
bytesReadable unit n =
|
||||
let
|
||||
k = n / 1024
|
||||
num = prettyNumber n
|
||||
in
|
||||
case unit of
|
||||
G -> num ++ "G"
|
||||
M -> if k > 1 then (bytesReadable G k) else num ++ "M"
|
||||
K -> if k > 1 then (bytesReadable M k) else num ++ "K"
|
||||
B -> if k > 1 then (bytesReadable K k) else num ++ "B"
|
28
modules/webapp/src/main/elm/Util/String.elm
Normal file
28
modules/webapp/src/main/elm/Util/String.elm
Normal file
@ -0,0 +1,28 @@
|
||||
module Util.String exposing (..)
|
||||
|
||||
import Base64
|
||||
|
||||
crazyEncode: String -> String
|
||||
crazyEncode str =
|
||||
let
|
||||
b64 = Base64.encode str
|
||||
len = String.length b64
|
||||
in
|
||||
case (String.right 2 b64 |> String.toList) of
|
||||
'=' :: '=' :: [] ->
|
||||
(String.dropRight 2 b64) ++ "0"
|
||||
|
||||
_ :: '=' :: [] ->
|
||||
(String.dropRight 1 b64) ++ "1"
|
||||
|
||||
_ ->
|
||||
b64
|
||||
|
||||
ellipsis: Int -> String -> String
|
||||
ellipsis len str =
|
||||
if String.length str <= len then str
|
||||
else (String.left (len - 3) str) ++ "..."
|
||||
|
||||
withDefault: String -> String -> String
|
||||
withDefault default str =
|
||||
if str == "" then default else str
|
87
modules/webapp/src/main/elm/Util/Time.elm
Normal file
87
modules/webapp/src/main/elm/Util/Time.elm
Normal file
@ -0,0 +1,87 @@
|
||||
module Util.Time exposing (..)
|
||||
|
||||
import DateFormat
|
||||
import Time exposing (Posix, Zone, utc)
|
||||
|
||||
|
||||
dateFormatter : Zone -> Posix -> String
|
||||
dateFormatter =
|
||||
DateFormat.format
|
||||
[ DateFormat.dayOfWeekNameAbbreviated
|
||||
, DateFormat.text ", "
|
||||
, DateFormat.monthNameFull
|
||||
, DateFormat.text " "
|
||||
, DateFormat.dayOfMonthSuffix
|
||||
, DateFormat.text ", "
|
||||
, DateFormat.yearNumber
|
||||
]
|
||||
|
||||
dateFormatterShort: Zone -> Posix -> String
|
||||
dateFormatterShort =
|
||||
DateFormat.format
|
||||
[ DateFormat.yearNumber
|
||||
, DateFormat.text "/"
|
||||
, DateFormat.monthFixed
|
||||
, DateFormat.text "/"
|
||||
, DateFormat.dayOfMonthFixed
|
||||
]
|
||||
|
||||
timeFormatter: Zone -> Posix -> String
|
||||
timeFormatter =
|
||||
DateFormat.format
|
||||
[ DateFormat.hourMilitaryNumber
|
||||
, DateFormat.text ":"
|
||||
, DateFormat.minuteFixed
|
||||
]
|
||||
|
||||
isoDateTimeFormatter: Zone -> Posix -> String
|
||||
isoDateTimeFormatter =
|
||||
DateFormat.format
|
||||
[ DateFormat.yearNumber
|
||||
, DateFormat.text "-"
|
||||
, DateFormat.monthFixed
|
||||
, DateFormat.text "-"
|
||||
, DateFormat.dayOfMonthFixed
|
||||
, DateFormat.text "T"
|
||||
, DateFormat.hourMilitaryNumber
|
||||
, DateFormat.text ":"
|
||||
, DateFormat.minuteFixed
|
||||
, DateFormat.text ":"
|
||||
, DateFormat.secondFixed
|
||||
]
|
||||
|
||||
|
||||
timeZone: Zone
|
||||
timeZone =
|
||||
utc
|
||||
|
||||
{- Format millis into "Wed, 10. Jan 2018, 18:57"
|
||||
-}
|
||||
formatDateTime: Int -> String
|
||||
formatDateTime millis =
|
||||
(formatDate millis) ++ ", " ++ (formatTime millis)
|
||||
|
||||
formatIsoDateTime: Int -> String
|
||||
formatIsoDateTime millis =
|
||||
Time.millisToPosix millis
|
||||
|> isoDateTimeFormatter timeZone
|
||||
|
||||
{- Format millis into "18:57". The current time (not the duration of
|
||||
the millis).
|
||||
-}
|
||||
formatTime: Int -> String
|
||||
formatTime millis =
|
||||
Time.millisToPosix millis
|
||||
|> timeFormatter timeZone
|
||||
|
||||
{- Format millis into "Wed, 10. Jan 2018"
|
||||
-}
|
||||
formatDate: Int -> String
|
||||
formatDate millis =
|
||||
Time.millisToPosix millis
|
||||
|> dateFormatter timeZone
|
||||
|
||||
formatDateShort: Int -> String
|
||||
formatDateShort millis =
|
||||
Time.millisToPosix millis
|
||||
|> dateFormatterShort timeZone
|
15
modules/webapp/src/main/elm/Util/Update.elm
Normal file
15
modules/webapp/src/main/elm/Util/Update.elm
Normal file
@ -0,0 +1,15 @@
|
||||
module Util.Update exposing (..)
|
||||
|
||||
|
||||
andThen1: List (a -> (a, Cmd b)) -> a -> (a, Cmd b)
|
||||
andThen1 fs a =
|
||||
let
|
||||
init = (a, [])
|
||||
update el tuple =
|
||||
let
|
||||
(a2, c2) = el (Tuple.first tuple)
|
||||
in
|
||||
(a2, c2 :: (Tuple.second tuple))
|
||||
in
|
||||
List.foldl update init fs
|
||||
|> Tuple.mapSecond Cmd.batch
|
Reference in New Issue
Block a user