Create upload component

This commit is contained in:
eikek 2022-01-26 21:22:35 +01:00
parent 370679daed
commit 67f1575707
7 changed files with 668 additions and 607 deletions

View File

@ -669,7 +669,7 @@ initPage model_ page =
UploadPage _ ->
Util.Update.andThen2
[ updateQueue Page.Queue.Data.StopRefresh
, updateUpload Page.Upload.Data.Clear
, updateUpload Page.Upload.Data.reset
]
model

View File

@ -0,0 +1,555 @@
module Comp.UploadForm exposing (Model, Msg, init, reset, update, view)
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.ItemUploadMeta
import Comp.Dropzone
import Comp.FixedDropdown
import Comp.Progress
import Data.DropdownStyle as DS
import Data.Flags exposing (Flags)
import Data.Language exposing (Language)
import Data.UiSettings exposing (UiSettings)
import Dict exposing (Dict)
import File exposing (File)
import Html exposing (Html, a, div, h2, h3, i, input, label, p, span, text)
import Html.Attributes exposing (action, checked, class, classList, href, id, type_)
import Html.Events exposing (onCheck, onClick)
import Http
import Messages.Comp.UploadForm exposing (Texts)
import Page exposing (Page(..))
import Set exposing (Set)
import Styles
import Util.File exposing (makeFileId)
import Util.Maybe
import Util.Size
type alias Model =
{ incoming : Bool
, singleItem : Bool
, files : List File
, completed : Set String
, errored : Set String
, loading : Dict String Int
, dropzone : Comp.Dropzone.Model
, skipDuplicates : Bool
, languageModel : Comp.FixedDropdown.Model Language
, language : Maybe Language
}
type Msg
= SubmitUpload
| SingleUploadResp String (Result Http.Error BasicResult)
| GotProgress String Http.Progress
| ToggleIncoming
| ToggleSingleItem
| Clear
| DropzoneMsg Comp.Dropzone.Msg
| ToggleSkipDuplicates
| LanguageMsg (Comp.FixedDropdown.Msg Language)
init : Model
init =
{ incoming = True
, singleItem = False
, files = []
, completed = Set.empty
, errored = Set.empty
, loading = Dict.empty
, dropzone = Comp.Dropzone.init []
, skipDuplicates = True
, languageModel =
Comp.FixedDropdown.init Data.Language.all
, language = Nothing
}
reset : Msg
reset =
Clear
isLoading : Model -> File -> Bool
isLoading model file =
Dict.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)
uploadAllTracker : String
uploadAllTracker =
"upload-all"
isDone : Model -> Bool
isDone model =
List.map makeFileId model.files
|> List.all (\id -> Set.member id model.completed || Set.member id model.errored)
isSuccessAll : Model -> Bool
isSuccessAll model =
List.map makeFileId model.files
|> List.all (\id -> Set.member id model.completed)
hasErrors : Model -> Bool
hasErrors model =
not (Set.isEmpty model.errored)
--- Update
update : Maybe String -> Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update sourceId flags msg model =
case msg of
ToggleIncoming ->
( { model | incoming = not model.incoming }, Cmd.none, Sub.none )
ToggleSingleItem ->
( { model | singleItem = not model.singleItem }, Cmd.none, Sub.none )
ToggleSkipDuplicates ->
( { model | skipDuplicates = not model.skipDuplicates }, Cmd.none, Sub.none )
SubmitUpload ->
let
emptyMeta =
Api.Model.ItemUploadMeta.empty
meta =
{ emptyMeta
| multiple = not model.singleItem
, skipDuplicates = Just model.skipDuplicates
, direction =
if model.incoming then
Just "incoming"
else
Just "outgoing"
, language = Maybe.map Data.Language.toIso3 model.language
}
fileids =
List.map makeFileId model.files
uploads =
if model.singleItem then
Api.uploadSingle flags
sourceId
meta
uploadAllTracker
model.files
(SingleUploadResp uploadAllTracker)
else
Cmd.batch (Api.upload flags sourceId meta model.files SingleUploadResp)
tracker =
if model.singleItem then
Http.track uploadAllTracker (GotProgress uploadAllTracker)
else
Sub.batch <| List.map (\id -> Http.track id (GotProgress id)) fileids
( cm2, _, _ ) =
Comp.Dropzone.update (Comp.Dropzone.setActive False) model.dropzone
nowLoading =
List.map (\fid -> ( fid, 0 )) fileids
|> Dict.fromList
in
( { model | loading = nowLoading, dropzone = cm2 }, uploads, tracker )
SingleUploadResp 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 =
if fileid == uploadAllTracker then
Dict.empty
else
Dict.remove fileid model.loading
in
( { model | completed = compl, errored = errs, loading = load }
, Cmd.none
, Sub.none
)
SingleUploadResp fileid (Err _) ->
let
errs =
setErrored model fileid
load =
if fileid == uploadAllTracker then
Dict.empty
else
Dict.remove fileid model.loading
in
( { model | errored = errs, loading = load }, Cmd.none, Sub.none )
GotProgress fileid progress ->
let
percent =
case progress of
Http.Sending p ->
Http.fractionSent p
|> (*) 100
|> round
_ ->
0
newLoading =
if model.singleItem then
Dict.insert uploadAllTracker percent model.loading
else
Dict.insert fileid percent model.loading
in
( { model | loading = newLoading }
, Cmd.none
, Sub.none
)
Clear ->
( init, Cmd.none, Sub.none )
DropzoneMsg m ->
let
( m2, c2, files ) =
Comp.Dropzone.update m model.dropzone
nextFiles =
List.append model.files files
in
( { model | files = nextFiles, dropzone = m2 }, Cmd.map DropzoneMsg c2, Sub.none )
LanguageMsg lm ->
let
( dm, sel ) =
Comp.FixedDropdown.update lm model.languageModel
in
( { model
| languageModel = dm
, language = Util.Maybe.or [ sel, model.language ]
}
, Cmd.none
, Sub.none
)
setCompleted : Model -> String -> Set String
setCompleted model fileid =
if fileid == uploadAllTracker then
List.map makeFileId model.files |> Set.fromList
else
Set.insert fileid model.completed
setErrored : Model -> String -> Set String
setErrored model fileid =
if fileid == uploadAllTracker then
List.map makeFileId model.files |> Set.fromList
else
Set.insert fileid model.errored
--- View
view : Texts -> Maybe String -> Flags -> UiSettings -> Model -> Html Msg
view texts mid _ _ model =
div
[ id "content"
, class Styles.content
]
[ div [ class "container mx-auto" ]
[ div [ class "px-0 flex flex-col" ]
[ div [ class "py-4" ]
[ if mid == Nothing then
renderForm texts model
else
span [ class "hidden" ] []
]
, div [ class "py-0" ]
[ Html.map DropzoneMsg
(Comp.Dropzone.view2 texts.dropzone model.dropzone)
]
, div [ class "py-4" ]
[ a
[ class Styles.primaryButton
, href "#"
, onClick SubmitUpload
]
[ text texts.basics.submit
]
, a
[ class Styles.secondaryButton
, class "ml-2"
, href "#"
, onClick Clear
]
[ text texts.reset
]
]
]
, renderErrorMsg texts model
, renderSuccessMsg texts (Util.Maybe.nonEmpty mid) model
, renderUploads texts model
]
]
renderForm : Texts -> Model -> Html Msg
renderForm texts model =
let
languageCfg =
{ display = texts.languageLabel
, icon = \_ -> Nothing
, style = DS.mainStyleWith "w-40"
, selectPlaceholder = texts.basics.selectPlaceholder
}
in
div [ class "row" ]
[ Html.form [ action "#" ]
[ div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked model.incoming
, onCheck (\_ -> ToggleIncoming)
, class Styles.radioInput
]
[]
, span [ class "ml-2" ] [ text texts.basics.incoming ]
]
, label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked (not model.incoming)
, onCheck (\_ -> ToggleIncoming)
, class Styles.radioInput
]
[]
, span [ class "ml-2" ] [ text texts.basics.outgoing ]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "checkbox"
, checked model.singleItem
, onCheck (\_ -> ToggleSingleItem)
, class Styles.checkboxInput
]
[]
, span [ class "ml-2" ]
[ text texts.allFilesOneItem
]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "checkbox"
, checked model.skipDuplicates
, onCheck (\_ -> ToggleSkipDuplicates)
, class Styles.checkboxInput
]
[]
, span [ class "ml-2" ]
[ text texts.skipExistingFiles
]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center mb-2" ]
[ span [ class "mr-2" ] [ text (texts.language ++ ":") ]
, Html.map LanguageMsg
(Comp.FixedDropdown.viewStyled2
languageCfg
False
model.language
model.languageModel
)
]
, div [ class "text-gray-400 text-xs" ]
[ text texts.languageInfo
]
]
]
]
renderErrorMsg : Texts -> Model -> Html Msg
renderErrorMsg texts model =
div
[ class "row"
, classList [ ( "hidden", not (isDone model && hasErrors model) ) ]
]
[ div [ class "mt-4" ]
[ div [ class Styles.errorMessage ]
[ text texts.uploadErrorMessage
]
]
]
renderSuccessMsg : Texts -> Bool -> Model -> Html Msg
renderSuccessMsg texts public model =
div
[ class "row"
, classList [ ( "hidden", List.isEmpty model.files || not (isSuccessAll model) ) ]
]
[ div [ class "mt-4" ]
[ div [ class Styles.successMessage ]
[ h3 [ class Styles.header2, class "text-green-800 dark:text-lime-800" ]
[ i [ class "fa fa-smile font-thin" ] []
, span [ class "ml-2" ]
[ text texts.successBox.allFilesUploaded
]
]
, p
[ classList [ ( "hidden", public ) ]
]
[ text texts.successBox.line1
, a
[ class Styles.successMessageLink
, Page.href (SearchPage Nothing)
]
[ text texts.successBox.itemsPage
]
, text texts.successBox.line2
, a
[ class Styles.successMessageLink
, Page.href QueuePage
]
[ text texts.successBox.processingPage
]
, text texts.successBox.line3
]
, p []
[ text texts.successBox.resetLine1
, a
[ class Styles.successMessageLink
, href "#"
, onClick Clear
]
[ text texts.successBox.reset
]
, text texts.successBox.resetLine2
]
]
]
]
renderUploads : Texts -> Model -> Html Msg
renderUploads texts model =
div
[ class "mt-4"
, classList [ ( "hidden", List.isEmpty model.files || isSuccessAll model ) ]
]
[ h2 [ class Styles.header2 ]
[ text texts.selectedFiles
, text (" (" ++ (List.length model.files |> String.fromInt) ++ ")")
]
, div [] <|
if model.singleItem then
List.map (renderFileItem model (Just uploadAllTracker)) model.files
else
List.map (renderFileItem model Nothing) model.files
]
getProgress : Model -> File -> Int
getProgress model file =
let
key =
if model.singleItem then
uploadAllTracker
else
makeFileId file
in
Dict.get key model.loading
|> Maybe.withDefault 0
renderFileItem : Model -> Maybe String -> 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 "flex flex-col w-full mb-4" ]
[ div [ class "flex flex-row items-center" ]
[ div [ class "inline-flex items-center" ]
[ i
[ classList
[ ( "mr-2 text-lg", True )
, ( "fa fa-file font-thin", isIdle model file )
, ( "fa fa-spinner animate-spin ", isLoading model file )
, ( "fa fa-check ", isCompleted model file )
, ( "fa fa-bolt", isError model file )
]
]
[]
, div [ class "middle aligned content" ]
[ div [ class "header" ]
[ text name
]
]
]
, div [ class "flex-grow inline-flex justify-end" ]
[ text size
]
]
, div [ class "h-4" ]
[ Comp.Progress.progress2 (getProgress model file)
]
]

