mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-08 07:59:51 +00:00
Add routes and upload form to item detail
This commit is contained in:
parent
f4949446e3
commit
a5ca3b0325
@ -87,12 +87,6 @@ paths:
|
|||||||
The upload meta data can be used to tell, whether multiple
|
The upload meta data can be used to tell, whether multiple
|
||||||
files are one item, or if each file should become a single
|
files are one item, or if each file should become a single
|
||||||
item. By default, each file will be a one item.
|
item. By default, each file will be a one item.
|
||||||
|
|
||||||
Only certain file types are supported:
|
|
||||||
|
|
||||||
* application/pdf
|
|
||||||
|
|
||||||
Support for more types might be added.
|
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: "#/components/parameters/id"
|
- $ref: "#/components/parameters/id"
|
||||||
requestBody:
|
requestBody:
|
||||||
@ -115,6 +109,48 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/BasicResult"
|
$ref: "#/components/schemas/BasicResult"
|
||||||
|
/open/upload/item/{itemId}/{id}:
|
||||||
|
post:
|
||||||
|
tags: [ Upload ]
|
||||||
|
summary: Upload files to docspell.
|
||||||
|
description: |
|
||||||
|
Upload a file to docspell for processing. The id is a *source
|
||||||
|
id* configured by a collective. Files are submitted for
|
||||||
|
processing which eventually resuts in an item in the inbox of
|
||||||
|
the corresponding collective. This endpoint associates the
|
||||||
|
files to an existing item identified by its `itemId`.
|
||||||
|
|
||||||
|
The request must be a `multipart/form-data` request, where the
|
||||||
|
first part has name `meta`, is optional and may contain upload
|
||||||
|
metadata as JSON. Checkout the structure `ItemUploadMeta` at
|
||||||
|
the end if it is not shown here. Other parts specify the
|
||||||
|
files. Multiple files can be specified, but at least on is
|
||||||
|
required.
|
||||||
|
|
||||||
|
Upload meta data is ignored.
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/id"
|
||||||
|
- $ref: "#/components/parameters/itemId"
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
meta:
|
||||||
|
$ref: "#/components/schemas/ItemUploadMeta"
|
||||||
|
file:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Ok
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/BasicResult"
|
||||||
/sec/checkfile/{checksum}:
|
/sec/checkfile/{checksum}:
|
||||||
get:
|
get:
|
||||||
tags: [ Upload ]
|
tags: [ Upload ]
|
||||||
@ -155,12 +191,6 @@ paths:
|
|||||||
The upload meta data can be used to tell, whether multiple
|
The upload meta data can be used to tell, whether multiple
|
||||||
files are one item, or if each file should become a single
|
files are one item, or if each file should become a single
|
||||||
item. By default, each file will be a one item.
|
item. By default, each file will be a one item.
|
||||||
|
|
||||||
Only certain file types are supported:
|
|
||||||
|
|
||||||
* application/pdf
|
|
||||||
|
|
||||||
Support for more types might be added.
|
|
||||||
security:
|
security:
|
||||||
- authTokenHeader: []
|
- authTokenHeader: []
|
||||||
requestBody:
|
requestBody:
|
||||||
@ -183,6 +213,50 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/BasicResult"
|
$ref: "#/components/schemas/BasicResult"
|
||||||
|
/sec/upload/{itemId}:
|
||||||
|
post:
|
||||||
|
tags: [ Upload ]
|
||||||
|
summary: Upload files to docspell.
|
||||||
|
description: |
|
||||||
|
Upload files to docspell for processing. This route is meant
|
||||||
|
for authenticated users that upload files to their account.
|
||||||
|
This endpoint will associate the files to an existing item
|
||||||
|
identified by its `itemId`.
|
||||||
|
|
||||||
|
Everything else is the same as with the
|
||||||
|
`/open/upload/item/{itemId}/{id}` endpoint.
|
||||||
|
|
||||||
|
The request must be a "multipart/form-data" request, where the
|
||||||
|
first part is optional and may contain upload metadata as
|
||||||
|
JSON. Other parts specify the files. Multiple files can be
|
||||||
|
specified, but at least on is required.
|
||||||
|
|
||||||
|
The upload meta data is ignored, since the item already
|
||||||
|
exists.
|
||||||
|
security:
|
||||||
|
- authTokenHeader: []
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/itemId"
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
meta:
|
||||||
|
$ref: "#/components/schemas/ItemUploadMeta"
|
||||||
|
file:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Ok
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/BasicResult"
|
||||||
/open/signup/register:
|
/open/signup/register:
|
||||||
post:
|
post:
|
||||||
tags: [ Registration ]
|
tags: [ Registration ]
|
||||||
@ -3156,6 +3230,13 @@ components:
|
|||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
itemId:
|
||||||
|
name: itemId
|
||||||
|
in: path
|
||||||
|
description: An identifier for an item
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
full:
|
full:
|
||||||
name: full
|
name: full
|
||||||
in: query
|
in: query
|
||||||
|
@ -39,6 +39,19 @@ object UploadRoutes {
|
|||||||
result <- backend.upload.submit(updata, user.account, true, None)
|
result <- backend.upload.submit(updata, user.account, true, None)
|
||||||
res <- Ok(basicResult(result))
|
res <- Ok(basicResult(result))
|
||||||
} yield res
|
} yield res
|
||||||
|
|
||||||
|
case req @ POST -> Root / "item" / Ident(itemId) =>
|
||||||
|
for {
|
||||||
|
multipart <- req.as[Multipart[F]]
|
||||||
|
updata <- readMultipart(
|
||||||
|
multipart,
|
||||||
|
logger,
|
||||||
|
Priority.High,
|
||||||
|
cfg.backend.files.validMimeTypes
|
||||||
|
)
|
||||||
|
result <- backend.upload.submit(updata, user.account, true, Some(itemId))
|
||||||
|
res <- Ok(basicResult(result))
|
||||||
|
} yield res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +72,19 @@ object UploadRoutes {
|
|||||||
result <- backend.upload.submit(updata, id, true, None)
|
result <- backend.upload.submit(updata, id, true, None)
|
||||||
res <- Ok(basicResult(result))
|
res <- Ok(basicResult(result))
|
||||||
} yield res
|
} yield res
|
||||||
|
|
||||||
|
case req @ POST -> Root / "item" / Ident(itemId) / Ident(id) =>
|
||||||
|
for {
|
||||||
|
multipart <- req.as[Multipart[F]]
|
||||||
|
updata <- readMultipart(
|
||||||
|
multipart,
|
||||||
|
logger,
|
||||||
|
Priority.Low,
|
||||||
|
cfg.backend.files.validMimeTypes
|
||||||
|
)
|
||||||
|
result <- backend.upload.submit(updata, id, true, Some(itemId))
|
||||||
|
res <- Ok(basicResult(result))
|
||||||
|
} yield res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ module Api exposing
|
|||||||
, submitNotifyDueItems
|
, submitNotifyDueItems
|
||||||
, updateScanMailbox
|
, updateScanMailbox
|
||||||
, upload
|
, upload
|
||||||
|
, uploadAmend
|
||||||
, uploadSingle
|
, uploadSingle
|
||||||
, versionInfo
|
, versionInfo
|
||||||
)
|
)
|
||||||
@ -429,7 +430,42 @@ createImapSettings flags mname ems receive =
|
|||||||
--- Upload
|
--- Upload
|
||||||
|
|
||||||
|
|
||||||
upload : Flags -> Maybe String -> ItemUploadMeta -> List File -> (String -> Result Http.Error BasicResult -> msg) -> List (Cmd msg)
|
uploadAmend :
|
||||||
|
Flags
|
||||||
|
-> String
|
||||||
|
-> List File
|
||||||
|
-> (String -> Result Http.Error BasicResult -> msg)
|
||||||
|
-> List (Cmd msg)
|
||||||
|
uploadAmend flags itemId files receive =
|
||||||
|
let
|
||||||
|
mkReq file =
|
||||||
|
let
|
||||||
|
fid =
|
||||||
|
Util.File.makeFileId file
|
||||||
|
|
||||||
|
path =
|
||||||
|
"/api/v1/sec/upload/item/" ++ itemId
|
||||||
|
in
|
||||||
|
Http2.authPostTrack
|
||||||
|
{ url = flags.config.baseUrl ++ path
|
||||||
|
, account = getAccount flags
|
||||||
|
, body =
|
||||||
|
Http.multipartBody <|
|
||||||
|
[ Http.filePart "file[]" file ]
|
||||||
|
, expect = Http.expectJson (receive fid) Api.Model.BasicResult.decoder
|
||||||
|
, tracker = fid
|
||||||
|
}
|
||||||
|
in
|
||||||
|
List.map mkReq files
|
||||||
|
|
||||||
|
|
||||||
|
upload :
|
||||||
|
Flags
|
||||||
|
-> Maybe String
|
||||||
|
-> ItemUploadMeta
|
||||||
|
-> List File
|
||||||
|
-> (String -> Result Http.Error BasicResult -> msg)
|
||||||
|
-> List (Cmd msg)
|
||||||
upload flags sourceId meta files receive =
|
upload flags sourceId meta files receive =
|
||||||
let
|
let
|
||||||
metaStr =
|
metaStr =
|
||||||
@ -457,7 +493,14 @@ upload flags sourceId meta files receive =
|
|||||||
List.map mkReq files
|
List.map mkReq files
|
||||||
|
|
||||||
|
|
||||||
uploadSingle : Flags -> Maybe String -> ItemUploadMeta -> String -> List File -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
uploadSingle :
|
||||||
|
Flags
|
||||||
|
-> Maybe String
|
||||||
|
-> ItemUploadMeta
|
||||||
|
-> String
|
||||||
|
-> List File
|
||||||
|
-> (Result Http.Error BasicResult -> msg)
|
||||||
|
-> Cmd msg
|
||||||
uploadSingle flags sourceId meta track files receive =
|
uploadSingle flags sourceId meta track files receive =
|
||||||
let
|
let
|
||||||
metaStr =
|
metaStr =
|
||||||
|
@ -25,6 +25,7 @@ import Browser.Navigation as Nav
|
|||||||
import Comp.AttachmentMeta
|
import Comp.AttachmentMeta
|
||||||
import Comp.DatePicker
|
import Comp.DatePicker
|
||||||
import Comp.Dropdown exposing (isDropdownChangeMsg)
|
import Comp.Dropdown exposing (isDropdownChangeMsg)
|
||||||
|
import Comp.Dropzone
|
||||||
import Comp.ItemMail
|
import Comp.ItemMail
|
||||||
import Comp.MarkdownInput
|
import Comp.MarkdownInput
|
||||||
import Comp.SentMails
|
import Comp.SentMails
|
||||||
@ -34,12 +35,16 @@ import Data.Flags exposing (Flags)
|
|||||||
import Data.Icons as Icons
|
import Data.Icons as Icons
|
||||||
import DatePicker exposing (DatePicker)
|
import DatePicker exposing (DatePicker)
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
|
import File exposing (File)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onCheck, onClick, onInput)
|
import Html.Events exposing (onCheck, onClick, onInput)
|
||||||
import Http
|
import Http
|
||||||
import Markdown
|
import Markdown
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
|
import Ports
|
||||||
|
import Set exposing (Set)
|
||||||
|
import Util.File exposing (makeFileId)
|
||||||
import Util.Http
|
import Util.Http
|
||||||
import Util.List
|
import Util.List
|
||||||
import Util.Maybe
|
import Util.Maybe
|
||||||
@ -77,6 +82,12 @@ type alias Model =
|
|||||||
, attachMetaOpen : Bool
|
, attachMetaOpen : Bool
|
||||||
, pdfNativeView : Bool
|
, pdfNativeView : Bool
|
||||||
, deleteAttachConfirm : Comp.YesNoDimmer.Model
|
, deleteAttachConfirm : Comp.YesNoDimmer.Model
|
||||||
|
, addFilesOpen : Bool
|
||||||
|
, addFilesModel : Comp.Dropzone.Model
|
||||||
|
, selectedFiles : List File
|
||||||
|
, completed : Set String
|
||||||
|
, errored : Set String
|
||||||
|
, loading : Set String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -165,6 +176,12 @@ emptyModel =
|
|||||||
, attachMetaOpen = False
|
, attachMetaOpen = False
|
||||||
, pdfNativeView = False
|
, pdfNativeView = False
|
||||||
, deleteAttachConfirm = Comp.YesNoDimmer.emptyModel
|
, deleteAttachConfirm = Comp.YesNoDimmer.emptyModel
|
||||||
|
, addFilesOpen = False
|
||||||
|
, addFilesModel = Comp.Dropzone.init Comp.Dropzone.defaultSettings
|
||||||
|
, selectedFiles = []
|
||||||
|
, completed = Set.empty
|
||||||
|
, errored = Set.empty
|
||||||
|
, loading = Set.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -221,6 +238,12 @@ type Msg
|
|||||||
| RequestDeleteAttachment String
|
| RequestDeleteAttachment String
|
||||||
| DeleteAttachConfirm String Comp.YesNoDimmer.Msg
|
| DeleteAttachConfirm String Comp.YesNoDimmer.Msg
|
||||||
| DeleteAttachResp (Result Http.Error BasicResult)
|
| DeleteAttachResp (Result Http.Error BasicResult)
|
||||||
|
| AddFilesToggle
|
||||||
|
| AddFilesMsg Comp.Dropzone.Msg
|
||||||
|
| AddFilesSubmitUpload
|
||||||
|
| AddFilesUploadResp String (Result Http.Error BasicResult)
|
||||||
|
| AddFilesProgress String Http.Progress
|
||||||
|
| AddFilesReset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -334,6 +357,42 @@ setDueDate flags model date =
|
|||||||
Api.setItemDueDate flags model.item.id (OptionalDate date) SaveResp
|
Api.setItemDueDate flags model.item.id (OptionalDate date) SaveResp
|
||||||
|
|
||||||
|
|
||||||
|
isLoading : Model -> File -> Bool
|
||||||
|
isLoading model file =
|
||||||
|
Set.member (makeFileId file) model.loading
|
||||||
|
|
||||||
|
|
||||||
|
isCompleted : Model -> File -> Bool
|
||||||
|
isCompleted model file =
|
||||||
|
Set.member (makeFileId file) model.completed
|
||||||
|
|
||||||
|
|
||||||
|
isError : Model -> File -> Bool
|
||||||
|
isError model file =
|
||||||
|
Set.member (makeFileId file) model.errored
|
||||||
|
|
||||||
|
|
||||||
|
isIdle : Model -> File -> Bool
|
||||||
|
isIdle model file =
|
||||||
|
not (isLoading model file || isCompleted model file || isError model file)
|
||||||
|
|
||||||
|
|
||||||
|
setCompleted : Model -> String -> Set String
|
||||||
|
setCompleted model fileid =
|
||||||
|
Set.insert fileid model.completed
|
||||||
|
|
||||||
|
|
||||||
|
setErrored : Model -> String -> Set String
|
||||||
|
setErrored model fileid =
|
||||||
|
Set.insert fileid model.errored
|
||||||
|
|
||||||
|
|
||||||
|
isSuccessAll : Model -> Bool
|
||||||
|
isSuccessAll model =
|
||||||
|
List.map makeFileId model.selectedFiles
|
||||||
|
|> List.all (\id -> Set.member id model.completed)
|
||||||
|
|
||||||
|
|
||||||
update : Nav.Key -> Flags -> Maybe String -> Msg -> Model -> ( Model, Cmd Msg )
|
update : Nav.Key -> Flags -> Maybe String -> Msg -> Model -> ( Model, Cmd Msg )
|
||||||
update key flags next msg model =
|
update key flags next msg model =
|
||||||
case msg of
|
case msg of
|
||||||
@ -430,6 +489,9 @@ update key flags next msg model =
|
|||||||
)
|
)
|
||||||
m5
|
m5
|
||||||
|
|
||||||
|
( m7, c7 ) =
|
||||||
|
update key flags next AddFilesReset m6
|
||||||
|
|
||||||
proposalCmd =
|
proposalCmd =
|
||||||
if item.state == "created" then
|
if item.state == "created" then
|
||||||
Api.getItemProposals flags item.id GetProposalResp
|
Api.getItemProposals flags item.id GetProposalResp
|
||||||
@ -437,7 +499,7 @@ update key flags next msg model =
|
|||||||
else
|
else
|
||||||
Cmd.none
|
Cmd.none
|
||||||
in
|
in
|
||||||
( { m6
|
( { m7
|
||||||
| item = item
|
| item = item
|
||||||
, nameModel = item.name
|
, nameModel = item.name
|
||||||
, notesModel = item.notes
|
, notesModel = item.notes
|
||||||
@ -453,6 +515,7 @@ update key flags next msg model =
|
|||||||
, c4
|
, c4
|
||||||
, c5
|
, c5
|
||||||
, c6
|
, c6
|
||||||
|
, c7
|
||||||
, getOptions flags
|
, getOptions flags
|
||||||
, proposalCmd
|
, proposalCmd
|
||||||
, Api.getSentMails flags item.id SentMailsResp
|
, Api.getSentMails flags item.id SentMailsResp
|
||||||
@ -980,6 +1043,107 @@ update key flags next msg model =
|
|||||||
(DeleteAttachConfirm id Comp.YesNoDimmer.activate)
|
(DeleteAttachConfirm id Comp.YesNoDimmer.activate)
|
||||||
model
|
model
|
||||||
|
|
||||||
|
AddFilesToggle ->
|
||||||
|
( { model | addFilesOpen = not model.addFilesOpen }
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
AddFilesMsg lm ->
|
||||||
|
let
|
||||||
|
( dm, dc, df ) =
|
||||||
|
Comp.Dropzone.update lm model.addFilesModel
|
||||||
|
|
||||||
|
nextFiles =
|
||||||
|
model.selectedFiles ++ df
|
||||||
|
in
|
||||||
|
( { model | addFilesModel = dm, selectedFiles = nextFiles }
|
||||||
|
, Cmd.map AddFilesMsg dc
|
||||||
|
)
|
||||||
|
|
||||||
|
AddFilesReset ->
|
||||||
|
( { model
|
||||||
|
| selectedFiles = []
|
||||||
|
, addFilesModel = Comp.Dropzone.init Comp.Dropzone.defaultSettings
|
||||||
|
, completed = Set.empty
|
||||||
|
, errored = Set.empty
|
||||||
|
, loading = Set.empty
|
||||||
|
}
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
AddFilesSubmitUpload ->
|
||||||
|
let
|
||||||
|
fileids =
|
||||||
|
List.map makeFileId model.selectedFiles
|
||||||
|
|
||||||
|
uploads =
|
||||||
|
Cmd.batch (Api.uploadAmend flags model.item.id model.selectedFiles AddFilesUploadResp)
|
||||||
|
|
||||||
|
tracker =
|
||||||
|
Sub.batch <| List.map (\id -> Http.track id (AddFilesProgress id)) fileids
|
||||||
|
|
||||||
|
( cm2, _, _ ) =
|
||||||
|
Comp.Dropzone.update (Comp.Dropzone.setActive False) model.addFilesModel
|
||||||
|
in
|
||||||
|
( { model | loading = Set.fromList fileids, addFilesModel = cm2 }, uploads )
|
||||||
|
|
||||||
|
AddFilesUploadResp fileid (Ok res) ->
|
||||||
|
let
|
||||||
|
compl =
|
||||||
|
if res.success then
|
||||||
|
setCompleted model fileid
|
||||||
|
|
||||||
|
else
|
||||||
|
model.completed
|
||||||
|
|
||||||
|
errs =
|
||||||
|
if not res.success then
|
||||||
|
setErrored model fileid
|
||||||
|
|
||||||
|
else
|
||||||
|
model.errored
|
||||||
|
|
||||||
|
load =
|
||||||
|
Set.remove fileid model.loading
|
||||||
|
|
||||||
|
newModel =
|
||||||
|
{ model | completed = compl, errored = errs, loading = load }
|
||||||
|
in
|
||||||
|
( newModel
|
||||||
|
, Ports.setProgress ( fileid, 100 )
|
||||||
|
)
|
||||||
|
|
||||||
|
AddFilesUploadResp fileid (Err _) ->
|
||||||
|
let
|
||||||
|
errs =
|
||||||
|
setErrored model fileid
|
||||||
|
|
||||||
|
load =
|
||||||
|
Set.remove fileid model.loading
|
||||||
|
in
|
||||||
|
( { model | errored = errs, loading = load }, Cmd.none )
|
||||||
|
|
||||||
|
AddFilesProgress fileid progress ->
|
||||||
|
let
|
||||||
|
percent =
|
||||||
|
case progress of
|
||||||
|
Http.Sending p ->
|
||||||
|
Http.fractionSent p
|
||||||
|
|> (*) 100
|
||||||
|
|> round
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
0
|
||||||
|
|
||||||
|
updateBars =
|
||||||
|
if percent == 0 then
|
||||||
|
Cmd.none
|
||||||
|
|
||||||
|
else
|
||||||
|
Ports.setProgress ( fileid, percent )
|
||||||
|
in
|
||||||
|
( model, updateBars )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- view
|
-- view
|
||||||
@ -1001,7 +1165,7 @@ view inav model =
|
|||||||
, div
|
, div
|
||||||
[ classList
|
[ classList
|
||||||
[ ( "ui ablue-comp menu", True )
|
[ ( "ui ablue-comp menu", True )
|
||||||
, ( "top attached", model.mailOpen )
|
, ( "top attached", model.mailOpen || model.addFilesOpen )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ a [ class "item", Page.href HomePage ]
|
[ a [ class "item", Page.href HomePage ]
|
||||||
@ -1066,8 +1230,24 @@ view inav model =
|
|||||||
]
|
]
|
||||||
[ Icons.editNotesIcon
|
[ Icons.editNotesIcon
|
||||||
]
|
]
|
||||||
|
, a
|
||||||
|
[ classList
|
||||||
|
[ ( "toggle item", True )
|
||||||
|
, ( "active", model.addFilesOpen )
|
||||||
|
]
|
||||||
|
, if model.addFilesOpen then
|
||||||
|
title "Close"
|
||||||
|
|
||||||
|
else
|
||||||
|
title "Add Files"
|
||||||
|
, onClick AddFilesToggle
|
||||||
|
, href "#"
|
||||||
|
]
|
||||||
|
[ Icons.addFilesIcon
|
||||||
|
]
|
||||||
]
|
]
|
||||||
, renderMailForm model
|
, renderMailForm model
|
||||||
|
, renderAddFilesForm model
|
||||||
, div [ class "ui grid" ]
|
, div [ class "ui grid" ]
|
||||||
[ Html.map DeleteItemConfirm (Comp.YesNoDimmer.view model.deleteItemConfirm)
|
[ Html.map DeleteItemConfirm (Comp.YesNoDimmer.view model.deleteItemConfirm)
|
||||||
, div
|
, div
|
||||||
@ -1756,3 +1936,94 @@ renderMailForm model =
|
|||||||
|> text
|
|> text
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderAddFilesForm : Model -> Html Msg
|
||||||
|
renderAddFilesForm model =
|
||||||
|
div
|
||||||
|
[ classList
|
||||||
|
[ ( "ui bottom attached segment", True )
|
||||||
|
, ( "invisible hidden", not model.addFilesOpen )
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[ h4 [ class "ui header" ]
|
||||||
|
[ text "Add more files to this item"
|
||||||
|
]
|
||||||
|
, Html.map AddFilesMsg (Comp.Dropzone.view model.addFilesModel)
|
||||||
|
, button
|
||||||
|
[ class "ui primary button"
|
||||||
|
, href "#"
|
||||||
|
, onClick AddFilesSubmitUpload
|
||||||
|
]
|
||||||
|
[ text "Submit"
|
||||||
|
]
|
||||||
|
, button
|
||||||
|
[ class "ui secondary button"
|
||||||
|
, href "#"
|
||||||
|
, onClick AddFilesReset
|
||||||
|
]
|
||||||
|
[ text "Reset"
|
||||||
|
]
|
||||||
|
, div
|
||||||
|
[ classList
|
||||||
|
[ ( "ui success message", True )
|
||||||
|
, ( "invisible hidden", model.selectedFiles == [] || not (isSuccessAll model) )
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[ text "All files have been uploaded. They are being processed, some data "
|
||||||
|
, text "may not be available immediately. "
|
||||||
|
, a
|
||||||
|
[ class "link"
|
||||||
|
, href "#"
|
||||||
|
, onClick ReloadItem
|
||||||
|
]
|
||||||
|
[ text "Refresh now"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "ui items" ]
|
||||||
|
(List.map (renderFileItem model) model.selectedFiles)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderFileItem : Model -> File -> Html Msg
|
||||||
|
renderFileItem model file =
|
||||||
|
let
|
||||||
|
name =
|
||||||
|
File.name file
|
||||||
|
|
||||||
|
size =
|
||||||
|
File.size file
|
||||||
|
|> toFloat
|
||||||
|
|> Util.Size.bytesReadable Util.Size.B
|
||||||
|
in
|
||||||
|
div [ class "item" ]
|
||||||
|
[ i
|
||||||
|
[ classList
|
||||||
|
[ ( "large", True )
|
||||||
|
, ( "file outline icon", isIdle model file )
|
||||||
|
, ( "loading spinner icon", isLoading model file )
|
||||||
|
, ( "green check icon", isCompleted model file )
|
||||||
|
, ( "red bolt icon", isError model file )
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, div [ class "middle aligned content" ]
|
||||||
|
[ div [ class "header" ]
|
||||||
|
[ text name
|
||||||
|
]
|
||||||
|
, div [ class "right floated meta" ]
|
||||||
|
[ text size
|
||||||
|
]
|
||||||
|
, div [ class "description" ]
|
||||||
|
[ div
|
||||||
|
[ classList
|
||||||
|
[ ( "ui small indicating progress", True )
|
||||||
|
]
|
||||||
|
, id (makeFileId file)
|
||||||
|
]
|
||||||
|
[ div [ class "bar" ]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
module Data.Icons exposing
|
module Data.Icons exposing
|
||||||
( concerned
|
( addFiles
|
||||||
|
, addFilesIcon
|
||||||
|
, concerned
|
||||||
, concernedIcon
|
, concernedIcon
|
||||||
, correspondent
|
, correspondent
|
||||||
, correspondentIcon
|
, correspondentIcon
|
||||||
@ -51,3 +53,13 @@ editNotes =
|
|||||||
editNotesIcon : Html msg
|
editNotesIcon : Html msg
|
||||||
editNotesIcon =
|
editNotesIcon =
|
||||||
i [ class editNotes ] []
|
i [ class editNotes ] []
|
||||||
|
|
||||||
|
|
||||||
|
addFiles : String
|
||||||
|
addFiles =
|
||||||
|
"file plus icon"
|
||||||
|
|
||||||
|
|
||||||
|
addFilesIcon : Html msg
|
||||||
|
addFilesIcon =
|
||||||
|
i [ class addFiles ] []
|
||||||
|
@ -41,7 +41,12 @@ update sourceId flags msg model =
|
|||||||
|
|
||||||
uploads =
|
uploads =
|
||||||
if model.singleItem then
|
if model.singleItem then
|
||||||
Api.uploadSingle flags sourceId meta uploadAllTracker model.files (SingleUploadResp uploadAllTracker)
|
Api.uploadSingle flags
|
||||||
|
sourceId
|
||||||
|
meta
|
||||||
|
uploadAllTracker
|
||||||
|
model.files
|
||||||
|
(SingleUploadResp uploadAllTracker)
|
||||||
|
|
||||||
else
|
else
|
||||||
Cmd.batch (Api.upload flags sourceId meta model.files SingleUploadResp)
|
Cmd.batch (Api.upload flags sourceId meta model.files SingleUploadResp)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user