Initial version.

Features:

- Upload PDF files let them analyze

- Manage meta data and items

- See processing in webapp
This commit is contained in:
Eike Kettner
2019-07-23 00:53:30 +02:00
parent 6154e6a387
commit 831cd8b655
341 changed files with 23634 additions and 484 deletions

View 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

View 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

View 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 "")

View 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

View 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 ""))

View File

@ -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
}

View 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)

View 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

View 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"

View 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

View 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

View 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