View File

@ -0,0 +1,91 @@
module Messages.Comp.UploadForm exposing (Texts, de, gb)
import Data.Language exposing (Language)
import Messages.Basics
import Messages.Comp.Dropzone
import Messages.Data.Language
type alias Texts =
{ basics : Messages.Basics.Texts
, dropzone : Messages.Comp.Dropzone.Texts
, reset : String
, allFilesOneItem : String
, skipExistingFiles : String
, language : String
, languageInfo : String
, uploadErrorMessage : String
, successBox :
{ allFilesUploaded : String
, line1 : String
, itemsPage : String
, line2 : String
, processingPage : String
, line3 : String
, resetLine1 : String
, reset : String
, resetLine2 : String
}
, selectedFiles : String
, languageLabel : Language -> String
}
gb : Texts
gb =
{ basics = Messages.Basics.gb
, dropzone = Messages.Comp.Dropzone.gb
, reset = "Reset"
, allFilesOneItem = "All files are one single item"
, skipExistingFiles = "Skip files already present in docspell"
, language = "Language"
, languageInfo =
"Used for text extraction and analysis. The collective's "
++ "default language is used if not specified here."
, uploadErrorMessage = "There were errors uploading some files."
, successBox =
{ allFilesUploaded = "All files uploaded"
, line1 =
"Your files have been successfully uploaded. "
++ "They are now being processed. Check the "
, itemsPage = "Items Page"
, line2 = " later where the files will arrive eventually. Or go to the "
, processingPage = "Processing Page"
, line3 = " to view the current processing state."
, resetLine1 = " Click "
, reset = "Reset"
, resetLine2 = " to upload more files."
}
, selectedFiles = "Selected Files"
, languageLabel = Messages.Data.Language.gb
}
de : Texts
de =
{ basics = Messages.Basics.de
, dropzone = Messages.Comp.Dropzone.de
, reset = "Zurücksetzen"
, allFilesOneItem = "Alle Dateien sind ein Dokument"
, skipExistingFiles = "Lasse Dateien aus, die schon in Docspell sind"
, language = "Sprache"
, languageInfo =
"Wird für Texterkennung und -analyse verwendet. Die Standardsprache des Kollektivs "
++ "wird verwendet, falls hier nicht angegeben."
, uploadErrorMessage = "Es gab Fehler beim Hochladen der Dateien."
, successBox =
{ allFilesUploaded = "Alle Dateien hochgeladen"
, line1 =
"Deine Dateien wurden erfolgreich hochgeladen und sie werden nun verarbeitet. "
++ "Gehe nachher zur "
, itemsPage = "Hauptseite"
, line2 = " wo die Dateien als Dokumente erscheinen werden oder gehe zur "
, processingPage = "Verarbeitungsseite,"
, line3 = " welche einen Einblick in den aktuellen Status gibt."
, resetLine1 = " Klicke "
, reset = "Zurücksetzen"
, resetLine2 = " um weitere Dateien hochzuladen."
}
, selectedFiles = "Ausgewählte Dateien"
, languageLabel = Messages.Data.Language.de
}

View File

@ -11,92 +11,21 @@ module Messages.Page.Upload exposing
, gb
)
import Data.Language exposing (Language)
import Messages.Basics
import Messages.Comp.Dropzone
import Messages.Data.Language
import Messages.Comp.UploadForm
type alias Texts =
{ basics : Messages.Basics.Texts
, dropzone : Messages.Comp.Dropzone.Texts
, reset : String
, allFilesOneItem : String
, skipExistingFiles : String
, language : String
, languageInfo : String
, uploadErrorMessage : String
, successBox :
{ allFilesUploaded : String
, line1 : String
, itemsPage : String
, line2 : String
, processingPage : String
, line3 : String
, resetLine1 : String
, reset : String
, resetLine2 : String
}
, selectedFiles : String
, languageLabel : Language -> String
{ uploadForm : Messages.Comp.UploadForm.Texts
}
gb : Texts
gb =
{ basics = Messages.Basics.gb
, dropzone = Messages.Comp.Dropzone.gb
, reset = "Reset"
, allFilesOneItem = "All files are one single item"
, skipExistingFiles = "Skip files already present in docspell"
, language = "Language"
, languageInfo =
"Used for text extraction and analysis. The collective's "
++ "default language is used if not specified here."
, uploadErrorMessage = "There were errors uploading some files."
, successBox =
{ allFilesUploaded = "All files uploaded"
, line1 =
"Your files have been successfully uploaded. "
++ "They are now being processed. Check the "
, itemsPage = "Items Page"
, line2 = " later where the files will arrive eventually. Or go to the "
, processingPage = "Processing Page"
, line3 = " to view the current processing state."
, resetLine1 = " Click "
, reset = "Reset"
, resetLine2 = " to upload more files."
}
, selectedFiles = "Selected Files"
, languageLabel = Messages.Data.Language.gb
{ uploadForm = Messages.Comp.UploadForm.gb
}
de : Texts
de =
{ basics = Messages.Basics.de
, dropzone = Messages.Comp.Dropzone.de
, reset = "Zurücksetzen"
, allFilesOneItem = "Alle Dateien sind ein Dokument"
, skipExistingFiles = "Lasse Dateien aus, die schon in Docspell sind"
, language = "Sprache"
, languageInfo =
"Wird für Texterkennung und -analyse verwendet. Die Standardsprache des Kollektivs "
++ "wird verwendet, falls hier nicht angegeben."
, uploadErrorMessage = "Es gab Fehler beim Hochladen der Dateien."
, successBox =
{ allFilesUploaded = "Alle Dateien hochgeladen"
, line1 =
"Deine Dateien wurden erfolgreich hochgeladen und sie werden nun verarbeitet. "
++ "Gehe nachher zur "
, itemsPage = "Hauptseite"
, line2 = " wo die Dateien als Dokumente erscheinen werden oder gehe zur "
, processingPage = "Verarbeitungsseite,"
, line3 = " welche einen Einblick in den aktuellen Status gibt."
, resetLine1 = " Klicke "
, reset = "Zurücksetzen"
, resetLine2 = " um weitere Dateien hochzuladen."
}
, selectedFiles = "Ausgewählte Dateien"
, languageLabel = Messages.Data.Language.de
{ uploadForm = Messages.Comp.UploadForm.de
}

View File

@ -9,106 +9,27 @@ module Page.Upload.Data exposing
( Model
, Msg(..)
, emptyModel
, hasErrors
, isCompleted
, isDone
, isError
, isIdle
, isLoading
, isSuccessAll
, uploadAllTracker
, reset
)
import Api.Model.BasicResult exposing (BasicResult)
import Comp.Dropzone
import Comp.FixedDropdown
import Data.Language exposing (Language)
import Dict exposing (Dict)
import File exposing (File)
import Http
import Set exposing (Set)
import Util.File exposing (makeFileId)
import Comp.UploadForm
type alias Model =
{ incoming : Bool
, singleItem : Bool
, files : List File
, completed : Set String
, errored : Set String
, loading : Dict String Int
, dropzone : Comp.Dropzone.Model
, skipDuplicates : Bool
, languageModel : Comp.FixedDropdown.Model Language
, language : Maybe Language
{ uploadForm : Comp.UploadForm.Model
}
emptyModel : Model
emptyModel =
{ incoming = True
, singleItem = False
, files = []
, completed = Set.empty
, errored = Set.empty
, loading = Dict.empty
, dropzone = Comp.Dropzone.init []
, skipDuplicates = True
, languageModel =
Comp.FixedDropdown.init Data.Language.all
, language = Nothing
{ uploadForm = Comp.UploadForm.init
}
type Msg
= SubmitUpload
| SingleUploadResp String (Result Http.Error BasicResult)
| GotProgress String Http.Progress
| ToggleIncoming
| ToggleSingleItem
| Clear
| DropzoneMsg Comp.Dropzone.Msg
| ToggleSkipDuplicates
| LanguageMsg (Comp.FixedDropdown.Msg Language)
= UploadMsg Comp.UploadForm.Msg
isLoading : Model -> File -> Bool
isLoading model file =
Dict.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)
uploadAllTracker : String
uploadAllTracker =
"upload-all"
isDone : Model -> Bool
isDone model =
List.map makeFileId model.files
|> List.all (\id -> Set.member id model.completed || Set.member id model.errored)
isSuccessAll : Model -> Bool
isSuccessAll model =
List.map makeFileId model.files
|> List.all (\id -> Set.member id model.completed)
hasErrors : Model -> Bool
hasErrors model =
not (Set.isEmpty model.errored)
reset : Msg
reset =
UploadMsg Comp.UploadForm.reset

View File

@ -7,187 +7,17 @@
module Page.Upload.Update exposing (update)
import Api
import Api.Model.ItemUploadMeta
import Comp.Dropzone
import Comp.FixedDropdown
import Comp.UploadForm
import Data.Flags exposing (Flags)
import Data.Language
import Dict
import Http
import Page.Upload.Data exposing (..)
import Set exposing (Set)
import Util.File exposing (makeFileId)
import Util.Maybe
update : Maybe String -> Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update sourceId flags msg model =
case msg of
ToggleIncoming ->
( { model | incoming = not model.incoming }, Cmd.none, Sub.none )
ToggleSingleItem ->
( { model | singleItem = not model.singleItem }, Cmd.none, Sub.none )
ToggleSkipDuplicates ->
( { model | skipDuplicates = not model.skipDuplicates }, Cmd.none, Sub.none )
SubmitUpload ->
UploadMsg lm ->
let
emptyMeta =
Api.Model.ItemUploadMeta.empty
meta =
{ emptyMeta
| multiple = not model.singleItem
, skipDuplicates = Just model.skipDuplicates
, direction =
if model.incoming then
Just "incoming"
else
Just "outgoing"
, language = Maybe.map Data.Language.toIso3 model.language
}
fileids =
List.map makeFileId model.files
uploads =
if model.singleItem then
Api.uploadSingle flags
sourceId
meta
uploadAllTracker
model.files
(SingleUploadResp uploadAllTracker)
else
Cmd.batch (Api.upload flags sourceId meta model.files SingleUploadResp)
tracker =
if model.singleItem then
Http.track uploadAllTracker (GotProgress uploadAllTracker)
else
Sub.batch <| List.map (\id -> Http.track id (GotProgress id)) fileids
( cm2, _, _ ) =
Comp.Dropzone.update (Comp.Dropzone.setActive False) model.dropzone
nowLoading =
List.map (\fid -> ( fid, 0 )) fileids
|> Dict.fromList
( um, uc, us ) =
Comp.UploadForm.update sourceId flags lm model.uploadForm
in
( { model | loading = nowLoading, dropzone = cm2 }, uploads, tracker )
SingleUploadResp 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 =
if fileid == uploadAllTracker then
Dict.empty
else
Dict.remove fileid model.loading
in
( { model | completed = compl, errored = errs, loading = load }
, Cmd.none
, Sub.none
)
SingleUploadResp fileid (Err _) ->
let
errs =
setErrored model fileid
load =
if fileid == uploadAllTracker then
Dict.empty
else
Dict.remove fileid model.loading
in
( { model | errored = errs, loading = load }, Cmd.none, Sub.none )
GotProgress fileid progress ->
let
percent =
case progress of
Http.Sending p ->
Http.fractionSent p
|> (*) 100
|> round
_ ->
0
newLoading =
if model.singleItem then
Dict.insert uploadAllTracker percent model.loading
else
Dict.insert fileid percent model.loading
in
( { model | loading = newLoading }
, Cmd.none
, Sub.none
)
Clear ->
( emptyModel, Cmd.none, Sub.none )
DropzoneMsg m ->
let
( m2, c2, files ) =
Comp.Dropzone.update m model.dropzone
nextFiles =
List.append model.files files
in
( { model | files = nextFiles, dropzone = m2 }, Cmd.map DropzoneMsg c2, Sub.none )
LanguageMsg lm ->
let
( dm, sel ) =
Comp.FixedDropdown.update lm model.languageModel
in
( { model
| languageModel = dm
, language = Util.Maybe.or [ sel, model.language ]
}
, Cmd.none
, Sub.none
)
setCompleted : Model -> String -> Set String
setCompleted model fileid =
if fileid == uploadAllTracker then
List.map makeFileId model.files |> Set.fromList
else
Set.insert fileid model.completed
setErrored : Model -> String -> Set String
setErrored model fileid =
if fileid == uploadAllTracker then
List.map makeFileId model.files |> Set.fromList
else
Set.insert fileid model.errored
( { model | uploadForm = um }, Cmd.map UploadMsg uc, Sub.map UploadMsg us )

View File

@ -7,24 +7,14 @@
module Page.Upload.View2 exposing (viewContent, viewSidebar)
import Comp.Dropzone
import Comp.FixedDropdown
import Comp.Progress
import Data.DropdownStyle as DS
import Comp.UploadForm
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Dict
import File exposing (File)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onCheck, onClick)
import Messages.Page.Upload exposing (Texts)
import Page exposing (Page(..))
import Page.Upload.Data exposing (..)
import Styles as S
import Util.File exposing (makeFileId)
import Util.Maybe
import Util.Size
viewSidebar : Maybe String -> Bool -> Flags -> UiSettings -> Model -> Html Msg
@ -37,261 +27,6 @@ viewSidebar _ _ _ _ _ =
viewContent : Texts -> Maybe String -> Flags -> UiSettings -> Model -> Html Msg
viewContent texts mid _ _ model =
div
[ id "content"
, class S.content
]
[ div [ class "container mx-auto" ]
[ div [ class "px-0 flex flex-col" ]
[ div [ class "py-4" ]
[ if mid == Nothing then
renderForm texts model
else
span [ class "hidden" ] []
]
, div [ class "py-0" ]
[ Html.map DropzoneMsg
(Comp.Dropzone.view2 texts.dropzone model.dropzone)
]
, div [ class "py-4" ]
[ a
[ class S.primaryButton
, href "#"
, onClick SubmitUpload
]
[ text texts.basics.submit
]
, a
[ class S.secondaryButton
, class "ml-2"
, href "#"
, onClick Clear
]
[ text texts.reset
]
]
]
, renderErrorMsg texts model
, renderSuccessMsg texts (Util.Maybe.nonEmpty mid) model
, renderUploads texts model
]
]
renderForm : Texts -> Model -> Html Msg
renderForm texts model =
let
languageCfg =
{ display = texts.languageLabel
, icon = \_ -> Nothing
, style = DS.mainStyleWith "w-40"
, selectPlaceholder = texts.basics.selectPlaceholder
}
in
div [ class "row" ]
[ Html.form [ action "#" ]
[ div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked model.incoming
, onCheck (\_ -> ToggleIncoming)
, class S.radioInput
]
[]
, span [ class "ml-2" ] [ text texts.basics.incoming ]
]
, label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked (not model.incoming)
, onCheck (\_ -> ToggleIncoming)
, class S.radioInput
]
[]
, span [ class "ml-2" ] [ text texts.basics.outgoing ]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "checkbox"
, checked model.singleItem
, onCheck (\_ -> ToggleSingleItem)
, class S.checkboxInput
]
[]
, span [ class "ml-2" ]
[ text texts.allFilesOneItem
]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "checkbox"
, checked model.skipDuplicates
, onCheck (\_ -> ToggleSkipDuplicates)
, class S.checkboxInput
]
[]
, span [ class "ml-2" ]
[ text texts.skipExistingFiles
]
]
]
, div [ class "flex flex-col mb-3" ]
[ label [ class "inline-flex items-center mb-2" ]
[ span [ class "mr-2" ] [ text (texts.language ++ ":") ]
, Html.map LanguageMsg
(Comp.FixedDropdown.viewStyled2
languageCfg
False
model.language
model.languageModel
)
]
, div [ class "text-gray-400 text-xs" ]
[ text texts.languageInfo
]
]
]
]
renderErrorMsg : Texts -> Model -> Html Msg
renderErrorMsg texts model =
div
[ class "row"
, classList [ ( "hidden", not (isDone model && hasErrors model) ) ]
]
[ div [ class "mt-4" ]
[ div [ class S.errorMessage ]
[ text texts.uploadErrorMessage
]
]
]
renderSuccessMsg : Texts -> Bool -> Model -> Html Msg
renderSuccessMsg texts public model =
div
[ class "row"
, classList [ ( "hidden", List.isEmpty model.files || not (isSuccessAll model) ) ]
]
[ div [ class "mt-4" ]
[ div [ class S.successMessage ]
[ h3 [ class S.header2, class "text-green-800 dark:text-lime-800" ]
[ i [ class "fa fa-smile font-thin" ] []
, span [ class "ml-2" ]
[ text texts.successBox.allFilesUploaded
]
]
, p
[ classList [ ( "hidden", public ) ]
]
[ text texts.successBox.line1
, a
[ class S.successMessageLink
, Page.href (SearchPage Nothing)
]
[ text texts.successBox.itemsPage
]
, text texts.successBox.line2
, a
[ class S.successMessageLink
, Page.href QueuePage
]
[ text texts.successBox.processingPage
]
, text texts.successBox.line3
]
, p []
[ text texts.successBox.resetLine1
, a
[ class S.successMessageLink
, href "#"
, onClick Clear
]
[ text texts.successBox.reset
]
, text texts.successBox.resetLine2
]
]
]
]
renderUploads : Texts -> Model -> Html Msg
renderUploads texts model =
div
[ class "mt-4"
, classList [ ( "hidden", List.isEmpty model.files || isSuccessAll model ) ]
]
[ h2 [ class S.header2 ]
[ text texts.selectedFiles
, text (" (" ++ (List.length model.files |> String.fromInt) ++ ")")
]
, div [] <|
if model.singleItem then
List.map (renderFileItem model (Just uploadAllTracker)) model.files
else
List.map (renderFileItem model Nothing) model.files
]
getProgress : Model -> File -> Int
getProgress model file =
let
key =
if model.singleItem then
uploadAllTracker
else
makeFileId file
in
Dict.get key model.loading
|> Maybe.withDefault 0
renderFileItem : Model -> Maybe String -> 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 "flex flex-col w-full mb-4" ]
[ div [ class "flex flex-row items-center" ]
[ div [ class "inline-flex items-center" ]
[ i
[ classList
[ ( "mr-2 text-lg", True )
, ( "fa fa-file font-thin", isIdle model file )
, ( "fa fa-spinner animate-spin ", isLoading model file )
, ( "fa fa-check ", isCompleted model file )
, ( "fa fa-bolt", isError model file )
]
]
[]
, div [ class "middle aligned content" ]
[ div [ class "header" ]
[ text name
]
]
]
, div [ class "flex-grow inline-flex justify-end" ]
[ text size
]
]
, div [ class "h-4" ]
[ Comp.Progress.progress2 (getProgress model file)
]
]
viewContent texts sourceId flags settings model =
Html.map UploadMsg
(Comp.UploadForm.view texts.uploadForm sourceId flags settings model.uploadForm)