mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 10:28:27 +00:00
@ -1961,7 +1961,7 @@ paths:
|
|||||||
- $ref: "#/components/parameters/bookmarkId"
|
- $ref: "#/components/parameters/bookmarkId"
|
||||||
delete:
|
delete:
|
||||||
operationId: "sec-querybookmark-delete"
|
operationId: "sec-querybookmark-delete"
|
||||||
tags: [Query Bookmark]
|
tags: [Query Bookmarks]
|
||||||
summary: Delete a bookmark.
|
summary: Delete a bookmark.
|
||||||
description: |
|
description: |
|
||||||
Deletes a bookmarks by its id.
|
Deletes a bookmarks by its id.
|
||||||
|
@ -11,6 +11,7 @@ module Api exposing
|
|||||||
, addConcPerson
|
, addConcPerson
|
||||||
, addCorrOrg
|
, addCorrOrg
|
||||||
, addCorrPerson
|
, addCorrPerson
|
||||||
|
, addDashboard
|
||||||
, addMember
|
, addMember
|
||||||
, addShare
|
, addShare
|
||||||
, addTag
|
, addTag
|
||||||
@ -39,6 +40,7 @@ module Api exposing
|
|||||||
, deleteCustomField
|
, deleteCustomField
|
||||||
, deleteCustomValue
|
, deleteCustomValue
|
||||||
, deleteCustomValueMultiple
|
, deleteCustomValueMultiple
|
||||||
|
, deleteDashboard
|
||||||
, deleteEquip
|
, deleteEquip
|
||||||
, deleteFolder
|
, deleteFolder
|
||||||
, deleteHook
|
, deleteHook
|
||||||
@ -56,6 +58,7 @@ module Api exposing
|
|||||||
, deleteUser
|
, deleteUser
|
||||||
, disableOtp
|
, disableOtp
|
||||||
, fileURL
|
, fileURL
|
||||||
|
, getAllDashboards
|
||||||
, getAttachmentMeta
|
, getAttachmentMeta
|
||||||
, getBookmarks
|
, getBookmarks
|
||||||
, getChannels
|
, getChannels
|
||||||
@ -101,7 +104,9 @@ module Api exposing
|
|||||||
, itemDetailShare
|
, itemDetailShare
|
||||||
, itemIndexSearch
|
, itemIndexSearch
|
||||||
, itemSearch
|
, itemSearch
|
||||||
|
, itemSearchBookmark
|
||||||
, itemSearchStats
|
, itemSearchStats
|
||||||
|
, itemSearchStatsBookmark
|
||||||
, login
|
, login
|
||||||
, loginSession
|
, loginSession
|
||||||
, logout
|
, logout
|
||||||
@ -124,6 +129,7 @@ module Api exposing
|
|||||||
, register
|
, register
|
||||||
, removeMember
|
, removeMember
|
||||||
, removeTagsMultiple
|
, removeTagsMultiple
|
||||||
|
, replaceDashboard
|
||||||
, reprocessItem
|
, reprocessItem
|
||||||
, reprocessMultiple
|
, reprocessMultiple
|
||||||
, restoreAllItems
|
, restoreAllItems
|
||||||
@ -275,9 +281,12 @@ import Api.Model.User exposing (User)
|
|||||||
import Api.Model.UserList exposing (UserList)
|
import Api.Model.UserList exposing (UserList)
|
||||||
import Api.Model.UserPass exposing (UserPass)
|
import Api.Model.UserPass exposing (UserPass)
|
||||||
import Api.Model.VersionInfo exposing (VersionInfo)
|
import Api.Model.VersionInfo exposing (VersionInfo)
|
||||||
|
import Data.AccountScope exposing (AccountScope)
|
||||||
import Data.Bookmarks exposing (AllBookmarks, Bookmarks)
|
import Data.Bookmarks exposing (AllBookmarks, Bookmarks)
|
||||||
import Data.ContactType exposing (ContactType)
|
import Data.ContactType exposing (ContactType)
|
||||||
import Data.CustomFieldOrder exposing (CustomFieldOrder)
|
import Data.CustomFieldOrder exposing (CustomFieldOrder)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Dashboards exposing (AllDashboards, Dashboards)
|
||||||
import Data.EquipmentOrder exposing (EquipmentOrder)
|
import Data.EquipmentOrder exposing (EquipmentOrder)
|
||||||
import Data.EventType exposing (EventType)
|
import Data.EventType exposing (EventType)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
@ -297,6 +306,7 @@ import Task
|
|||||||
import Url
|
import Url
|
||||||
import Util.File
|
import Util.File
|
||||||
import Util.Http as Http2
|
import Util.Http as Http2
|
||||||
|
import Util.Result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2028,24 +2038,70 @@ itemIndexSearch flags query receive =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
itemSearch : Flags -> ItemQuery -> (Result Http.Error ItemLightList -> msg) -> Cmd msg
|
itemSearchTask : Flags -> ItemQuery -> Task.Task Http.Error ItemLightList
|
||||||
itemSearch flags search receive =
|
itemSearchTask flags search =
|
||||||
Http2.authPost
|
Http2.authTask
|
||||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/item/search"
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/item/search"
|
||||||
|
, method = "POST"
|
||||||
|
, headers = []
|
||||||
, account = getAccount flags
|
, account = getAccount flags
|
||||||
, body = Http.jsonBody (Api.Model.ItemQuery.encode search)
|
, body = Http.jsonBody (Api.Model.ItemQuery.encode search)
|
||||||
, expect = Http.expectJson receive Api.Model.ItemLightList.decoder
|
, resolver = Http2.jsonResolver Api.Model.ItemLightList.decoder
|
||||||
|
, timeout = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
itemSearch : Flags -> ItemQuery -> (Result Http.Error ItemLightList -> msg) -> Cmd msg
|
||||||
|
itemSearch flags search receive =
|
||||||
|
itemSearchTask flags search |> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
{-| Same as `itemSearch` but interprets the `query` field as a bookmark id.
|
||||||
|
-}
|
||||||
|
itemSearchBookmark : Flags -> ItemQuery -> (Result Http.Error ItemLightList -> msg) -> Cmd msg
|
||||||
|
itemSearchBookmark flags bmSearch receive =
|
||||||
|
let
|
||||||
|
getBookmark =
|
||||||
|
getBookmarkByIdTask flags bmSearch.query
|
||||||
|
|> Task.map (\bm -> { bmSearch | query = bm.query })
|
||||||
|
|
||||||
|
search q =
|
||||||
|
itemSearchTask flags q
|
||||||
|
in
|
||||||
|
Task.andThen search getBookmark
|
||||||
|
|> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
itemSearchStatsTask : Flags -> ItemQuery -> Task.Task Http.Error SearchStats
|
||||||
|
itemSearchStatsTask flags search =
|
||||||
|
Http2.authTask
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/item/searchStats"
|
||||||
|
, method = "POST"
|
||||||
|
, headers = []
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.ItemQuery.encode search)
|
||||||
|
, resolver = Http2.jsonResolver Api.Model.SearchStats.decoder
|
||||||
|
, timeout = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
itemSearchStats : Flags -> ItemQuery -> (Result Http.Error SearchStats -> msg) -> Cmd msg
|
itemSearchStats : Flags -> ItemQuery -> (Result Http.Error SearchStats -> msg) -> Cmd msg
|
||||||
itemSearchStats flags search receive =
|
itemSearchStats flags search receive =
|
||||||
Http2.authPost
|
itemSearchStatsTask flags search |> Task.attempt receive
|
||||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/item/searchStats"
|
|
||||||
, account = getAccount flags
|
|
||||||
, body = Http.jsonBody (Api.Model.ItemQuery.encode search)
|
itemSearchStatsBookmark : Flags -> ItemQuery -> (Result Http.Error SearchStats -> msg) -> Cmd msg
|
||||||
, expect = Http.expectJson receive Api.Model.SearchStats.decoder
|
itemSearchStatsBookmark flags search receive =
|
||||||
}
|
let
|
||||||
|
getBookmark =
|
||||||
|
getBookmarkByIdTask flags search.query
|
||||||
|
|> Task.map (\bm -> { search | query = bm.query })
|
||||||
|
|
||||||
|
getStats q =
|
||||||
|
itemSearchStatsTask flags q
|
||||||
|
in
|
||||||
|
Task.andThen getStats getBookmark
|
||||||
|
|> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
itemDetail : Flags -> String -> (Result Http.Error ItemDetail -> msg) -> Cmd msg
|
itemDetail : Flags -> String -> (Result Http.Error ItemDetail -> msg) -> Cmd msg
|
||||||
@ -2314,6 +2370,132 @@ saveClientSettings flags settings receive =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Dashboards
|
||||||
|
|
||||||
|
|
||||||
|
dashboardsUrl : Flags -> AccountScope -> String
|
||||||
|
dashboardsUrl flags scope =
|
||||||
|
let
|
||||||
|
part =
|
||||||
|
Data.AccountScope.fold "user" "collective" scope
|
||||||
|
in
|
||||||
|
flags.config.baseUrl ++ "/api/v1/sec/clientSettings/" ++ part ++ "/webClientDashboards"
|
||||||
|
|
||||||
|
|
||||||
|
getDashboardsScopeTask : Flags -> AccountScope -> Task.Task Http.Error Dashboards
|
||||||
|
getDashboardsScopeTask flags scope =
|
||||||
|
Http2.authTask
|
||||||
|
{ method = "GET"
|
||||||
|
, url = dashboardsUrl flags scope
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.emptyBody
|
||||||
|
, resolver = Http2.jsonResolver Data.Dashboards.decoder
|
||||||
|
, headers = []
|
||||||
|
, timeout = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pushDashbordsScopeTask : Flags -> AccountScope -> Dashboards -> Task.Task Http.Error BasicResult
|
||||||
|
pushDashbordsScopeTask flags scope boards =
|
||||||
|
Http2.authTask
|
||||||
|
{ method = "PUT"
|
||||||
|
, url = dashboardsUrl flags scope
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Data.Dashboards.encode boards)
|
||||||
|
, resolver = Http2.jsonResolver Api.Model.BasicResult.decoder
|
||||||
|
, headers = []
|
||||||
|
, timeout = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getAllDashboardsTask : Flags -> Task.Task Http.Error AllDashboards
|
||||||
|
getAllDashboardsTask flags =
|
||||||
|
let
|
||||||
|
coll =
|
||||||
|
getDashboardsScopeTask flags Data.AccountScope.Collective
|
||||||
|
|
||||||
|
user =
|
||||||
|
getDashboardsScopeTask flags Data.AccountScope.User
|
||||||
|
in
|
||||||
|
Task.map2 AllDashboards coll user
|
||||||
|
|
||||||
|
|
||||||
|
getAllDashboards : Flags -> (Result Http.Error AllDashboards -> msg) -> Cmd msg
|
||||||
|
getAllDashboards flags receive =
|
||||||
|
getAllDashboardsTask flags |> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
saveDashboardTask : Flags -> String -> Dashboard -> AccountScope -> Bool -> Task.Task Http.Error BasicResult
|
||||||
|
saveDashboardTask flags original board scope isDefault =
|
||||||
|
let
|
||||||
|
boardsTask =
|
||||||
|
getAllDashboardsTask flags
|
||||||
|
|
||||||
|
setDefault all =
|
||||||
|
if isDefault then
|
||||||
|
Data.Dashboards.setDefaultAll board.name all
|
||||||
|
|
||||||
|
else
|
||||||
|
Data.Dashboards.unsetDefaultAll board.name all
|
||||||
|
|
||||||
|
removeOriginal boards =
|
||||||
|
Data.Dashboards.removeFromAll original boards
|
||||||
|
|
||||||
|
insert all =
|
||||||
|
Data.Dashboards.insertIn scope board all
|
||||||
|
|
||||||
|
update all =
|
||||||
|
let
|
||||||
|
next =
|
||||||
|
(removeOriginal >> insert >> setDefault) all
|
||||||
|
|
||||||
|
saveU =
|
||||||
|
if all.user == next.user then
|
||||||
|
Task.succeed (BasicResult True "")
|
||||||
|
|
||||||
|
else
|
||||||
|
pushDashbordsScopeTask flags Data.AccountScope.User next.user
|
||||||
|
|
||||||
|
saveC =
|
||||||
|
if all.collective == next.collective then
|
||||||
|
Task.succeed (BasicResult True "")
|
||||||
|
|
||||||
|
else
|
||||||
|
pushDashbordsScopeTask flags Data.AccountScope.Collective next.collective
|
||||||
|
in
|
||||||
|
Task.map2 Util.Result.combine saveU saveC
|
||||||
|
in
|
||||||
|
Task.andThen update boardsTask
|
||||||
|
|
||||||
|
|
||||||
|
addDashboard : Flags -> Dashboard -> AccountScope -> Bool -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addDashboard flags board scope isDefault receive =
|
||||||
|
saveDashboardTask flags board.name board scope isDefault |> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
replaceDashboard : Flags -> String -> Dashboard -> AccountScope -> Bool -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
replaceDashboard flags originalName board scope isDefault receive =
|
||||||
|
saveDashboardTask flags originalName board scope isDefault |> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
deleteDashboardTask : Flags -> String -> AccountScope -> Task.Task Http.Error BasicResult
|
||||||
|
deleteDashboardTask flags name scope =
|
||||||
|
let
|
||||||
|
boardsTask =
|
||||||
|
getDashboardsScopeTask flags scope
|
||||||
|
|
||||||
|
remove boards =
|
||||||
|
Data.Dashboards.remove name boards
|
||||||
|
in
|
||||||
|
Task.andThen (remove >> pushDashbordsScopeTask flags scope) boardsTask
|
||||||
|
|
||||||
|
|
||||||
|
deleteDashboard : Flags -> String -> AccountScope -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
deleteDashboard flags name scope receive =
|
||||||
|
deleteDashboardTask flags name scope |> Task.attempt receive
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Query Bookmarks
|
--- Query Bookmarks
|
||||||
|
|
||||||
|
|
||||||
@ -2335,6 +2517,21 @@ getBookmarksTask flags =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getBookmarkByIdTask : Flags -> String -> Task.Task Http.Error BookmarkedQuery
|
||||||
|
getBookmarkByIdTask flags id =
|
||||||
|
let
|
||||||
|
findBm all =
|
||||||
|
Data.Bookmarks.findById id all
|
||||||
|
|
||||||
|
mapNotFound maybeBookmark =
|
||||||
|
Maybe.map Task.succeed maybeBookmark
|
||||||
|
|> Maybe.withDefault (Task.fail (Http.BadStatus 404))
|
||||||
|
in
|
||||||
|
getBookmarksTask flags
|
||||||
|
|> Task.map findBm
|
||||||
|
|> Task.andThen mapNotFound
|
||||||
|
|
||||||
|
|
||||||
getBookmarks : Flags -> (Result Http.Error AllBookmarks -> msg) -> Cmd msg
|
getBookmarks : Flags -> (Result Http.Error AllBookmarks -> msg) -> Cmd msg
|
||||||
getBookmarks flags receive =
|
getBookmarks flags receive =
|
||||||
let
|
let
|
||||||
|
@ -18,21 +18,25 @@ import Api.Model.BasicResult exposing (BasicResult)
|
|||||||
import Api.Model.VersionInfo exposing (VersionInfo)
|
import Api.Model.VersionInfo exposing (VersionInfo)
|
||||||
import Browser exposing (UrlRequest)
|
import Browser exposing (UrlRequest)
|
||||||
import Browser.Navigation exposing (Key)
|
import Browser.Navigation exposing (Key)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.ServerEvent exposing (ServerEvent)
|
import Data.ServerEvent exposing (ServerEvent)
|
||||||
import Data.UiSettings exposing (StoredUiSettings, UiSettings)
|
import Data.UiSettings exposing (StoredUiSettings, UiSettings)
|
||||||
import Data.UiTheme exposing (UiTheme)
|
import Data.UiTheme exposing (UiTheme)
|
||||||
import Http
|
import Http
|
||||||
|
import Messages
|
||||||
import Messages.UiLanguage exposing (UiLanguage)
|
import Messages.UiLanguage exposing (UiLanguage)
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Page.CollectiveSettings.Data
|
import Page.CollectiveSettings.Data
|
||||||
import Page.Home.Data
|
import Page.Dashboard.Data
|
||||||
|
import Page.Dashboard.DefaultDashboard
|
||||||
import Page.ItemDetail.Data
|
import Page.ItemDetail.Data
|
||||||
import Page.Login.Data
|
import Page.Login.Data
|
||||||
import Page.ManageData.Data
|
import Page.ManageData.Data
|
||||||
import Page.NewInvite.Data
|
import Page.NewInvite.Data
|
||||||
import Page.Queue.Data
|
import Page.Queue.Data
|
||||||
import Page.Register.Data
|
import Page.Register.Data
|
||||||
|
import Page.Search.Data
|
||||||
import Page.Share.Data
|
import Page.Share.Data
|
||||||
import Page.ShareDetail.Data
|
import Page.ShareDetail.Data
|
||||||
import Page.Upload.Data
|
import Page.Upload.Data
|
||||||
@ -45,7 +49,7 @@ type alias Model =
|
|||||||
, key : Key
|
, key : Key
|
||||||
, page : Page
|
, page : Page
|
||||||
, version : VersionInfo
|
, version : VersionInfo
|
||||||
, homeModel : Page.Home.Data.Model
|
, searchModel : Page.Search.Data.Model
|
||||||
, loginModel : Page.Login.Data.Model
|
, loginModel : Page.Login.Data.Model
|
||||||
, manageDataModel : Page.ManageData.Data.Model
|
, manageDataModel : Page.ManageData.Data.Model
|
||||||
, collSettingsModel : Page.CollectiveSettings.Data.Model
|
, collSettingsModel : Page.CollectiveSettings.Data.Model
|
||||||
@ -57,6 +61,7 @@ type alias Model =
|
|||||||
, itemDetailModel : Page.ItemDetail.Data.Model
|
, itemDetailModel : Page.ItemDetail.Data.Model
|
||||||
, shareModel : Page.Share.Data.Model
|
, shareModel : Page.Share.Data.Model
|
||||||
, shareDetailModel : Page.ShareDetail.Data.Model
|
, shareDetailModel : Page.ShareDetail.Data.Model
|
||||||
|
, dashboardModel : Page.Dashboard.Data.Model
|
||||||
, navMenuOpen : Bool
|
, navMenuOpen : Bool
|
||||||
, userMenuOpen : Bool
|
, userMenuOpen : Bool
|
||||||
, subs : Sub Msg
|
, subs : Sub Msg
|
||||||
@ -98,18 +103,21 @@ init key url flags_ settings =
|
|||||||
( sdm, sdc ) =
|
( sdm, sdc ) =
|
||||||
Page.ShareDetail.Data.init (Page.pageShareDetail page) flags
|
Page.ShareDetail.Data.init (Page.pageShareDetail page) flags
|
||||||
|
|
||||||
homeViewMode =
|
( dbm, dbc ) =
|
||||||
|
Page.Dashboard.Data.init flags
|
||||||
|
|
||||||
|
searchViewMode =
|
||||||
if settings.searchMenuVisible then
|
if settings.searchMenuVisible then
|
||||||
Page.Home.Data.SearchView
|
Page.Search.Data.SearchView
|
||||||
|
|
||||||
else
|
else
|
||||||
Page.Home.Data.SimpleView
|
Page.Search.Data.SimpleView
|
||||||
in
|
in
|
||||||
( { flags = flags
|
( { flags = flags
|
||||||
, key = key
|
, key = key
|
||||||
, page = page
|
, page = page
|
||||||
, version = Api.Model.VersionInfo.empty
|
, version = Api.Model.VersionInfo.empty
|
||||||
, homeModel = Page.Home.Data.init flags homeViewMode
|
, searchModel = Page.Search.Data.init flags searchViewMode
|
||||||
, loginModel = loginm
|
, loginModel = loginm
|
||||||
, manageDataModel = mdm
|
, manageDataModel = mdm
|
||||||
, collSettingsModel = csm
|
, collSettingsModel = csm
|
||||||
@ -121,6 +129,7 @@ init key url flags_ settings =
|
|||||||
, itemDetailModel = Page.ItemDetail.Data.emptyModel
|
, itemDetailModel = Page.ItemDetail.Data.emptyModel
|
||||||
, shareModel = shm
|
, shareModel = shm
|
||||||
, shareDetailModel = sdm
|
, shareDetailModel = sdm
|
||||||
|
, dashboardModel = dbm
|
||||||
, navMenuOpen = False
|
, navMenuOpen = False
|
||||||
, userMenuOpen = False
|
, userMenuOpen = False
|
||||||
, subs = Sub.none
|
, subs = Sub.none
|
||||||
@ -133,7 +142,8 @@ init key url flags_ settings =
|
|||||||
, jobsWaiting = 0
|
, jobsWaiting = 0
|
||||||
}
|
}
|
||||||
, Cmd.batch
|
, Cmd.batch
|
||||||
[ Cmd.map UserSettingsMsg uc
|
[ Cmd.map DashboardMsg dbc
|
||||||
|
, Cmd.map UserSettingsMsg uc
|
||||||
, Cmd.map ManageDataMsg mdc
|
, Cmd.map ManageDataMsg mdc
|
||||||
, Cmd.map CollSettingsMsg csc
|
, Cmd.map CollSettingsMsg csc
|
||||||
, Cmd.map LoginMsg loginc
|
, Cmd.map LoginMsg loginc
|
||||||
@ -171,7 +181,7 @@ type Msg
|
|||||||
= NavRequest UrlRequest
|
= NavRequest UrlRequest
|
||||||
| NavChange Url
|
| NavChange Url
|
||||||
| VersionResp (Result Http.Error VersionInfo)
|
| VersionResp (Result Http.Error VersionInfo)
|
||||||
| HomeMsg Page.Home.Data.Msg
|
| SearchMsg Page.Search.Data.Msg
|
||||||
| LoginMsg Page.Login.Data.Msg
|
| LoginMsg Page.Login.Data.Msg
|
||||||
| ManageDataMsg Page.ManageData.Data.Msg
|
| ManageDataMsg Page.ManageData.Data.Msg
|
||||||
| CollSettingsMsg Page.CollectiveSettings.Data.Msg
|
| CollSettingsMsg Page.CollectiveSettings.Data.Msg
|
||||||
@ -183,6 +193,7 @@ type Msg
|
|||||||
| ItemDetailMsg Page.ItemDetail.Data.Msg
|
| ItemDetailMsg Page.ItemDetail.Data.Msg
|
||||||
| ShareMsg Page.Share.Data.Msg
|
| ShareMsg Page.Share.Data.Msg
|
||||||
| ShareDetailMsg Page.ShareDetail.Data.Msg
|
| ShareDetailMsg Page.ShareDetail.Data.Msg
|
||||||
|
| DashboardMsg Page.Dashboard.Data.Msg
|
||||||
| Logout
|
| Logout
|
||||||
| LogoutResp (Result Http.Error ())
|
| LogoutResp (Result Http.Error ())
|
||||||
| SessionCheckResp (Result Http.Error AuthResult)
|
| SessionCheckResp (Result Http.Error AuthResult)
|
||||||
@ -201,14 +212,9 @@ type Msg
|
|||||||
|
|
||||||
defaultPage : Flags -> Page
|
defaultPage : Flags -> Page
|
||||||
defaultPage _ =
|
defaultPage _ =
|
||||||
HomePage
|
DashboardPage
|
||||||
|
|
||||||
|
|
||||||
getUiLanguage : Model -> UiLanguage
|
getUiLanguage : Model -> UiLanguage
|
||||||
getUiLanguage model =
|
getUiLanguage model =
|
||||||
case model.flags.account of
|
Data.UiSettings.getUiLanguage model.flags model.uiSettings model.anonymousUiLang
|
||||||
Just _ ->
|
|
||||||
model.uiSettings.uiLang
|
|
||||||
|
|
||||||
Nothing ->
|
|
||||||
model.anonymousUiLang
|
|
||||||
|
@ -14,7 +14,7 @@ import Api
|
|||||||
import App.Data exposing (..)
|
import App.Data exposing (..)
|
||||||
import Browser exposing (UrlRequest(..))
|
import Browser exposing (UrlRequest(..))
|
||||||
import Browser.Navigation as Nav
|
import Browser.Navigation as Nav
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags
|
||||||
import Data.ServerEvent exposing (ServerEvent(..))
|
import Data.ServerEvent exposing (ServerEvent(..))
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import Data.UiTheme
|
import Data.UiTheme
|
||||||
@ -22,8 +22,8 @@ import Messages exposing (Messages)
|
|||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Page.CollectiveSettings.Data
|
import Page.CollectiveSettings.Data
|
||||||
import Page.CollectiveSettings.Update
|
import Page.CollectiveSettings.Update
|
||||||
import Page.Home.Data
|
import Page.Dashboard.Data
|
||||||
import Page.Home.Update
|
import Page.Dashboard.Update
|
||||||
import Page.ItemDetail.Data
|
import Page.ItemDetail.Data
|
||||||
import Page.ItemDetail.Update
|
import Page.ItemDetail.Update
|
||||||
import Page.Login.Data
|
import Page.Login.Data
|
||||||
@ -36,6 +36,8 @@ import Page.Queue.Data
|
|||||||
import Page.Queue.Update
|
import Page.Queue.Update
|
||||||
import Page.Register.Data
|
import Page.Register.Data
|
||||||
import Page.Register.Update
|
import Page.Register.Update
|
||||||
|
import Page.Search.Data
|
||||||
|
import Page.Search.Update
|
||||||
import Page.Share.Data
|
import Page.Share.Data
|
||||||
import Page.Share.Update
|
import Page.Share.Update
|
||||||
import Page.ShareDetail.Data
|
import Page.ShareDetail.Data
|
||||||
@ -121,8 +123,8 @@ updateWithSub msg model =
|
|||||||
SetLanguage lang ->
|
SetLanguage lang ->
|
||||||
( { model | anonymousUiLang = lang, langMenuOpen = False }, Cmd.none, Sub.none )
|
( { model | anonymousUiLang = lang, langMenuOpen = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
HomeMsg lm ->
|
SearchMsg lm ->
|
||||||
updateHome texts lm model
|
updateSearch texts lm model
|
||||||
|
|
||||||
ShareMsg lm ->
|
ShareMsg lm ->
|
||||||
updateShare lm model
|
updateShare lm model
|
||||||
@ -157,6 +159,9 @@ updateWithSub msg model =
|
|||||||
ItemDetailMsg m ->
|
ItemDetailMsg m ->
|
||||||
updateItemDetail texts m model
|
updateItemDetail texts m model
|
||||||
|
|
||||||
|
DashboardMsg m ->
|
||||||
|
updateDashboard texts m model
|
||||||
|
|
||||||
VersionResp (Ok info) ->
|
VersionResp (Ok info) ->
|
||||||
( { model | version = info }, Cmd.none, Sub.none )
|
( { model | version = info }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
@ -318,12 +323,15 @@ updateWithSub msg model =
|
|||||||
|
|
||||||
newModel =
|
newModel =
|
||||||
{ model
|
{ model
|
||||||
| showNewItemsArrived = isProcessItem && model.page /= HomePage
|
| showNewItemsArrived = isProcessItem && not (Page.isSearchPage model.page)
|
||||||
, jobsWaiting = max 0 (model.jobsWaiting - 1)
|
, jobsWaiting = max 0 (model.jobsWaiting - 1)
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
if model.page == HomePage && isProcessItem then
|
if Page.isSearchPage model.page && isProcessItem then
|
||||||
updateHome texts Page.Home.Data.RefreshView newModel
|
updateSearch texts Page.Search.Data.RefreshView newModel
|
||||||
|
|
||||||
|
else if Page.isDashboardPage model.page && isProcessItem then
|
||||||
|
updateDashboard texts Page.Dashboard.Data.reloadDashboardData newModel
|
||||||
|
|
||||||
else
|
else
|
||||||
( newModel, Cmd.none, Sub.none )
|
( newModel, Cmd.none, Sub.none )
|
||||||
@ -359,13 +367,31 @@ applyClientSettings texts model settings =
|
|||||||
, setTheme
|
, setTheme
|
||||||
, Sub.none
|
, Sub.none
|
||||||
)
|
)
|
||||||
|
, updateDashboard texts Page.Dashboard.Data.reloadUiSettings
|
||||||
, updateUserSettings texts Page.UserSettings.Data.UpdateSettings
|
, updateUserSettings texts Page.UserSettings.Data.UpdateSettings
|
||||||
, updateHome texts Page.Home.Data.UiSettingsUpdated
|
, updateSearch texts Page.Search.Data.UiSettingsUpdated
|
||||||
, updateItemDetail texts Page.ItemDetail.Data.UiSettingsUpdated
|
, updateItemDetail texts Page.ItemDetail.Data.UiSettingsUpdated
|
||||||
]
|
]
|
||||||
{ model | uiSettings = settings }
|
{ model | uiSettings = settings }
|
||||||
|
|
||||||
|
|
||||||
|
updateDashboard : Messages -> Page.Dashboard.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
updateDashboard texts lmsg model =
|
||||||
|
let
|
||||||
|
( dbm, dbc, dbs ) =
|
||||||
|
Page.Dashboard.Update.update texts.dashboard
|
||||||
|
model.uiSettings
|
||||||
|
model.key
|
||||||
|
model.flags
|
||||||
|
lmsg
|
||||||
|
model.dashboardModel
|
||||||
|
in
|
||||||
|
( { model | dashboardModel = dbm }
|
||||||
|
, Cmd.map DashboardMsg dbc
|
||||||
|
, Sub.map DashboardMsg dbs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
updateShareDetail : Page.ShareDetail.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
updateShareDetail : Page.ShareDetail.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
updateShareDetail lmsg model =
|
updateShareDetail lmsg model =
|
||||||
case Page.pageShareDetail model.page of
|
case Page.pageShareDetail model.page of
|
||||||
@ -404,7 +430,7 @@ updateItemDetail : Messages -> Page.ItemDetail.Data.Msg -> Model -> ( Model, Cmd
|
|||||||
updateItemDetail texts lmsg model =
|
updateItemDetail texts lmsg model =
|
||||||
let
|
let
|
||||||
inav =
|
inav =
|
||||||
Page.Home.Data.itemNav model.itemDetailModel.detail.item.id model.homeModel
|
Page.Search.Data.itemNav model.itemDetailModel.detail.item.id model.searchModel
|
||||||
|
|
||||||
result =
|
result =
|
||||||
Page.ItemDetail.Update.update
|
Page.ItemDetail.Update.update
|
||||||
@ -421,12 +447,12 @@ updateItemDetail texts lmsg model =
|
|||||||
}
|
}
|
||||||
|
|
||||||
( hm, hc, hs ) =
|
( hm, hc, hs ) =
|
||||||
updateHome texts (Page.Home.Data.SetLinkTarget result.linkTarget) model_
|
updateSearch texts (Page.Search.Data.SetLinkTarget result.linkTarget) model_
|
||||||
|
|
||||||
( hm1, hc1, hs1 ) =
|
( hm1, hc1, hs1 ) =
|
||||||
case result.removedItem of
|
case result.removedItem of
|
||||||
Just removedId ->
|
Just removedId ->
|
||||||
updateHome texts (Page.Home.Data.RemoveItem removedId) hm
|
updateSearch texts (Page.Search.Data.RemoveItem removedId) hm
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
( hm, hc, hs )
|
( hm, hc, hs )
|
||||||
@ -552,22 +578,22 @@ updateLogin lmsg model =
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
updateHome : Messages -> Page.Home.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
updateSearch : Messages -> Page.Search.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
updateHome texts lmsg model =
|
updateSearch texts lmsg model =
|
||||||
let
|
let
|
||||||
mid =
|
( mid, bmId ) =
|
||||||
case model.page of
|
case model.page of
|
||||||
HomePage ->
|
SearchPage bId ->
|
||||||
Util.Maybe.fromString model.itemDetailModel.detail.item.id
|
( Util.Maybe.fromString model.itemDetailModel.detail.item.id, bId )
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
Nothing
|
( Nothing, Nothing )
|
||||||
|
|
||||||
result =
|
result =
|
||||||
Page.Home.Update.update mid model.key model.flags texts.home model.uiSettings lmsg model.homeModel
|
Page.Search.Update.update bmId mid model.key model.flags texts.search model.uiSettings lmsg model.searchModel
|
||||||
|
|
||||||
model_ =
|
model_ =
|
||||||
{ model | homeModel = result.model }
|
{ model | searchModel = result.model }
|
||||||
|
|
||||||
( lm, lc, ls ) =
|
( lm, lc, ls ) =
|
||||||
case result.newSettings of
|
case result.newSettings of
|
||||||
@ -579,11 +605,11 @@ updateHome texts lmsg model =
|
|||||||
in
|
in
|
||||||
( lm
|
( lm
|
||||||
, Cmd.batch
|
, Cmd.batch
|
||||||
[ Cmd.map HomeMsg result.cmd
|
[ Cmd.map SearchMsg result.cmd
|
||||||
, lc
|
, lc
|
||||||
]
|
]
|
||||||
, Sub.batch
|
, Sub.batch
|
||||||
[ Sub.map HomeMsg result.sub
|
[ Sub.map SearchMsg result.sub
|
||||||
, ls
|
, ls
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -611,9 +637,9 @@ initPage model_ page =
|
|||||||
Messages.get <| App.Data.getUiLanguage model
|
Messages.get <| App.Data.getUiLanguage model
|
||||||
in
|
in
|
||||||
case page of
|
case page of
|
||||||
HomePage ->
|
SearchPage _ ->
|
||||||
Util.Update.andThen2
|
Util.Update.andThen2
|
||||||
[ updateHome texts Page.Home.Data.Init
|
[ updateSearch texts Page.Search.Data.Init
|
||||||
, updateQueue Page.Queue.Data.StopRefresh
|
, updateQueue Page.Queue.Data.StopRefresh
|
||||||
]
|
]
|
||||||
model
|
model
|
||||||
@ -646,7 +672,7 @@ initPage model_ page =
|
|||||||
UploadPage _ ->
|
UploadPage _ ->
|
||||||
Util.Update.andThen2
|
Util.Update.andThen2
|
||||||
[ updateQueue Page.Queue.Data.StopRefresh
|
[ updateQueue Page.Queue.Data.StopRefresh
|
||||||
, updateUpload Page.Upload.Data.Clear
|
, updateUpload Page.Upload.Data.reset
|
||||||
]
|
]
|
||||||
model
|
model
|
||||||
|
|
||||||
@ -685,3 +711,6 @@ initPage model_ page =
|
|||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
( model, Cmd.none, Sub.none )
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DashboardPage ->
|
||||||
|
( model, Cmd.map DashboardMsg (Page.Dashboard.Data.reinitCmd model.flags), Sub.none )
|
||||||
|
@ -11,6 +11,8 @@ import Api.Model.AuthResult exposing (AuthResult)
|
|||||||
import App.Data exposing (..)
|
import App.Data exposing (..)
|
||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
import Data.Flags
|
import Data.Flags
|
||||||
|
import Data.Icons as Icons
|
||||||
|
import Data.UiSettings
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick)
|
import Html.Events exposing (onClick)
|
||||||
@ -19,14 +21,15 @@ import Messages.App exposing (Texts)
|
|||||||
import Messages.UiLanguage
|
import Messages.UiLanguage
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Page.CollectiveSettings.View2 as CollectiveSettings
|
import Page.CollectiveSettings.View2 as CollectiveSettings
|
||||||
import Page.Home.Data
|
import Page.Dashboard.View as Dashboard
|
||||||
import Page.Home.View2 as Home
|
|
||||||
import Page.ItemDetail.View2 as ItemDetail
|
import Page.ItemDetail.View2 as ItemDetail
|
||||||
import Page.Login.View2 as Login
|
import Page.Login.View2 as Login
|
||||||
import Page.ManageData.View2 as ManageData
|
import Page.ManageData.View2 as ManageData
|
||||||
import Page.NewInvite.View2 as NewInvite
|
import Page.NewInvite.View2 as NewInvite
|
||||||
import Page.Queue.View2 as Queue
|
import Page.Queue.View2 as Queue
|
||||||
import Page.Register.View2 as Register
|
import Page.Register.View2 as Register
|
||||||
|
import Page.Search.Data
|
||||||
|
import Page.Search.View2 as Search
|
||||||
import Page.Share.View as Share
|
import Page.Share.View as Share
|
||||||
import Page.ShareDetail.View as ShareDetail
|
import Page.ShareDetail.View as ShareDetail
|
||||||
import Page.Upload.View2 as Upload
|
import Page.Upload.View2 as Upload
|
||||||
@ -76,7 +79,11 @@ topNavUser auth model =
|
|||||||
[ class S.infoMessageBase
|
[ class S.infoMessageBase
|
||||||
, class "my-2 px-1 py-1 rounded-lg inline-block hover:opacity-50"
|
, class "my-2 px-1 py-1 rounded-lg inline-block hover:opacity-50"
|
||||||
, classList [ ( "hidden", not model.showNewItemsArrived ) ]
|
, classList [ ( "hidden", not model.showNewItemsArrived ) ]
|
||||||
, Page.href HomePage
|
, if Page.isSearchPage model.page || Page.isDashboardPage model.page then
|
||||||
|
href "#"
|
||||||
|
|
||||||
|
else
|
||||||
|
Page.href (SearchPage Nothing)
|
||||||
, onClick ToggleShowNewItemsArrived
|
, onClick ToggleShowNewItemsArrived
|
||||||
]
|
]
|
||||||
[ i [ class "fa fa-exclamation-circle mr-1" ] []
|
[ i [ class "fa fa-exclamation-circle mr-1" ] []
|
||||||
@ -133,7 +140,7 @@ headerNavItem authenticated model =
|
|||||||
[ class "inline-flex font-bold items-center px-4"
|
[ class "inline-flex font-bold items-center px-4"
|
||||||
, classList [ ( "hover:bg-blue-200 dark:hover:bg-slate-800", authenticated ) ]
|
, classList [ ( "hover:bg-blue-200 dark:hover:bg-slate-800", authenticated ) ]
|
||||||
, if authenticated then
|
, if authenticated then
|
||||||
Page.href HomePage
|
Page.href DashboardPage
|
||||||
|
|
||||||
else
|
else
|
||||||
href "#"
|
href "#"
|
||||||
@ -160,8 +167,11 @@ mainContent model =
|
|||||||
, class styleMain
|
, class styleMain
|
||||||
]
|
]
|
||||||
(case model.page of
|
(case model.page of
|
||||||
HomePage ->
|
DashboardPage ->
|
||||||
viewHome texts model
|
viewDashboard texts model
|
||||||
|
|
||||||
|
SearchPage bmId ->
|
||||||
|
viewSearch texts bmId model
|
||||||
|
|
||||||
CollectiveSettingPage ->
|
CollectiveSettingPage ->
|
||||||
viewCollectiveSettings texts model
|
viewCollectiveSettings texts model
|
||||||
@ -280,7 +290,7 @@ dataMenu texts _ model =
|
|||||||
, classList [ ( "hidden", not model.navMenuOpen ) ]
|
, classList [ ( "hidden", not model.navMenuOpen ) ]
|
||||||
]
|
]
|
||||||
[ dataPageLink model
|
[ dataPageLink model
|
||||||
HomePage
|
DashboardPage
|
||||||
[]
|
[]
|
||||||
[ img
|
[ img
|
||||||
[ class "w-4 inline-block"
|
[ class "w-4 inline-block"
|
||||||
@ -288,14 +298,22 @@ dataMenu texts _ model =
|
|||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, div [ class "inline-block ml-2" ]
|
, div [ class "inline-block ml-2" ]
|
||||||
[ text texts.items
|
[ text texts.dashboard
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, div [ class "py-1" ] [ hr [ class S.border ] [] ]
|
, div [ class "py-1" ] [ hr [ class S.border ] [] ]
|
||||||
|
, dataPageLink model
|
||||||
|
(SearchPage Nothing)
|
||||||
|
[]
|
||||||
|
[ Icons.searchIcon "w-6"
|
||||||
|
, span [ class "ml-1" ]
|
||||||
|
[ text texts.items
|
||||||
|
]
|
||||||
|
]
|
||||||
, dataPageLink model
|
, dataPageLink model
|
||||||
ManageDataPage
|
ManageDataPage
|
||||||
[]
|
[]
|
||||||
[ i [ class "fa fa-cubes w-6" ] []
|
[ Icons.metadataIcon "w-6"
|
||||||
, span [ class "ml-1" ]
|
, span [ class "ml-1" ]
|
||||||
[ text texts.manageData
|
[ text texts.manageData
|
||||||
]
|
]
|
||||||
@ -304,7 +322,7 @@ dataMenu texts _ model =
|
|||||||
, dataPageLink model
|
, dataPageLink model
|
||||||
(UploadPage Nothing)
|
(UploadPage Nothing)
|
||||||
[]
|
[]
|
||||||
[ i [ class "fa fa-upload w-6" ] []
|
[ Icons.fileUploadIcon "w-6"
|
||||||
, span [ class "ml-1" ]
|
, span [ class "ml-1" ]
|
||||||
[ text texts.uploadFiles
|
[ text texts.uploadFiles
|
||||||
]
|
]
|
||||||
@ -345,11 +363,11 @@ dataMenu texts _ model =
|
|||||||
]
|
]
|
||||||
, a
|
, a
|
||||||
[ class dropdownItem
|
[ class dropdownItem
|
||||||
, href "https://docspell.org/docs"
|
, href Data.UiSettings.documentationSite
|
||||||
, target "_new"
|
, target "_new"
|
||||||
, title "Opens https://docspell.org/docs"
|
, title ("Opens " ++ Data.UiSettings.documentationSite)
|
||||||
]
|
]
|
||||||
[ i [ class "fa fa-question-circle w-6" ] []
|
[ Icons.documentationIcon "w-6"
|
||||||
, span [ class "ml-1" ] [ text texts.help ]
|
, span [ class "ml-1" ] [ text texts.help ]
|
||||||
, span [ class "float-right" ]
|
, span [ class "float-right" ]
|
||||||
[ i [ class "fa fa-external-link-alt w-6" ] []
|
[ i [ class "fa fa-external-link-alt w-6" ] []
|
||||||
@ -467,6 +485,25 @@ dropdownMenu =
|
|||||||
" absolute right-0 bg-white dark:bg-slate-800 border dark:border-slate-700 dark:text-slate-300 shadow-lg opacity-1 transition duration-200 min-w-max "
|
" absolute right-0 bg-white dark:bg-slate-800 border dark:border-slate-700 dark:text-slate-300 shadow-lg opacity-1 transition duration-200 min-w-max "
|
||||||
|
|
||||||
|
|
||||||
|
viewDashboard : Messages -> Model -> List (Html Msg)
|
||||||
|
viewDashboard texts model =
|
||||||
|
[ Html.map DashboardMsg
|
||||||
|
(Dashboard.viewSidebar texts.dashboard
|
||||||
|
model.sidebarVisible
|
||||||
|
model.flags
|
||||||
|
model.version
|
||||||
|
model.uiSettings
|
||||||
|
model.dashboardModel
|
||||||
|
)
|
||||||
|
, Html.map DashboardMsg
|
||||||
|
(Dashboard.viewContent texts.dashboard
|
||||||
|
model.flags
|
||||||
|
model.uiSettings
|
||||||
|
model.dashboardModel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
viewShare : Messages -> String -> Model -> List (Html Msg)
|
viewShare : Messages -> String -> Model -> List (Html Msg)
|
||||||
viewShare texts shareId model =
|
viewShare texts shareId model =
|
||||||
[ Html.map ShareMsg
|
[ Html.map ShareMsg
|
||||||
@ -510,20 +547,20 @@ viewShareDetail texts shareId itemId model =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
viewHome : Messages -> Model -> List (Html Msg)
|
viewSearch : Messages -> Maybe String -> Model -> List (Html Msg)
|
||||||
viewHome texts model =
|
viewSearch texts bmId model =
|
||||||
[ Html.map HomeMsg
|
[ Html.map SearchMsg
|
||||||
(Home.viewSidebar texts.home
|
(Search.viewSidebar texts.search
|
||||||
model.sidebarVisible
|
model.sidebarVisible
|
||||||
model.flags
|
model.flags
|
||||||
model.uiSettings
|
model.uiSettings
|
||||||
model.homeModel
|
model.searchModel
|
||||||
)
|
)
|
||||||
, Html.map HomeMsg
|
, Html.map SearchMsg
|
||||||
(Home.viewContent texts.home
|
(Search.viewContent texts.search
|
||||||
model.flags
|
model.flags
|
||||||
model.uiSettings
|
model.uiSettings
|
||||||
model.homeModel
|
model.searchModel
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -647,7 +684,7 @@ viewItemDetail : Messages -> String -> Model -> List (Html Msg)
|
|||||||
viewItemDetail texts id model =
|
viewItemDetail texts id model =
|
||||||
let
|
let
|
||||||
inav =
|
inav =
|
||||||
Page.Home.Data.itemNav id model.homeModel
|
Page.Search.Data.itemNav id model.searchModel
|
||||||
in
|
in
|
||||||
[ Html.map ItemDetailMsg
|
[ Html.map ItemDetailMsg
|
||||||
(ItemDetail.viewSidebar texts.itemDetail
|
(ItemDetail.viewSidebar texts.itemDetail
|
||||||
|
@ -207,7 +207,7 @@ loadingDimmer : { label : String, active : Bool } -> Html msg
|
|||||||
loadingDimmer cfg =
|
loadingDimmer cfg =
|
||||||
let
|
let
|
||||||
content =
|
content =
|
||||||
div [ class "text-gray-200" ]
|
div [ class "text-gray-200 " ]
|
||||||
[ i [ class "fa fa-circle-notch animate-spin" ] []
|
[ i [ class "fa fa-circle-notch animate-spin" ] []
|
||||||
, span [ class "ml-2" ]
|
, span [ class "ml-2" ]
|
||||||
[ text cfg.label
|
[ text cfg.label
|
||||||
|
@ -16,6 +16,7 @@ module Comp.BookmarkChooser exposing
|
|||||||
, isEmptySelection
|
, isEmptySelection
|
||||||
, update
|
, update
|
||||||
, view
|
, view
|
||||||
|
, viewWith
|
||||||
)
|
)
|
||||||
|
|
||||||
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
|
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
|
||||||
@ -114,33 +115,43 @@ update msg model current =
|
|||||||
--- View
|
--- View
|
||||||
|
|
||||||
|
|
||||||
view : Texts -> Model -> Selection -> Html Msg
|
type alias ViewSettings =
|
||||||
view texts model selection =
|
{ showUser : Bool
|
||||||
|
, showCollective : Bool
|
||||||
|
, showShares : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
viewWith : ViewSettings -> Texts -> Model -> Selection -> Html Msg
|
||||||
|
viewWith cfg texts model selection =
|
||||||
let
|
let
|
||||||
( user, coll ) =
|
( user, coll ) =
|
||||||
List.partition .personal model.all.bookmarks
|
List.partition .personal model.all.bookmarks
|
||||||
in
|
in
|
||||||
div [ class "flex flex-col" ]
|
div [ class "flex flex-col" ]
|
||||||
[ userBookmarks texts user selection
|
[ userBookmarks cfg.showUser texts user selection
|
||||||
, collBookmarks texts coll selection
|
, collBookmarks cfg.showCollective texts coll selection
|
||||||
, shares texts model selection
|
, shares cfg.showShares texts model selection
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Model -> Selection -> Html Msg
|
||||||
|
view =
|
||||||
|
viewWith { showUser = True, showCollective = True, showShares = True }
|
||||||
|
|
||||||
|
|
||||||
titleDiv : String -> Html msg
|
titleDiv : String -> Html msg
|
||||||
titleDiv label =
|
titleDiv label =
|
||||||
div [ class "text-sm opacity-75 py-0.5 italic" ]
|
div [ class "text-sm opacity-75 py-0.5 italic" ]
|
||||||
[ text label
|
[ text label
|
||||||
|
|
||||||
--, text " ──"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
userBookmarks : Texts -> List BookmarkedQuery -> Selection -> Html Msg
|
userBookmarks : Bool -> Texts -> List BookmarkedQuery -> Selection -> Html Msg
|
||||||
userBookmarks texts model sel =
|
userBookmarks visible texts model sel =
|
||||||
div
|
div
|
||||||
[ class "mb-2"
|
[ class "mb-2"
|
||||||
, classList [ ( "hidden", model == [] ) ]
|
, classList [ ( "hidden", model == [] || not visible ) ]
|
||||||
]
|
]
|
||||||
[ titleDiv texts.userLabel
|
[ titleDiv texts.userLabel
|
||||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||||
@ -148,11 +159,11 @@ userBookmarks texts model sel =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
collBookmarks : Texts -> List BookmarkedQuery -> Selection -> Html Msg
|
collBookmarks : Bool -> Texts -> List BookmarkedQuery -> Selection -> Html Msg
|
||||||
collBookmarks texts model sel =
|
collBookmarks visible texts model sel =
|
||||||
div
|
div
|
||||||
[ class "mb-2"
|
[ class "mb-2"
|
||||||
, classList [ ( "hidden", [] == model ) ]
|
, classList [ ( "hidden", [] == model || not visible ) ]
|
||||||
]
|
]
|
||||||
[ titleDiv texts.collectiveLabel
|
[ titleDiv texts.collectiveLabel
|
||||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||||
@ -160,15 +171,15 @@ collBookmarks texts model sel =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
shares : Texts -> Model -> Selection -> Html Msg
|
shares : Bool -> Texts -> Model -> Selection -> Html Msg
|
||||||
shares texts model sel =
|
shares visible texts model sel =
|
||||||
let
|
let
|
||||||
bms =
|
bms =
|
||||||
List.map shareToBookmark model.all.shares
|
List.map shareToBookmark model.all.shares
|
||||||
in
|
in
|
||||||
div
|
div
|
||||||
[ class ""
|
[ class ""
|
||||||
, classList [ ( "hidden", List.isEmpty bms ) ]
|
, classList [ ( "hidden", List.isEmpty bms || not visible ) ]
|
||||||
]
|
]
|
||||||
[ titleDiv texts.shareLabel
|
[ titleDiv texts.shareLabel
|
||||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||||
|
474
modules/webapp/src/main/elm/Comp/BoxEdit.elm
Normal file
474
modules/webapp/src/main/elm/Comp/BoxEdit.elm
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxEdit exposing
|
||||||
|
( BoxAction(..)
|
||||||
|
, Model
|
||||||
|
, Msg
|
||||||
|
, UpdateResult
|
||||||
|
, init
|
||||||
|
, update
|
||||||
|
, view
|
||||||
|
)
|
||||||
|
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.BoxMessageEdit
|
||||||
|
import Comp.BoxQueryEdit
|
||||||
|
import Comp.BoxStatsEdit
|
||||||
|
import Comp.BoxUploadEdit
|
||||||
|
import Comp.FixedDropdown
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.Box exposing (Box)
|
||||||
|
import Data.BoxContent exposing (BoxContent(..))
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, i, input, label, text)
|
||||||
|
import Html.Attributes exposing (class, classList, placeholder, type_, value)
|
||||||
|
import Html.Events exposing (onInput, onMouseEnter, onMouseLeave)
|
||||||
|
import Messages.Comp.BoxEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ box : Box
|
||||||
|
, content : ContentModel
|
||||||
|
, colspanModel : Comp.FixedDropdown.Model Int
|
||||||
|
, focus : Bool
|
||||||
|
, deleteRequested : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type ContentModel
|
||||||
|
= ContentMessage Comp.BoxMessageEdit.Model
|
||||||
|
| ContentQuery Comp.BoxQueryEdit.Model
|
||||||
|
| ContentStats Comp.BoxStatsEdit.Model
|
||||||
|
| ContentUpload Comp.BoxUploadEdit.Model
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= ToggleVisible
|
||||||
|
| ToggleDecoration
|
||||||
|
| SetName String
|
||||||
|
| ColspanMsg (Comp.FixedDropdown.Msg Int)
|
||||||
|
| MessageMsg Comp.BoxMessageEdit.Msg
|
||||||
|
| UploadMsg Comp.BoxUploadEdit.Msg
|
||||||
|
| QueryMsg Comp.BoxQueryEdit.Msg
|
||||||
|
| StatsMsg Comp.BoxStatsEdit.Msg
|
||||||
|
| SetFocus Bool
|
||||||
|
| RequestDelete
|
||||||
|
| DeleteBox
|
||||||
|
| CancelDelete
|
||||||
|
| MoveLeft
|
||||||
|
| MoveRight
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> Box -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init flags box =
|
||||||
|
let
|
||||||
|
( cm, cc, cs ) =
|
||||||
|
contentInit flags box.content
|
||||||
|
in
|
||||||
|
( { box = box
|
||||||
|
, content = cm
|
||||||
|
, colspanModel = Comp.FixedDropdown.init [ 1, 2, 3, 4, 5 ]
|
||||||
|
, focus = False
|
||||||
|
, deleteRequested = False
|
||||||
|
}
|
||||||
|
, cc
|
||||||
|
, cs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
contentInit : Flags -> BoxContent -> ( ContentModel, Cmd Msg, Sub Msg )
|
||||||
|
contentInit flags content =
|
||||||
|
case content of
|
||||||
|
BoxMessage data ->
|
||||||
|
( ContentMessage (Comp.BoxMessageEdit.init data), Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
BoxUpload data ->
|
||||||
|
let
|
||||||
|
( um, uc ) =
|
||||||
|
Comp.BoxUploadEdit.init flags data
|
||||||
|
in
|
||||||
|
( ContentUpload um, Cmd.map UploadMsg uc, Sub.none )
|
||||||
|
|
||||||
|
BoxQuery data ->
|
||||||
|
let
|
||||||
|
( qm, qc, qs ) =
|
||||||
|
Comp.BoxQueryEdit.init flags data
|
||||||
|
in
|
||||||
|
( ContentQuery qm, Cmd.map QueryMsg qc, Sub.map QueryMsg qs )
|
||||||
|
|
||||||
|
BoxStats data ->
|
||||||
|
let
|
||||||
|
( qm, qc, qs ) =
|
||||||
|
Comp.BoxStatsEdit.init flags data
|
||||||
|
in
|
||||||
|
( ContentStats qm, Cmd.map StatsMsg qc, Sub.map StatsMsg qs )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type BoxAction
|
||||||
|
= BoxNoAction
|
||||||
|
| BoxMoveLeft
|
||||||
|
| BoxMoveRight
|
||||||
|
| BoxDelete
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
, action : BoxAction
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
MessageMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentMessage m ->
|
||||||
|
let
|
||||||
|
( mm, data ) =
|
||||||
|
Comp.BoxMessageEdit.update lm m
|
||||||
|
|
||||||
|
boxn =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ boxn | content = BoxMessage data }
|
||||||
|
in
|
||||||
|
{ model = { model | content = ContentMessage mm, box = box_ }
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, action = BoxNoAction
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
UploadMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentUpload m ->
|
||||||
|
let
|
||||||
|
( um, data ) =
|
||||||
|
Comp.BoxUploadEdit.update lm m
|
||||||
|
|
||||||
|
boxn =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ boxn | content = BoxUpload data }
|
||||||
|
in
|
||||||
|
{ model = { model | content = ContentUpload um, box = box_ }
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, action = BoxNoAction
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
QueryMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentQuery m ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.BoxQueryEdit.update flags lm m
|
||||||
|
|
||||||
|
boxn =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ boxn | content = BoxQuery result.data }
|
||||||
|
in
|
||||||
|
{ model = { model | content = ContentQuery result.model, box = box_ }
|
||||||
|
, cmd = Cmd.map QueryMsg result.cmd
|
||||||
|
, sub = Sub.map QueryMsg result.sub
|
||||||
|
, action = BoxNoAction
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
StatsMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentStats m ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.BoxStatsEdit.update flags lm m
|
||||||
|
|
||||||
|
boxn =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ boxn | content = BoxStats result.data }
|
||||||
|
in
|
||||||
|
{ model = { model | content = ContentStats result.model, box = box_ }
|
||||||
|
, cmd = Cmd.map StatsMsg result.cmd
|
||||||
|
, sub = Sub.map StatsMsg result.sub
|
||||||
|
, action = BoxNoAction
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
ColspanMsg lm ->
|
||||||
|
let
|
||||||
|
( cm, num ) =
|
||||||
|
Comp.FixedDropdown.update lm model.colspanModel
|
||||||
|
|
||||||
|
boxn =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ boxn | colspan = Maybe.withDefault boxn.colspan num }
|
||||||
|
in
|
||||||
|
unit { model | box = box_, colspanModel = cm }
|
||||||
|
|
||||||
|
ToggleVisible ->
|
||||||
|
let
|
||||||
|
box =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ box | visible = not box.visible }
|
||||||
|
in
|
||||||
|
unit { model | box = box_ }
|
||||||
|
|
||||||
|
ToggleDecoration ->
|
||||||
|
let
|
||||||
|
box =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ box | decoration = not box.decoration }
|
||||||
|
in
|
||||||
|
unit { model | box = box_ }
|
||||||
|
|
||||||
|
SetName name ->
|
||||||
|
let
|
||||||
|
box =
|
||||||
|
model.box
|
||||||
|
|
||||||
|
box_ =
|
||||||
|
{ box | name = name }
|
||||||
|
in
|
||||||
|
unit { model | box = box_ }
|
||||||
|
|
||||||
|
SetFocus flag ->
|
||||||
|
unit { model | focus = flag }
|
||||||
|
|
||||||
|
RequestDelete ->
|
||||||
|
unit { model | deleteRequested = True }
|
||||||
|
|
||||||
|
DeleteBox ->
|
||||||
|
UpdateResult model Cmd.none Sub.none BoxDelete
|
||||||
|
|
||||||
|
CancelDelete ->
|
||||||
|
unit { model | deleteRequested = False }
|
||||||
|
|
||||||
|
MoveLeft ->
|
||||||
|
UpdateResult model Cmd.none Sub.none BoxMoveLeft
|
||||||
|
|
||||||
|
MoveRight ->
|
||||||
|
UpdateResult model Cmd.none Sub.none BoxMoveRight
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
UpdateResult model Cmd.none Sub.none BoxNoAction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags settings model =
|
||||||
|
div
|
||||||
|
[ class (S.box ++ "rounded md:relative")
|
||||||
|
, class " h-full"
|
||||||
|
, classList [ ( "ring ring-opacity-50 ring-blue-600 dark:ring-sky-600", model.focus ) ]
|
||||||
|
, onMouseEnter (SetFocus True)
|
||||||
|
, onMouseLeave (SetFocus False)
|
||||||
|
]
|
||||||
|
[ B.contentDimmer model.deleteRequested
|
||||||
|
(div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "text-xl" ]
|
||||||
|
[ i [ class "fa fa-info-circle mr-2" ] []
|
||||||
|
, text texts.reallyDeleteBox
|
||||||
|
]
|
||||||
|
, div [ class "mt-4 flex flex-row items-center space-x-2" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.DeleteButton
|
||||||
|
{ tagger = DeleteBox
|
||||||
|
, title = ""
|
||||||
|
, label = texts.basics.yes
|
||||||
|
, icon = Just "fa fa-check"
|
||||||
|
}
|
||||||
|
, MB.viewItem <|
|
||||||
|
MB.SecondaryButton
|
||||||
|
{ tagger = CancelDelete
|
||||||
|
, title = ""
|
||||||
|
, label = texts.basics.no
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
, boxHeader texts model
|
||||||
|
, formHeader (texts.boxContent.forContent model.box.content)
|
||||||
|
, div [ class "mb-4 pl-2" ]
|
||||||
|
[ metaForm texts flags model
|
||||||
|
]
|
||||||
|
, formHeader texts.contentProperties
|
||||||
|
, div [ class "pl-4 pr-2 py-2 h-5/6" ]
|
||||||
|
[ boxContent texts flags settings model
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
formHeader : String -> Html msg
|
||||||
|
formHeader heading =
|
||||||
|
div
|
||||||
|
[ class "mx-2 border-b dark:border-slate-500 text-lg mt-1"
|
||||||
|
]
|
||||||
|
[ text heading
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
metaForm : Texts -> Flags -> Model -> Html Msg
|
||||||
|
metaForm texts _ model =
|
||||||
|
let
|
||||||
|
colspanCfg =
|
||||||
|
{ display = String.fromInt
|
||||||
|
, icon = \_ -> Nothing
|
||||||
|
, selectPlaceholder = ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "my-1 px-2 " ]
|
||||||
|
[ div []
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.basics.name
|
||||||
|
]
|
||||||
|
, input
|
||||||
|
[ type_ "text"
|
||||||
|
, placeholder texts.namePlaceholder
|
||||||
|
, class S.textInput
|
||||||
|
, value model.box.name
|
||||||
|
, onInput SetName
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, div [ class "mt-1" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleVisible
|
||||||
|
, label = texts.visible
|
||||||
|
, value = model.box.visible
|
||||||
|
, id = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, div [ class "mt-1" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleDecoration
|
||||||
|
, label = texts.decorations
|
||||||
|
, value = model.box.decoration
|
||||||
|
, id = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, div [ class "mt-1" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.colspan ]
|
||||||
|
, Html.map ColspanMsg
|
||||||
|
(Comp.FixedDropdown.viewStyled2
|
||||||
|
colspanCfg
|
||||||
|
False
|
||||||
|
(Just model.box.colspan)
|
||||||
|
model.colspanModel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
boxHeader : Texts -> Model -> Html Msg
|
||||||
|
boxHeader texts model =
|
||||||
|
div
|
||||||
|
[ class "flex flex-row py-1 bg-blue-50 dark:bg-slate-700 rounded-t"
|
||||||
|
]
|
||||||
|
[ div [ class "flex flex-row items-center text-lg tracking-medium italic px-2" ]
|
||||||
|
[ i
|
||||||
|
[ class (Data.Box.boxIcon model.box)
|
||||||
|
, class "mr-2"
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, text model.box.name
|
||||||
|
]
|
||||||
|
, div [ class "flex flex-grow justify-end pr-1" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.CustomButton
|
||||||
|
{ tagger = MoveLeft
|
||||||
|
, title = texts.moveToLeft
|
||||||
|
, label = ""
|
||||||
|
, icon = Just "fa fa-arrow-left"
|
||||||
|
, inputClass =
|
||||||
|
[ ( S.secondaryBasicButton, True )
|
||||||
|
, ( "text-xs", True )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, MB.viewItem <|
|
||||||
|
MB.CustomButton
|
||||||
|
{ tagger = MoveRight
|
||||||
|
, title = texts.moveToRight
|
||||||
|
, label = ""
|
||||||
|
, icon = Just "fa fa-arrow-right"
|
||||||
|
, inputClass =
|
||||||
|
[ ( S.secondaryBasicButton, True )
|
||||||
|
, ( "text-xs mr-3", True )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, MB.viewItem <|
|
||||||
|
MB.CustomButton
|
||||||
|
{ tagger = RequestDelete
|
||||||
|
, title = texts.deleteBox
|
||||||
|
, label = ""
|
||||||
|
, icon = Just "fa fa-trash"
|
||||||
|
, inputClass =
|
||||||
|
[ ( S.deleteButton, True )
|
||||||
|
, ( "text-xs", True )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
boxContent : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
boxContent texts flags settings model =
|
||||||
|
case model.content of
|
||||||
|
ContentMessage m ->
|
||||||
|
Html.map MessageMsg
|
||||||
|
(Comp.BoxMessageEdit.view texts.messageEdit m)
|
||||||
|
|
||||||
|
ContentUpload m ->
|
||||||
|
Html.map UploadMsg
|
||||||
|
(Comp.BoxUploadEdit.view texts.uploadEdit m)
|
||||||
|
|
||||||
|
ContentQuery m ->
|
||||||
|
Html.map QueryMsg
|
||||||
|
(Comp.BoxQueryEdit.view texts.queryEdit settings m)
|
||||||
|
|
||||||
|
ContentStats m ->
|
||||||
|
Html.map StatsMsg
|
||||||
|
(Comp.BoxStatsEdit.view texts.statsEdit settings m)
|
99
modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm
Normal file
99
modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxMessageEdit exposing (Model, Msg, init, update, view)
|
||||||
|
|
||||||
|
import Data.BoxContent exposing (MessageData)
|
||||||
|
import Html exposing (Html, div, input, label, text, textarea)
|
||||||
|
import Html.Attributes exposing (autocomplete, class, name, placeholder, type_, value)
|
||||||
|
import Html.Events exposing (onInput)
|
||||||
|
import Messages.Comp.BoxMessageEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ data : MessageData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SetTitle String
|
||||||
|
| SetBody String
|
||||||
|
|
||||||
|
|
||||||
|
init : MessageData -> Model
|
||||||
|
init data =
|
||||||
|
{ data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> ( Model, MessageData )
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
SetTitle str ->
|
||||||
|
let
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | title = str }
|
||||||
|
in
|
||||||
|
( { model | data = data_ }, data_ )
|
||||||
|
|
||||||
|
SetBody str ->
|
||||||
|
let
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | body = str }
|
||||||
|
in
|
||||||
|
( { model | data = data_ }, data_ )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Model -> Html Msg
|
||||||
|
view texts model =
|
||||||
|
div []
|
||||||
|
[ div []
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.titleLabel
|
||||||
|
]
|
||||||
|
, input
|
||||||
|
[ type_ "text"
|
||||||
|
, name "message-title"
|
||||||
|
, autocomplete False
|
||||||
|
, onInput SetTitle
|
||||||
|
, value model.data.title
|
||||||
|
, placeholder texts.titlePlaceholder
|
||||||
|
, class S.textInput
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.bodyLabel
|
||||||
|
]
|
||||||
|
, textarea
|
||||||
|
[ value model.data.body
|
||||||
|
, onInput SetBody
|
||||||
|
, class S.textAreaInput
|
||||||
|
, placeholder texts.bodyPlaceholder
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, div [ class "opacity-75 text-sm mt-1" ]
|
||||||
|
[ text texts.infoText
|
||||||
|
]
|
||||||
|
]
|
197
modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm
Normal file
197
modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxQueryEdit exposing (..)
|
||||||
|
|
||||||
|
import Comp.BoxSearchQueryInput
|
||||||
|
import Comp.IntField
|
||||||
|
import Comp.ItemColumnDropdown
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.Bookmarks
|
||||||
|
import Data.BoxContent exposing (QueryData, SearchQuery(..))
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, label, text)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.BoxQueryEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ data : QueryData
|
||||||
|
, searchQueryModel : Comp.BoxSearchQueryInput.Model
|
||||||
|
, limitModel : Comp.IntField.Model
|
||||||
|
, limitValue : Maybe Int
|
||||||
|
, columnModel : Comp.ItemColumnDropdown.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SearchQueryMsg Comp.BoxSearchQueryInput.Msg
|
||||||
|
| LimitMsg Comp.IntField.Msg
|
||||||
|
| ColumnMsg Comp.ItemColumnDropdown.Msg
|
||||||
|
| ToggleColumnHeaders
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> QueryData -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init flags data =
|
||||||
|
let
|
||||||
|
( qm, qc, qs ) =
|
||||||
|
Comp.BoxSearchQueryInput.init flags data.query Data.Bookmarks.empty
|
||||||
|
|
||||||
|
emptyModel =
|
||||||
|
{ data = data
|
||||||
|
, searchQueryModel = qm
|
||||||
|
, limitModel = Comp.IntField.init (Just 1) Nothing False
|
||||||
|
, limitValue = Just data.limit
|
||||||
|
, columnModel = Comp.ItemColumnDropdown.init data.columns
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( emptyModel, Cmd.map SearchQueryMsg qc, Sub.map SearchQueryMsg qs )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
, data : QueryData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
SearchQueryMsg lm ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.BoxSearchQueryInput.update flags lm model.searchQueryModel
|
||||||
|
|
||||||
|
setData data =
|
||||||
|
{ data | query = Maybe.withDefault data.query result.query }
|
||||||
|
|
||||||
|
nextModel =
|
||||||
|
withData setData { model | searchQueryModel = result.model }
|
||||||
|
in
|
||||||
|
{ model = nextModel
|
||||||
|
, cmd = Cmd.map SearchQueryMsg result.cmd
|
||||||
|
, sub = Sub.map SearchQueryMsg result.sub
|
||||||
|
, data = nextModel.data
|
||||||
|
}
|
||||||
|
|
||||||
|
LimitMsg lm ->
|
||||||
|
let
|
||||||
|
( im, n ) =
|
||||||
|
Comp.IntField.update lm model.limitModel
|
||||||
|
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
case n of
|
||||||
|
Just num ->
|
||||||
|
{ data | limit = num }
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
data
|
||||||
|
in
|
||||||
|
{ model = { model | limitModel = im, limitValue = n, data = data_ }
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, data = data_
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnMsg lm ->
|
||||||
|
let
|
||||||
|
( cm, cc ) =
|
||||||
|
Comp.ItemColumnDropdown.update lm model.columnModel
|
||||||
|
|
||||||
|
selection =
|
||||||
|
Comp.ItemColumnDropdown.getSelected cm
|
||||||
|
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | columns = selection }
|
||||||
|
in
|
||||||
|
{ model = { model | columnModel = cm, data = data_ }
|
||||||
|
, cmd = Cmd.map ColumnMsg cc
|
||||||
|
, sub = Sub.none
|
||||||
|
, data = data_
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleColumnHeaders ->
|
||||||
|
let
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | showHeaders = not data.showHeaders }
|
||||||
|
in
|
||||||
|
{ model = { model | data = data_ }
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, data = data_
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
{ model = model
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, data = model.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
withData : (QueryData -> QueryData) -> Model -> Model
|
||||||
|
withData modify model =
|
||||||
|
{ model | data = modify model.data }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
let
|
||||||
|
limitSettings =
|
||||||
|
{ label = "Limit"
|
||||||
|
, info = "Show this many results."
|
||||||
|
, number = model.limitValue
|
||||||
|
, classes = ""
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ Html.map SearchQueryMsg
|
||||||
|
(Comp.BoxSearchQueryInput.view texts.searchQuery settings model.searchQueryModel)
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ Html.map LimitMsg
|
||||||
|
(Comp.IntField.view limitSettings model.limitModel)
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text "Columns"
|
||||||
|
]
|
||||||
|
, Html.map ColumnMsg
|
||||||
|
(Comp.ItemColumnDropdown.view texts.columnDropdown settings model.columnModel)
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleColumnHeaders
|
||||||
|
, label = texts.showColumnHeaders
|
||||||
|
, value = model.data.showHeaders
|
||||||
|
, id = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
212
modules/webapp/src/main/elm/Comp/BoxQueryView.elm
Normal file
212
modules/webapp/src/main/elm/Comp/BoxQueryView.elm
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxQueryView exposing (Model, Msg, init, reloadData, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.ItemLight exposing (ItemLight)
|
||||||
|
import Api.Model.ItemLightList exposing (ItemLightList)
|
||||||
|
import Api.Model.ItemQuery exposing (ItemQuery)
|
||||||
|
import Comp.Basic
|
||||||
|
import Comp.ItemColumnView
|
||||||
|
import Data.BoxContent exposing (QueryData, SearchQuery(..))
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.ItemColumn as IC exposing (ItemColumn)
|
||||||
|
import Data.Items
|
||||||
|
import Data.SearchMode
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, a, div, i, table, tbody, td, text, th, thead, tr)
|
||||||
|
import Html.Attributes exposing (class, classList)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.BoxQueryView exposing (Texts)
|
||||||
|
import Page exposing (Page(..))
|
||||||
|
import Styles
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ results : ViewResult
|
||||||
|
, meta : QueryData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type ViewResult
|
||||||
|
= Loading
|
||||||
|
| Loaded ItemLightList
|
||||||
|
| Failed Http.Error
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= ItemsResp (Result Http.Error ItemLightList)
|
||||||
|
| ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> QueryData -> ( Model, Cmd Msg )
|
||||||
|
init flags data =
|
||||||
|
( { results = Loading
|
||||||
|
, meta = data
|
||||||
|
}
|
||||||
|
, dataCmd flags data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
reloadData : Msg
|
||||||
|
reloadData =
|
||||||
|
ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Bool )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
ItemsResp (Ok list) ->
|
||||||
|
( { model | results = Loaded list }, Cmd.none, False )
|
||||||
|
|
||||||
|
ItemsResp (Err err) ->
|
||||||
|
( { model | results = Failed err }, Cmd.none, False )
|
||||||
|
|
||||||
|
ReloadData ->
|
||||||
|
( model, dataCmd flags model.meta, True )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
case model.results of
|
||||||
|
Loading ->
|
||||||
|
div [ class "h-24 " ]
|
||||||
|
[ Comp.Basic.loadingDimmer
|
||||||
|
{ label = ""
|
||||||
|
, active = True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Failed err ->
|
||||||
|
div
|
||||||
|
[ class "py-4"
|
||||||
|
, class Styles.errorMessage
|
||||||
|
]
|
||||||
|
[ text texts.errorOccurred
|
||||||
|
, text ": "
|
||||||
|
, text (texts.httpError err)
|
||||||
|
]
|
||||||
|
|
||||||
|
Loaded list ->
|
||||||
|
if list.groups == [] then
|
||||||
|
viewEmpty texts
|
||||||
|
|
||||||
|
else
|
||||||
|
viewItems texts settings model.meta list
|
||||||
|
|
||||||
|
|
||||||
|
viewItems : Texts -> UiSettings -> QueryData -> ItemLightList -> Html Msg
|
||||||
|
viewItems texts settings meta list =
|
||||||
|
let
|
||||||
|
items =
|
||||||
|
Data.Items.flatten list
|
||||||
|
in
|
||||||
|
table [ class "w-full divide-y divide-y-2 dark:divide-slate-500" ]
|
||||||
|
(viewItemHead texts meta ++ [ tbody [ class "divide-y divide-dotted dark:divide-slate-500" ] <| List.map (viewItemRow texts settings meta) items ])
|
||||||
|
|
||||||
|
|
||||||
|
viewItemHead : Texts -> QueryData -> List (Html Msg)
|
||||||
|
viewItemHead texts meta =
|
||||||
|
let
|
||||||
|
( col1, cols ) =
|
||||||
|
getColumns meta
|
||||||
|
in
|
||||||
|
if not meta.showHeaders then
|
||||||
|
[]
|
||||||
|
|
||||||
|
else
|
||||||
|
[ thead []
|
||||||
|
[ tr []
|
||||||
|
(List.map texts.itemColumn.header (col1 :: cols)
|
||||||
|
|> List.map (\n -> th [ class "text-left text-sm" ] [ text n ])
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewItemRow : Texts -> UiSettings -> QueryData -> ItemLight -> Html Msg
|
||||||
|
viewItemRow texts settings meta item =
|
||||||
|
let
|
||||||
|
( col1, cols ) =
|
||||||
|
getColumns meta
|
||||||
|
|
||||||
|
render col =
|
||||||
|
Comp.ItemColumnView.renderDiv texts.templateCtx settings col [ class "flex flex-row space-x-1" ] item
|
||||||
|
|
||||||
|
td1 =
|
||||||
|
td [ class "py-2 px-1" ]
|
||||||
|
[ a
|
||||||
|
[ class Styles.link
|
||||||
|
, Page.href (ItemDetailPage item.id)
|
||||||
|
]
|
||||||
|
[ render col1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
tdRem index col =
|
||||||
|
td
|
||||||
|
[ class "py-2 px-1"
|
||||||
|
, classList [ ( "hidden md:table-cell", index > 1 ) ]
|
||||||
|
]
|
||||||
|
[ render col
|
||||||
|
]
|
||||||
|
in
|
||||||
|
tr []
|
||||||
|
(td1 :: List.indexedMap tdRem cols)
|
||||||
|
|
||||||
|
|
||||||
|
viewEmpty : Texts -> Html Msg
|
||||||
|
viewEmpty texts =
|
||||||
|
div [ class "flex justify-center items-center h-full" ]
|
||||||
|
[ div [ class "px-4 py-4 text-center align-middle text-lg" ]
|
||||||
|
[ i [ class "fa fa-smile font-thin mr-2" ] []
|
||||||
|
, text texts.noResults
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
getColumns : QueryData -> ( ItemColumn, List ItemColumn )
|
||||||
|
getColumns meta =
|
||||||
|
case meta.columns of
|
||||||
|
x :: xs ->
|
||||||
|
( x, xs )
|
||||||
|
|
||||||
|
[] ->
|
||||||
|
( IC.Name, [ IC.Correspondent, IC.DateShort ] )
|
||||||
|
|
||||||
|
|
||||||
|
mkQuery : String -> QueryData -> ItemQuery
|
||||||
|
mkQuery q meta =
|
||||||
|
{ query = q
|
||||||
|
, limit = Just meta.limit
|
||||||
|
, offset = Nothing
|
||||||
|
, searchMode = Just <| Data.SearchMode.asString Data.SearchMode.Normal
|
||||||
|
, withDetails = Just meta.details
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dataCmd : Flags -> QueryData -> Cmd Msg
|
||||||
|
dataCmd flags data =
|
||||||
|
case data.query of
|
||||||
|
SearchQueryString q ->
|
||||||
|
Api.itemSearch flags (mkQuery q data) ItemsResp
|
||||||
|
|
||||||
|
SearchQueryBookmark bmId ->
|
||||||
|
Api.itemSearchBookmark flags (mkQuery bmId data) ItemsResp
|
299
modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm
Normal file
299
modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxSearchQueryInput exposing
|
||||||
|
( Model
|
||||||
|
, Msg
|
||||||
|
, UpdateResult
|
||||||
|
, init
|
||||||
|
, switchToBookmark
|
||||||
|
, switchToQuery
|
||||||
|
, toSearchQuery
|
||||||
|
, update
|
||||||
|
, view
|
||||||
|
)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Comp.BookmarkDropdown
|
||||||
|
import Comp.PowerSearchInput
|
||||||
|
import Data.Bookmarks exposing (AllBookmarks)
|
||||||
|
import Data.BoxContent exposing (SearchQuery(..))
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, input, label, span, text)
|
||||||
|
import Html.Attributes exposing (checked, class, type_)
|
||||||
|
import Html.Events exposing (onCheck)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.BoxSearchQueryInput exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ queryModel : QueryModel
|
||||||
|
, allBookmarks : AllBookmarks
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type QueryModel
|
||||||
|
= Search Comp.PowerSearchInput.Model
|
||||||
|
| Bookmark Comp.BookmarkDropdown.Model
|
||||||
|
|
||||||
|
|
||||||
|
toSearchQuery : Model -> Maybe SearchQuery
|
||||||
|
toSearchQuery model =
|
||||||
|
case model.queryModel of
|
||||||
|
Search pm ->
|
||||||
|
let
|
||||||
|
qstr =
|
||||||
|
Maybe.withDefault "" pm.input
|
||||||
|
in
|
||||||
|
if qstr == "" || Comp.PowerSearchInput.isValid pm then
|
||||||
|
Just (SearchQueryString qstr)
|
||||||
|
|
||||||
|
else
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
Bookmark bm ->
|
||||||
|
Comp.BookmarkDropdown.getSelectedId bm
|
||||||
|
|> Maybe.map SearchQueryBookmark
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= GetBookmarksResp (Result Http.Error AllBookmarks)
|
||||||
|
| BookmarkMsg Comp.BookmarkDropdown.Msg
|
||||||
|
| PowerSearchMsg Comp.PowerSearchInput.Msg
|
||||||
|
| SwitchQueryBookmark
|
||||||
|
| SwitchQuerySearch
|
||||||
|
|
||||||
|
|
||||||
|
switchToBookmark : Msg
|
||||||
|
switchToBookmark =
|
||||||
|
SwitchQueryBookmark
|
||||||
|
|
||||||
|
|
||||||
|
switchToQuery : Msg
|
||||||
|
switchToQuery =
|
||||||
|
SwitchQuerySearch
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> SearchQuery -> AllBookmarks -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init flags query bookmarks =
|
||||||
|
let
|
||||||
|
emptyModel =
|
||||||
|
{ queryModel = Search Comp.PowerSearchInput.init
|
||||||
|
, allBookmarks = bookmarks
|
||||||
|
}
|
||||||
|
in
|
||||||
|
case query of
|
||||||
|
SearchQueryBookmark id ->
|
||||||
|
initQueryBookmark flags emptyModel (Just id)
|
||||||
|
|
||||||
|
SearchQueryString qstr ->
|
||||||
|
initQuerySearch emptyModel qstr
|
||||||
|
|
||||||
|
|
||||||
|
initQueryBookmark : Flags -> Model -> Maybe String -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
initQueryBookmark flags model bookmarkId =
|
||||||
|
( { model
|
||||||
|
| queryModel =
|
||||||
|
Bookmark
|
||||||
|
(Comp.BookmarkDropdown.initWith model.allBookmarks bookmarkId)
|
||||||
|
}
|
||||||
|
, if model.allBookmarks == Data.Bookmarks.empty then
|
||||||
|
Api.getBookmarks flags GetBookmarksResp
|
||||||
|
|
||||||
|
else
|
||||||
|
Cmd.none
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initQuerySearch : Model -> String -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
initQuerySearch model qstr =
|
||||||
|
let
|
||||||
|
( qm, qc, qs ) =
|
||||||
|
Comp.PowerSearchInput.initWith qstr
|
||||||
|
in
|
||||||
|
( { model | queryModel = Search qm }
|
||||||
|
, Cmd.map PowerSearchMsg qc
|
||||||
|
, Sub.map PowerSearchMsg qs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
, query : Maybe SearchQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
GetBookmarksResp (Ok list) ->
|
||||||
|
let
|
||||||
|
bmId =
|
||||||
|
case model.queryModel of
|
||||||
|
Bookmark bm ->
|
||||||
|
Comp.BookmarkDropdown.getSelectedId bm
|
||||||
|
|
||||||
|
Search _ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
nm =
|
||||||
|
{ model | allBookmarks = list }
|
||||||
|
in
|
||||||
|
case model.queryModel of
|
||||||
|
Bookmark _ ->
|
||||||
|
update flags
|
||||||
|
SwitchQueryBookmark
|
||||||
|
{ nm
|
||||||
|
| queryModel =
|
||||||
|
Bookmark (Comp.BookmarkDropdown.initWith model.allBookmarks bmId)
|
||||||
|
}
|
||||||
|
|
||||||
|
Search _ ->
|
||||||
|
unit nm
|
||||||
|
|
||||||
|
GetBookmarksResp (Err _) ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
BookmarkMsg lm ->
|
||||||
|
case model.queryModel of
|
||||||
|
Bookmark m ->
|
||||||
|
let
|
||||||
|
( bm, bc ) =
|
||||||
|
Comp.BookmarkDropdown.update lm m
|
||||||
|
|
||||||
|
nextModel =
|
||||||
|
{ model | queryModel = Bookmark bm }
|
||||||
|
in
|
||||||
|
{ model = nextModel
|
||||||
|
, cmd = Cmd.map BookmarkMsg bc
|
||||||
|
, sub = Sub.none
|
||||||
|
, query = toSearchQuery nextModel
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
PowerSearchMsg lm ->
|
||||||
|
case model.queryModel of
|
||||||
|
Search m ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.PowerSearchInput.update lm m
|
||||||
|
|
||||||
|
nextModel =
|
||||||
|
{ model | queryModel = Search result.model }
|
||||||
|
in
|
||||||
|
{ model = nextModel
|
||||||
|
, cmd = Cmd.map PowerSearchMsg result.cmd
|
||||||
|
, sub = Sub.map PowerSearchMsg result.subs
|
||||||
|
, query = toSearchQuery nextModel
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
SwitchQueryBookmark ->
|
||||||
|
let
|
||||||
|
selected =
|
||||||
|
case toSearchQuery model of
|
||||||
|
Just (SearchQueryBookmark id) ->
|
||||||
|
Just id
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
( m, c, s ) =
|
||||||
|
initQueryBookmark flags model selected
|
||||||
|
in
|
||||||
|
UpdateResult m c s (toSearchQuery m)
|
||||||
|
|
||||||
|
SwitchQuerySearch ->
|
||||||
|
let
|
||||||
|
qstr =
|
||||||
|
case toSearchQuery model of
|
||||||
|
Just (SearchQueryString q) ->
|
||||||
|
q
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
""
|
||||||
|
|
||||||
|
( m, c, s ) =
|
||||||
|
initQuerySearch model qstr
|
||||||
|
in
|
||||||
|
UpdateResult m c s (toSearchQuery m)
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
UpdateResult model Cmd.none Sub.none Nothing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
let
|
||||||
|
( isBookmark, isQuery ) =
|
||||||
|
case model.queryModel of
|
||||||
|
Bookmark _ ->
|
||||||
|
( True, False )
|
||||||
|
|
||||||
|
Search _ ->
|
||||||
|
( False, True )
|
||||||
|
|
||||||
|
searchSettings =
|
||||||
|
{ placeholder = texts.searchPlaceholder
|
||||||
|
, extraAttrs = []
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "flex flex-row space-x-4" ]
|
||||||
|
[ label [ class "inline-flex items-center" ]
|
||||||
|
[ input
|
||||||
|
[ type_ "radio"
|
||||||
|
, checked isBookmark
|
||||||
|
, onCheck (\_ -> SwitchQueryBookmark)
|
||||||
|
, class S.radioInput
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, span [ class "ml-2" ] [ text texts.switchToBookmark ]
|
||||||
|
]
|
||||||
|
, label [ class "inline-flex items-center" ]
|
||||||
|
[ input
|
||||||
|
[ type_ "radio"
|
||||||
|
, checked isQuery
|
||||||
|
, onCheck (\_ -> SwitchQuerySearch)
|
||||||
|
, class S.radioInput
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, span [ class "ml-2" ] [ text texts.switchToQuery ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, case model.queryModel of
|
||||||
|
Bookmark m ->
|
||||||
|
Html.map BookmarkMsg
|
||||||
|
(Comp.BookmarkDropdown.view texts.bookmarkDropdown settings m)
|
||||||
|
|
||||||
|
Search m ->
|
||||||
|
div [ class "relative" ]
|
||||||
|
[ Html.map PowerSearchMsg
|
||||||
|
(Comp.PowerSearchInput.viewInput searchSettings m)
|
||||||
|
, Html.map PowerSearchMsg
|
||||||
|
(Comp.PowerSearchInput.viewResult [] m)
|
||||||
|
]
|
||||||
|
]
|
202
modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm
Normal file
202
modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxStatsEdit exposing (..)
|
||||||
|
|
||||||
|
import Comp.BoxSearchQueryInput
|
||||||
|
import Comp.FixedDropdown
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.Bookmarks
|
||||||
|
import Data.BoxContent exposing (QueryData, SearchQuery(..), StatsData, SummaryShow(..))
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, label, span, text)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.BoxStatsEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ data : StatsData
|
||||||
|
, searchQueryModel : Comp.BoxSearchQueryInput.Model
|
||||||
|
, showModel : Comp.FixedDropdown.Model SummaryShowLabel
|
||||||
|
, summaryShow : SummaryShow
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SearchQueryMsg Comp.BoxSearchQueryInput.Msg
|
||||||
|
| ShowMsg (Comp.FixedDropdown.Msg SummaryShowLabel)
|
||||||
|
| ToggleItemCountVisible
|
||||||
|
|
||||||
|
|
||||||
|
type SummaryShowLabel
|
||||||
|
= ShowFields
|
||||||
|
| ShowGeneric
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> StatsData -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init flags data =
|
||||||
|
let
|
||||||
|
( qm, qc, qs ) =
|
||||||
|
Comp.BoxSearchQueryInput.init flags data.query Data.Bookmarks.empty
|
||||||
|
|
||||||
|
emptyModel =
|
||||||
|
{ data = data
|
||||||
|
, searchQueryModel = qm
|
||||||
|
, showModel =
|
||||||
|
Comp.FixedDropdown.init
|
||||||
|
[ ShowFields, ShowGeneric ]
|
||||||
|
, summaryShow = data.show
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( emptyModel, Cmd.map SearchQueryMsg qc, Sub.map SearchQueryMsg qs )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
, data : StatsData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
SearchQueryMsg lm ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.BoxSearchQueryInput.update flags lm model.searchQueryModel
|
||||||
|
|
||||||
|
setData data =
|
||||||
|
{ data | query = Maybe.withDefault data.query result.query }
|
||||||
|
|
||||||
|
nextModel =
|
||||||
|
withData setData { model | searchQueryModel = result.model }
|
||||||
|
in
|
||||||
|
{ model = nextModel
|
||||||
|
, cmd = Cmd.map SearchQueryMsg result.cmd
|
||||||
|
, sub = Sub.map SearchQueryMsg result.sub
|
||||||
|
, data = nextModel.data
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowMsg lm ->
|
||||||
|
let
|
||||||
|
( mm, sel ) =
|
||||||
|
Comp.FixedDropdown.update lm model.showModel
|
||||||
|
|
||||||
|
nextShow =
|
||||||
|
case ( model.summaryShow, sel ) of
|
||||||
|
( SummaryShowFields _, Just ShowGeneric ) ->
|
||||||
|
SummaryShowGeneral
|
||||||
|
|
||||||
|
( SummaryShowGeneral, Just ShowFields ) ->
|
||||||
|
SummaryShowFields False
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
model.summaryShow
|
||||||
|
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | show = nextShow }
|
||||||
|
in
|
||||||
|
unit { model | showModel = mm, summaryShow = nextShow, data = data_ }
|
||||||
|
|
||||||
|
ToggleItemCountVisible ->
|
||||||
|
let
|
||||||
|
nextShow =
|
||||||
|
case model.summaryShow of
|
||||||
|
SummaryShowFields flag ->
|
||||||
|
SummaryShowFields (not flag)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
model.summaryShow
|
||||||
|
|
||||||
|
data =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
data_ =
|
||||||
|
{ data | show = nextShow }
|
||||||
|
in
|
||||||
|
unit { model | summaryShow = nextShow, data = data_ }
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
{ model = model
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, sub = Sub.none
|
||||||
|
, data = model.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
withData : (StatsData -> StatsData) -> Model -> Model
|
||||||
|
withData modify model =
|
||||||
|
{ model | data = modify model.data }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
let
|
||||||
|
showSettings =
|
||||||
|
{ display =
|
||||||
|
\a ->
|
||||||
|
case a of
|
||||||
|
ShowFields ->
|
||||||
|
texts.fieldStatistics
|
||||||
|
|
||||||
|
ShowGeneric ->
|
||||||
|
texts.basicNumbers
|
||||||
|
, icon = \_ -> Nothing
|
||||||
|
, selectPlaceholder = ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
showLabel =
|
||||||
|
case model.summaryShow of
|
||||||
|
SummaryShowFields _ ->
|
||||||
|
ShowFields
|
||||||
|
|
||||||
|
SummaryShowGeneral ->
|
||||||
|
ShowGeneric
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ Html.map SearchQueryMsg
|
||||||
|
(Comp.BoxSearchQueryInput.view texts.searchQuery settings model.searchQueryModel)
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.showLabel ]
|
||||||
|
, Html.map ShowMsg
|
||||||
|
(Comp.FixedDropdown.viewStyled2 showSettings False (Just showLabel) model.showModel)
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ case model.summaryShow of
|
||||||
|
SummaryShowGeneral ->
|
||||||
|
span [ class "hidden" ] []
|
||||||
|
|
||||||
|
SummaryShowFields itemCountVisible ->
|
||||||
|
MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleItemCountVisible
|
||||||
|
, label = texts.showItemCount
|
||||||
|
, id = ""
|
||||||
|
, value = itemCountVisible
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
186
modules/webapp/src/main/elm/Comp/BoxStatsView.elm
Normal file
186
modules/webapp/src/main/elm/Comp/BoxStatsView.elm
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxStatsView exposing (Model, Msg, init, reloadData, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.ItemQuery exposing (ItemQuery)
|
||||||
|
import Api.Model.SearchStats exposing (SearchStats)
|
||||||
|
import Comp.Basic
|
||||||
|
import Comp.SearchStatsView
|
||||||
|
import Data.BoxContent exposing (SearchQuery(..), StatsData, SummaryShow(..))
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Html exposing (Html, div, text)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.BoxStatsView exposing (Texts)
|
||||||
|
import Styles
|
||||||
|
import Util.List
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ results : ViewResult
|
||||||
|
, meta : StatsData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type ViewResult
|
||||||
|
= Loading
|
||||||
|
| Loaded SearchStats
|
||||||
|
| Failed Http.Error
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= StatsResp (Result Http.Error SearchStats)
|
||||||
|
| ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> StatsData -> ( Model, Cmd Msg )
|
||||||
|
init flags data =
|
||||||
|
( { results = Loading
|
||||||
|
, meta = data
|
||||||
|
}
|
||||||
|
, dataCmd flags data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
reloadData : Msg
|
||||||
|
reloadData =
|
||||||
|
ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Bool )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
StatsResp (Ok stats) ->
|
||||||
|
( { model | results = Loaded stats }, Cmd.none, False )
|
||||||
|
|
||||||
|
StatsResp (Err err) ->
|
||||||
|
( { model | results = Failed err }, Cmd.none, False )
|
||||||
|
|
||||||
|
ReloadData ->
|
||||||
|
( model, dataCmd flags model.meta, True )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Model -> Html Msg
|
||||||
|
view texts model =
|
||||||
|
case model.results of
|
||||||
|
Loading ->
|
||||||
|
div [ class "h-24 " ]
|
||||||
|
[ Comp.Basic.loadingDimmer
|
||||||
|
{ label = ""
|
||||||
|
, active = True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Failed err ->
|
||||||
|
div
|
||||||
|
[ class "py-4"
|
||||||
|
, class Styles.errorMessage
|
||||||
|
]
|
||||||
|
[ text texts.errorOccurred
|
||||||
|
, text ": "
|
||||||
|
, text (texts.httpError err)
|
||||||
|
]
|
||||||
|
|
||||||
|
Loaded stats ->
|
||||||
|
viewStats texts model stats
|
||||||
|
|
||||||
|
|
||||||
|
viewStats : Texts -> Model -> SearchStats -> Html Msg
|
||||||
|
viewStats texts model stats =
|
||||||
|
case model.meta.show of
|
||||||
|
SummaryShowFields flag ->
|
||||||
|
Comp.SearchStatsView.view2
|
||||||
|
texts.statsView
|
||||||
|
flag
|
||||||
|
""
|
||||||
|
stats
|
||||||
|
|
||||||
|
SummaryShowGeneral ->
|
||||||
|
viewGeneral texts stats
|
||||||
|
|
||||||
|
|
||||||
|
viewGeneral : Texts -> SearchStats -> Html Msg
|
||||||
|
viewGeneral texts stats =
|
||||||
|
let
|
||||||
|
tagCount =
|
||||||
|
List.length stats.tagCloud.items
|
||||||
|
|
||||||
|
fieldCount =
|
||||||
|
List.length stats.fieldStats
|
||||||
|
|
||||||
|
orgCount =
|
||||||
|
List.length stats.corrOrgStats
|
||||||
|
|
||||||
|
persCount =
|
||||||
|
(stats.corrPersStats ++ stats.concPersStats)
|
||||||
|
|> List.map (.ref >> .id)
|
||||||
|
|> Util.List.distinct
|
||||||
|
|> List.length
|
||||||
|
|
||||||
|
equipCount =
|
||||||
|
List.length stats.concEquipStats
|
||||||
|
|
||||||
|
mklabel name =
|
||||||
|
div [ class "py-0.5 text-lg" ] [ text name ]
|
||||||
|
|
||||||
|
value num =
|
||||||
|
div [ class "py-0.5 font-mono text-lg" ] [ text <| String.fromInt num ]
|
||||||
|
in
|
||||||
|
div [ class "opacity-90" ]
|
||||||
|
[ div [ class "flex flex-row" ]
|
||||||
|
[ div [ class "flex flex-col mr-4" ]
|
||||||
|
[ mklabel texts.basics.items
|
||||||
|
, mklabel texts.basics.tags
|
||||||
|
, mklabel texts.basics.customFields
|
||||||
|
, mklabel texts.basics.organization
|
||||||
|
, mklabel texts.basics.person
|
||||||
|
, mklabel texts.basics.equipment
|
||||||
|
]
|
||||||
|
, div [ class "flex flex-col" ]
|
||||||
|
[ value stats.count
|
||||||
|
, value tagCount
|
||||||
|
, value fieldCount
|
||||||
|
, value orgCount
|
||||||
|
, value persCount
|
||||||
|
, value equipCount
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
mkQuery : String -> ItemQuery
|
||||||
|
mkQuery query =
|
||||||
|
{ query = query
|
||||||
|
, limit = Nothing
|
||||||
|
, offset = Nothing
|
||||||
|
, searchMode = Nothing
|
||||||
|
, withDetails = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dataCmd : Flags -> StatsData -> Cmd Msg
|
||||||
|
dataCmd flags data =
|
||||||
|
case data.query of
|
||||||
|
SearchQueryString q ->
|
||||||
|
Api.itemSearchStats flags (mkQuery q) StatsResp
|
||||||
|
|
||||||
|
SearchQueryBookmark bmId ->
|
||||||
|
Api.itemSearchStatsBookmark flags (mkQuery bmId) StatsResp
|
113
modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm
Normal file
113
modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxUploadEdit exposing (..)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.Source exposing (Source)
|
||||||
|
import Api.Model.SourceList exposing (SourceList)
|
||||||
|
import Comp.BoxUploadView exposing (Msg)
|
||||||
|
import Comp.FixedDropdown
|
||||||
|
import Data.BoxContent exposing (UploadData)
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Html exposing (Html, div, label, text)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.BoxUploadEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ data : UploadData
|
||||||
|
, allSources : List Source
|
||||||
|
, sourceModel : Comp.FixedDropdown.Model Source
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= GetSourcesResp (Result Http.Error SourceList)
|
||||||
|
| SourceMsg (Comp.FixedDropdown.Msg Source)
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> UploadData -> ( Model, Cmd Msg )
|
||||||
|
init flags data =
|
||||||
|
( { data = data
|
||||||
|
, allSources = []
|
||||||
|
, sourceModel = Comp.FixedDropdown.init []
|
||||||
|
}
|
||||||
|
, Api.getSources flags GetSourcesResp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> ( Model, UploadData )
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
GetSourcesResp (Ok list) ->
|
||||||
|
let
|
||||||
|
all =
|
||||||
|
List.map .source list.items
|
||||||
|
|> List.filter .enabled
|
||||||
|
|
||||||
|
dm =
|
||||||
|
Comp.FixedDropdown.init all
|
||||||
|
in
|
||||||
|
( { model | allSources = all, sourceModel = dm }
|
||||||
|
, model.data
|
||||||
|
)
|
||||||
|
|
||||||
|
GetSourcesResp (Err _) ->
|
||||||
|
( model, model.data )
|
||||||
|
|
||||||
|
SourceMsg lm ->
|
||||||
|
let
|
||||||
|
( dm, sel ) =
|
||||||
|
Comp.FixedDropdown.update lm model.sourceModel
|
||||||
|
|
||||||
|
ud =
|
||||||
|
model.data
|
||||||
|
|
||||||
|
ud_ =
|
||||||
|
{ ud | sourceId = Maybe.map .id sel }
|
||||||
|
in
|
||||||
|
( { model | sourceModel = dm, data = ud_ }, ud_ )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Model -> Html Msg
|
||||||
|
view texts model =
|
||||||
|
let
|
||||||
|
cfg =
|
||||||
|
{ display = \s -> s.abbrev
|
||||||
|
, icon = \_ -> Nothing
|
||||||
|
, selectPlaceholder = texts.sourcePlaceholder
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
selected =
|
||||||
|
List.filter (\e -> Just e.id == model.data.sourceId) model.allSources
|
||||||
|
|> List.head
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ div []
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.sourceLabel
|
||||||
|
]
|
||||||
|
, Html.map SourceMsg
|
||||||
|
(Comp.FixedDropdown.viewStyled2 cfg False selected model.sourceModel)
|
||||||
|
]
|
||||||
|
, div [ class "mt-1 opacity-75 text-sm" ]
|
||||||
|
[ text texts.infoText
|
||||||
|
]
|
||||||
|
]
|
70
modules/webapp/src/main/elm/Comp/BoxUploadView.elm
Normal file
70
modules/webapp/src/main/elm/Comp/BoxUploadView.elm
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxUploadView exposing (..)
|
||||||
|
|
||||||
|
import Comp.UploadForm
|
||||||
|
import Data.BoxContent exposing (UploadData)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.BoxUploadView exposing (Texts)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ uploadForm : Comp.UploadForm.Model
|
||||||
|
, sourceId : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= UploadMsg Comp.UploadForm.Msg
|
||||||
|
|
||||||
|
|
||||||
|
init : UploadData -> Model
|
||||||
|
init data =
|
||||||
|
{ uploadForm = Comp.UploadForm.init
|
||||||
|
, sourceId = data.sourceId
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
UploadMsg lm ->
|
||||||
|
let
|
||||||
|
( um, uc, us ) =
|
||||||
|
Comp.UploadForm.update model.sourceId flags lm model.uploadForm
|
||||||
|
in
|
||||||
|
( { model | uploadForm = um }
|
||||||
|
, Cmd.map UploadMsg uc
|
||||||
|
, Sub.map UploadMsg us
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags settings model =
|
||||||
|
let
|
||||||
|
viewCfg =
|
||||||
|
{ sourceId = model.sourceId
|
||||||
|
, showForm = False
|
||||||
|
, lightForm = True
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "" ]
|
||||||
|
[ Html.map UploadMsg
|
||||||
|
(Comp.UploadForm.view texts.uploadForm viewCfg flags settings model.uploadForm)
|
||||||
|
]
|
247
modules/webapp/src/main/elm/Comp/BoxView.elm
Normal file
247
modules/webapp/src/main/elm/Comp/BoxView.elm
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.BoxView exposing (..)
|
||||||
|
|
||||||
|
import Comp.BoxQueryView
|
||||||
|
import Comp.BoxStatsView
|
||||||
|
import Comp.BoxUploadView
|
||||||
|
import Data.Box exposing (Box)
|
||||||
|
import Data.BoxContent exposing (BoxContent(..), MessageData)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, i, text)
|
||||||
|
import Html.Attributes exposing (class, classList)
|
||||||
|
import Markdown
|
||||||
|
import Messages.Comp.BoxView exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ box : Box
|
||||||
|
, content : ContentModel
|
||||||
|
, reloading : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type ContentModel
|
||||||
|
= ContentMessage Data.BoxContent.MessageData
|
||||||
|
| ContentUpload Comp.BoxUploadView.Model
|
||||||
|
| ContentQuery Comp.BoxQueryView.Model
|
||||||
|
| ContentStats Comp.BoxStatsView.Model
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= QueryMsg Comp.BoxQueryView.Msg
|
||||||
|
| StatsMsg Comp.BoxStatsView.Msg
|
||||||
|
| UploadMsg Comp.BoxUploadView.Msg
|
||||||
|
| ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> Box -> ( Model, Cmd Msg )
|
||||||
|
init flags box =
|
||||||
|
let
|
||||||
|
( cm, cc ) =
|
||||||
|
contentInit flags box.content
|
||||||
|
in
|
||||||
|
( { box = box
|
||||||
|
, content = cm
|
||||||
|
, reloading = False
|
||||||
|
}
|
||||||
|
, cc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
reloadData : Msg
|
||||||
|
reloadData =
|
||||||
|
ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
contentInit : Flags -> BoxContent -> ( ContentModel, Cmd Msg )
|
||||||
|
contentInit flags content =
|
||||||
|
case content of
|
||||||
|
BoxMessage data ->
|
||||||
|
( ContentMessage data, Cmd.none )
|
||||||
|
|
||||||
|
BoxUpload data ->
|
||||||
|
let
|
||||||
|
qm =
|
||||||
|
Comp.BoxUploadView.init data
|
||||||
|
in
|
||||||
|
( ContentUpload qm, Cmd.none )
|
||||||
|
|
||||||
|
BoxQuery data ->
|
||||||
|
let
|
||||||
|
( qm, qc ) =
|
||||||
|
Comp.BoxQueryView.init flags data
|
||||||
|
in
|
||||||
|
( ContentQuery qm, Cmd.map QueryMsg qc )
|
||||||
|
|
||||||
|
BoxStats data ->
|
||||||
|
let
|
||||||
|
( sm, sc ) =
|
||||||
|
Comp.BoxStatsView.init flags data
|
||||||
|
in
|
||||||
|
( ContentStats sm, Cmd.map StatsMsg sc )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
QueryMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentQuery qm ->
|
||||||
|
let
|
||||||
|
( cm, cc, reloading ) =
|
||||||
|
Comp.BoxQueryView.update flags lm qm
|
||||||
|
in
|
||||||
|
( { model | content = ContentQuery cm, reloading = reloading }
|
||||||
|
, Cmd.map QueryMsg cc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
StatsMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentStats qm ->
|
||||||
|
let
|
||||||
|
( cm, cc, reloading ) =
|
||||||
|
Comp.BoxStatsView.update flags lm qm
|
||||||
|
in
|
||||||
|
( { model | content = ContentStats cm, reloading = reloading }
|
||||||
|
, Cmd.map StatsMsg cc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
UploadMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
ContentUpload qm ->
|
||||||
|
let
|
||||||
|
( cm, cc, cs ) =
|
||||||
|
Comp.BoxUploadView.update flags lm qm
|
||||||
|
in
|
||||||
|
( { model | content = ContentUpload cm }
|
||||||
|
, Cmd.map UploadMsg cc
|
||||||
|
, Sub.map UploadMsg cs
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
ReloadData ->
|
||||||
|
case model.content of
|
||||||
|
ContentQuery _ ->
|
||||||
|
update flags (QueryMsg Comp.BoxQueryView.reloadData) model
|
||||||
|
|
||||||
|
ContentStats _ ->
|
||||||
|
update flags (StatsMsg Comp.BoxStatsView.reloadData) model
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
unit model =
|
||||||
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags settings model =
|
||||||
|
div
|
||||||
|
[ classList [ ( S.box ++ "rounded", model.box.decoration ) ]
|
||||||
|
, class (spanStyle model.box)
|
||||||
|
, class "relative h-full"
|
||||||
|
, classList [ ( "hidden", not model.box.visible ) ]
|
||||||
|
]
|
||||||
|
[ boxLoading model
|
||||||
|
, boxHeader model
|
||||||
|
, div [ class "px-2 py-1 h-5/6" ]
|
||||||
|
[ boxContent texts flags settings model
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
boxLoading : Model -> Html Msg
|
||||||
|
boxLoading model =
|
||||||
|
if not model.reloading then
|
||||||
|
div [ class "hidden" ] []
|
||||||
|
|
||||||
|
else
|
||||||
|
div [ class "absolute right-0 top-1 h-6 w-6" ]
|
||||||
|
[ i [ class "fa fa-spinner animate-spin" ] []
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
boxHeader : Model -> Html Msg
|
||||||
|
boxHeader model =
|
||||||
|
div
|
||||||
|
[ class "flex flex-row py-1 bg-blue-50 dark:bg-slate-700 rounded-t"
|
||||||
|
, classList [ ( "hidden", not model.box.decoration || model.box.name == "" ) ]
|
||||||
|
]
|
||||||
|
[ div [ class "flex text-lg tracking-medium italic px-2" ]
|
||||||
|
[ text model.box.name
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
boxContent : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
boxContent texts flags settings model =
|
||||||
|
case model.content of
|
||||||
|
ContentMessage m ->
|
||||||
|
messageContent m
|
||||||
|
|
||||||
|
ContentUpload qm ->
|
||||||
|
Html.map UploadMsg
|
||||||
|
(Comp.BoxUploadView.view texts.uploadView flags settings qm)
|
||||||
|
|
||||||
|
ContentQuery qm ->
|
||||||
|
Html.map QueryMsg
|
||||||
|
(Comp.BoxQueryView.view texts.queryView settings qm)
|
||||||
|
|
||||||
|
ContentStats qm ->
|
||||||
|
Html.map StatsMsg
|
||||||
|
(Comp.BoxStatsView.view texts.statsView qm)
|
||||||
|
|
||||||
|
|
||||||
|
spanStyle : Box -> String
|
||||||
|
spanStyle box =
|
||||||
|
case box.colspan of
|
||||||
|
1 ->
|
||||||
|
""
|
||||||
|
|
||||||
|
2 ->
|
||||||
|
"col-span-1 md:col-span-2"
|
||||||
|
|
||||||
|
3 ->
|
||||||
|
"col-span-1 md:col-span-3"
|
||||||
|
|
||||||
|
4 ->
|
||||||
|
"col-span-1 md:col-span-4"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"col-span-1 md:col-span-5"
|
||||||
|
|
||||||
|
|
||||||
|
messageContent : MessageData -> Html msg
|
||||||
|
messageContent data =
|
||||||
|
div [ class "markdown-preview" ]
|
||||||
|
[ Markdown.toHtml [] data.title
|
||||||
|
, Markdown.toHtml [] data.body
|
||||||
|
]
|
512
modules/webapp/src/main/elm/Comp/DashboardEdit.elm
Normal file
512
modules/webapp/src/main/elm/Comp/DashboardEdit.elm
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.DashboardEdit exposing (Model, Msg, getBoard, init, update, view, viewBox)
|
||||||
|
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.BoxEdit
|
||||||
|
import Comp.FixedDropdown
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.AccountScope exposing (AccountScope)
|
||||||
|
import Data.Box exposing (Box)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Html exposing (Html, div, i, input, label, span, text)
|
||||||
|
import Html.Attributes exposing (checked, class, classList, href, placeholder, type_, value)
|
||||||
|
import Html.Events exposing (onCheck, onClick, onInput)
|
||||||
|
import Html5.DragDrop as DD
|
||||||
|
import Messages.Comp.DashboardEdit exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
import Util.Maybe
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ dashboard : Dashboard
|
||||||
|
, boxModels : Dict Int Comp.BoxEdit.Model
|
||||||
|
, nameValue : String
|
||||||
|
, columnsModel : Comp.FixedDropdown.Model Int
|
||||||
|
, columnsValue : Maybe Int
|
||||||
|
, gapModel : Comp.FixedDropdown.Model Int
|
||||||
|
, gapValue : Maybe Int
|
||||||
|
, defaultDashboard : Bool
|
||||||
|
, scope : AccountScope
|
||||||
|
, newBoxMenuOpen : Bool
|
||||||
|
, boxDragDrop : DD.Model Int Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= BoxMsg Int Comp.BoxEdit.Msg
|
||||||
|
| SetName String
|
||||||
|
| ColumnsMsg (Comp.FixedDropdown.Msg Int)
|
||||||
|
| GapMsg (Comp.FixedDropdown.Msg Int)
|
||||||
|
| ToggleNewBoxMenu
|
||||||
|
| SetScope AccountScope
|
||||||
|
| ToggleDefault
|
||||||
|
| PrependNew Box
|
||||||
|
| DragDropMsg (DD.Msg Int Int)
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> Dashboard -> AccountScope -> Bool -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init flags db scope default =
|
||||||
|
let
|
||||||
|
( boxModels, cmdsAndSubs ) =
|
||||||
|
List.map (Comp.BoxEdit.init flags) db.boxes
|
||||||
|
|> List.indexedMap
|
||||||
|
(\a ->
|
||||||
|
\( bm, bc, bs ) ->
|
||||||
|
( bm, ( Cmd.map (BoxMsg a) bc, Sub.map (BoxMsg a) bs ) )
|
||||||
|
)
|
||||||
|
|> List.unzip
|
||||||
|
|
||||||
|
( cmds, subs ) =
|
||||||
|
List.unzip cmdsAndSubs
|
||||||
|
in
|
||||||
|
( { dashboard = db
|
||||||
|
, nameValue = db.name
|
||||||
|
, columnsModel = Comp.FixedDropdown.init [ 1, 2, 3, 4, 5 ]
|
||||||
|
, columnsValue = Just db.columns
|
||||||
|
, gapModel = Comp.FixedDropdown.init (List.range 0 12)
|
||||||
|
, gapValue = Just db.gap
|
||||||
|
, defaultDashboard = default
|
||||||
|
, scope = scope
|
||||||
|
, newBoxMenuOpen = False
|
||||||
|
, boxModels =
|
||||||
|
List.indexedMap Tuple.pair boxModels
|
||||||
|
|> Dict.fromList
|
||||||
|
, boxDragDrop = DD.init
|
||||||
|
}
|
||||||
|
, Cmd.batch cmds
|
||||||
|
, Sub.batch subs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
getBoard : Model -> ( Dashboard, AccountScope, Bool )
|
||||||
|
getBoard model =
|
||||||
|
( model.dashboard, model.scope, model.defaultDashboard )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
BoxMsg index lm ->
|
||||||
|
case Dict.get index model.boxModels of
|
||||||
|
Just bm ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.BoxEdit.update flags lm bm
|
||||||
|
|
||||||
|
newBoxes =
|
||||||
|
applyBoxAction index result.action <|
|
||||||
|
Dict.insert index result.model model.boxModels
|
||||||
|
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | boxes = List.map .box (Dict.values newBoxes) }
|
||||||
|
in
|
||||||
|
{ model = { model | boxModels = newBoxes, dashboard = db_ }
|
||||||
|
, cmd = Cmd.map (BoxMsg index) result.cmd
|
||||||
|
, sub = Sub.map (BoxMsg index) result.sub
|
||||||
|
}
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
SetName str ->
|
||||||
|
let
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | name = String.trim str }
|
||||||
|
in
|
||||||
|
unit { model | dashboard = db_, nameValue = str }
|
||||||
|
|
||||||
|
ColumnsMsg lm ->
|
||||||
|
let
|
||||||
|
( cm, value ) =
|
||||||
|
Comp.FixedDropdown.update lm model.columnsModel
|
||||||
|
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | columns = Maybe.withDefault db.columns value }
|
||||||
|
in
|
||||||
|
unit
|
||||||
|
{ model
|
||||||
|
| columnsValue = Util.Maybe.or [ value, model.columnsValue ]
|
||||||
|
, columnsModel = cm
|
||||||
|
, dashboard = db_
|
||||||
|
}
|
||||||
|
|
||||||
|
GapMsg lm ->
|
||||||
|
let
|
||||||
|
( gm, value ) =
|
||||||
|
Comp.FixedDropdown.update lm model.gapModel
|
||||||
|
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | gap = Maybe.withDefault db.gap value }
|
||||||
|
in
|
||||||
|
unit
|
||||||
|
{ model
|
||||||
|
| gapModel = gm
|
||||||
|
, gapValue = Util.Maybe.or [ value, model.gapValue ]
|
||||||
|
, dashboard = db_
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleNewBoxMenu ->
|
||||||
|
unit { model | newBoxMenuOpen = not model.newBoxMenuOpen }
|
||||||
|
|
||||||
|
PrependNew box ->
|
||||||
|
let
|
||||||
|
min =
|
||||||
|
Dict.keys model.boxModels
|
||||||
|
|> List.minimum
|
||||||
|
|> Maybe.withDefault 1
|
||||||
|
|
||||||
|
index =
|
||||||
|
min - 1
|
||||||
|
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | boxes = box :: db.boxes }
|
||||||
|
|
||||||
|
( bm, bc, bs ) =
|
||||||
|
Comp.BoxEdit.init flags box
|
||||||
|
|
||||||
|
newBoxes =
|
||||||
|
Dict.insert index bm model.boxModels
|
||||||
|
in
|
||||||
|
{ model = { model | boxModels = newBoxes, dashboard = db_, newBoxMenuOpen = False }
|
||||||
|
, cmd = Cmd.map (BoxMsg index) bc
|
||||||
|
, sub = Sub.map (BoxMsg index) bs
|
||||||
|
}
|
||||||
|
|
||||||
|
DragDropMsg lm ->
|
||||||
|
let
|
||||||
|
( dm, dropped ) =
|
||||||
|
DD.update lm model.boxDragDrop
|
||||||
|
|
||||||
|
m_ =
|
||||||
|
{ model | boxDragDrop = dm }
|
||||||
|
|
||||||
|
nextModel =
|
||||||
|
case dropped of
|
||||||
|
Just ( dragId, dropId, _ ) ->
|
||||||
|
applyDrop dragId dropId m_
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
m_
|
||||||
|
in
|
||||||
|
unit nextModel
|
||||||
|
|
||||||
|
SetScope s ->
|
||||||
|
unit { model | scope = s }
|
||||||
|
|
||||||
|
ToggleDefault ->
|
||||||
|
unit { model | defaultDashboard = not model.defaultDashboard }
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
UpdateResult model Cmd.none Sub.none
|
||||||
|
|
||||||
|
|
||||||
|
applyBoxAction :
|
||||||
|
Int
|
||||||
|
-> Comp.BoxEdit.BoxAction
|
||||||
|
-> Dict Int Comp.BoxEdit.Model
|
||||||
|
-> Dict Int Comp.BoxEdit.Model
|
||||||
|
applyBoxAction index action boxes =
|
||||||
|
let
|
||||||
|
swap n1 n2 =
|
||||||
|
Maybe.map2
|
||||||
|
(\e1 -> \e2 -> Dict.insert n2 e1 boxes |> Dict.insert n1 e2)
|
||||||
|
(Dict.get n1 boxes)
|
||||||
|
(Dict.get n2 boxes)
|
||||||
|
|> Maybe.withDefault boxes
|
||||||
|
in
|
||||||
|
case action of
|
||||||
|
Comp.BoxEdit.BoxNoAction ->
|
||||||
|
boxes
|
||||||
|
|
||||||
|
Comp.BoxEdit.BoxDelete ->
|
||||||
|
Dict.remove index boxes
|
||||||
|
|
||||||
|
Comp.BoxEdit.BoxMoveLeft ->
|
||||||
|
swap (index - 1) index
|
||||||
|
|
||||||
|
Comp.BoxEdit.BoxMoveRight ->
|
||||||
|
swap index (index + 1)
|
||||||
|
|
||||||
|
|
||||||
|
applyDrop : Int -> Int -> Model -> Model
|
||||||
|
applyDrop dragId dropId model =
|
||||||
|
let
|
||||||
|
dragEl =
|
||||||
|
Dict.get dragId model.boxModels
|
||||||
|
in
|
||||||
|
if dragId == dropId then
|
||||||
|
model
|
||||||
|
|
||||||
|
else
|
||||||
|
case dragEl of
|
||||||
|
Just box ->
|
||||||
|
let
|
||||||
|
withoutDragged =
|
||||||
|
Dict.remove dragId model.boxModels
|
||||||
|
|
||||||
|
( begin, end ) =
|
||||||
|
Dict.partition (\k -> \_ -> k < dropId) withoutDragged
|
||||||
|
|
||||||
|
incKeys =
|
||||||
|
Dict.toList end
|
||||||
|
|> List.map (\( k, v ) -> ( k + 1, v ))
|
||||||
|
|> Dict.fromList
|
||||||
|
|
||||||
|
newBoxes =
|
||||||
|
Dict.insert dropId box (Dict.union begin incKeys)
|
||||||
|
|
||||||
|
db =
|
||||||
|
model.dashboard
|
||||||
|
|
||||||
|
db_ =
|
||||||
|
{ db | boxes = List.map .box (Dict.values newBoxes) }
|
||||||
|
in
|
||||||
|
{ model | boxModels = newBoxes, dashboard = db_ }
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags settings model =
|
||||||
|
let
|
||||||
|
boxMenuItem box =
|
||||||
|
{ icon = i [ class (Data.Box.boxIcon box) ] []
|
||||||
|
, label = texts.boxContent.forContent box.content
|
||||||
|
, disabled = False
|
||||||
|
, attrs =
|
||||||
|
[ href "#"
|
||||||
|
, onClick (PrependNew box)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ viewMain texts flags settings model
|
||||||
|
, div [ class S.formHeader ]
|
||||||
|
[ text texts.dashboardBoxes
|
||||||
|
]
|
||||||
|
, MB.view
|
||||||
|
{ start = []
|
||||||
|
, end =
|
||||||
|
[ MB.Dropdown
|
||||||
|
{ linkIcon = "fa fa-plus"
|
||||||
|
, label = texts.newBox
|
||||||
|
, linkClass =
|
||||||
|
[ ( S.secondaryBasicButton, True )
|
||||||
|
]
|
||||||
|
, toggleMenu = ToggleNewBoxMenu
|
||||||
|
, menuOpen = model.newBoxMenuOpen
|
||||||
|
, items =
|
||||||
|
[ boxMenuItem Data.Box.queryBox
|
||||||
|
, boxMenuItem Data.Box.statsBox
|
||||||
|
, boxMenuItem Data.Box.messageBox
|
||||||
|
, boxMenuItem Data.Box.uploadBox
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, rootClasses = "mb-2"
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ class (gridStyle model.dashboard)
|
||||||
|
]
|
||||||
|
(List.map
|
||||||
|
(viewBox texts flags settings model)
|
||||||
|
(Dict.toList model.boxModels)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewBox : Texts -> Flags -> UiSettings -> Model -> ( Int, Comp.BoxEdit.Model ) -> Html Msg
|
||||||
|
viewBox texts flags settings model ( index, box ) =
|
||||||
|
let
|
||||||
|
dropId =
|
||||||
|
DD.getDropId model.boxDragDrop
|
||||||
|
|
||||||
|
dragId =
|
||||||
|
DD.getDragId model.boxDragDrop
|
||||||
|
|
||||||
|
styles =
|
||||||
|
[ classList [ ( "opacity-40", dropId == Just index && dropId /= dragId ) ]
|
||||||
|
, class (spanStyle box.box)
|
||||||
|
]
|
||||||
|
in
|
||||||
|
div
|
||||||
|
(DD.draggable DragDropMsg index ++ DD.droppable DragDropMsg index ++ styles)
|
||||||
|
[ Html.map (BoxMsg index)
|
||||||
|
(Comp.BoxEdit.view texts.boxView flags settings box)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewMain : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
viewMain texts _ _ model =
|
||||||
|
let
|
||||||
|
columnsSettings =
|
||||||
|
{ display = String.fromInt
|
||||||
|
, icon = \_ -> Nothing
|
||||||
|
, selectPlaceholder = ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "my-2 " ]
|
||||||
|
[ div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.basics.name
|
||||||
|
, B.inputRequired
|
||||||
|
]
|
||||||
|
, input
|
||||||
|
[ type_ "text"
|
||||||
|
, placeholder texts.namePlaceholder
|
||||||
|
, class S.textInput
|
||||||
|
, classList [ ( S.inputErrorBorder, String.trim model.nameValue == "" ) ]
|
||||||
|
, value model.nameValue
|
||||||
|
, onInput SetName
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.columns
|
||||||
|
]
|
||||||
|
, Html.map ColumnsMsg
|
||||||
|
(Comp.FixedDropdown.viewStyled2 columnsSettings
|
||||||
|
False
|
||||||
|
model.columnsValue
|
||||||
|
model.columnsModel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.gap
|
||||||
|
]
|
||||||
|
, Html.map GapMsg
|
||||||
|
(Comp.FixedDropdown.viewStyled2 columnsSettings
|
||||||
|
False
|
||||||
|
model.gapValue
|
||||||
|
model.gapModel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ div [ class "flex flex-row space-x-4" ]
|
||||||
|
[ label [ class "inline-flex items-center" ]
|
||||||
|
[ input
|
||||||
|
[ type_ "radio"
|
||||||
|
, checked (Data.AccountScope.isUser model.scope)
|
||||||
|
, onCheck (\_ -> SetScope Data.AccountScope.User)
|
||||||
|
, class S.radioInput
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, span [ class "ml-2" ] [ text <| texts.accountScope Data.AccountScope.User ]
|
||||||
|
]
|
||||||
|
, label [ class "inline-flex items-center" ]
|
||||||
|
[ input
|
||||||
|
[ type_ "radio"
|
||||||
|
, checked (Data.AccountScope.isCollective model.scope)
|
||||||
|
, onCheck (\_ -> SetScope Data.AccountScope.Collective)
|
||||||
|
, class S.radioInput
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, span [ class "ml-2" ]
|
||||||
|
[ text <| texts.accountScope Data.AccountScope.Collective ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "mt-2" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleDefault
|
||||||
|
, label = texts.defaultDashboard
|
||||||
|
, id = ""
|
||||||
|
, value = model.defaultDashboard
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
gridStyle : Dashboard -> String
|
||||||
|
gridStyle db =
|
||||||
|
let
|
||||||
|
colStyle =
|
||||||
|
case db.columns of
|
||||||
|
1 ->
|
||||||
|
""
|
||||||
|
|
||||||
|
2 ->
|
||||||
|
"md:grid-cols-2"
|
||||||
|
|
||||||
|
3 ->
|
||||||
|
"md:grid-cols-3"
|
||||||
|
|
||||||
|
4 ->
|
||||||
|
"md:grid-cols-4"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"md:grid-cols-5"
|
||||||
|
in
|
||||||
|
"grid gap-4 grid-cols-1 " ++ colStyle
|
||||||
|
|
||||||
|
|
||||||
|
spanStyle : Box -> String
|
||||||
|
spanStyle box =
|
||||||
|
case box.colspan of
|
||||||
|
1 ->
|
||||||
|
""
|
||||||
|
|
||||||
|
2 ->
|
||||||
|
"col-span-1 md:col-span-2"
|
||||||
|
|
||||||
|
3 ->
|
||||||
|
"col-span-1 md:col-span-3"
|
||||||
|
|
||||||
|
4 ->
|
||||||
|
"col-span-1 md:col-span-4"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"col-span-1 md:col-span-5"
|
319
modules/webapp/src/main/elm/Comp/DashboardManage.elm
Normal file
319
modules/webapp/src/main/elm/Comp/DashboardManage.elm
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.DashboardManage exposing (Model, Msg, SubmitAction(..), UpdateResult, init, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.DashboardEdit
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.AccountScope exposing (AccountScope)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, i, text)
|
||||||
|
import Html.Attributes exposing (class, classList)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.DashboardManage exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ edit : Comp.DashboardEdit.Model
|
||||||
|
, initData : InitData
|
||||||
|
, deleteRequested : Bool
|
||||||
|
, formError : Maybe FormError
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SaveDashboard
|
||||||
|
| Cancel
|
||||||
|
| DeleteDashboard
|
||||||
|
| SetRequestDelete Bool
|
||||||
|
| EditMsg Comp.DashboardEdit.Msg
|
||||||
|
| DeleteResp (Result Http.Error BasicResult)
|
||||||
|
| SaveResp String (Result Http.Error BasicResult)
|
||||||
|
| CreateNew
|
||||||
|
| CopyCurrent
|
||||||
|
|
||||||
|
|
||||||
|
type FormError
|
||||||
|
= FormInvalid String
|
||||||
|
| FormHttpError Http.Error
|
||||||
|
| FormNameEmpty
|
||||||
|
| FormNameExists
|
||||||
|
|
||||||
|
|
||||||
|
type alias InitData =
|
||||||
|
{ flags : Flags
|
||||||
|
, dashboard : Dashboard
|
||||||
|
, scope : AccountScope
|
||||||
|
, isDefault : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : InitData -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
init data =
|
||||||
|
let
|
||||||
|
( em, ec, es ) =
|
||||||
|
Comp.DashboardEdit.init data.flags data.dashboard data.scope data.isDefault
|
||||||
|
|
||||||
|
model =
|
||||||
|
{ edit = em
|
||||||
|
, initData = data
|
||||||
|
, deleteRequested = False
|
||||||
|
, formError = Nothing
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( model, Cmd.map EditMsg ec, Sub.map EditMsg es )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
type SubmitAction
|
||||||
|
= SubmitNone
|
||||||
|
| SubmitCancel String
|
||||||
|
| SubmitSaved String
|
||||||
|
| SubmitDeleted
|
||||||
|
|
||||||
|
|
||||||
|
type alias UpdateResult =
|
||||||
|
{ model : Model
|
||||||
|
, cmd : Cmd Msg
|
||||||
|
, sub : Sub Msg
|
||||||
|
, action : SubmitAction
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> (String -> Bool) -> Msg -> Model -> UpdateResult
|
||||||
|
update flags nameExists msg model =
|
||||||
|
case msg of
|
||||||
|
EditMsg lm ->
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
Comp.DashboardEdit.update flags lm model.edit
|
||||||
|
in
|
||||||
|
{ model = { model | edit = result.model }
|
||||||
|
, cmd = Cmd.map EditMsg result.cmd
|
||||||
|
, sub = Sub.map EditMsg result.sub
|
||||||
|
, action = SubmitNone
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateNew ->
|
||||||
|
let
|
||||||
|
initData =
|
||||||
|
{ flags = flags
|
||||||
|
, dashboard = Data.Dashboard.empty
|
||||||
|
, scope = Data.AccountScope.User
|
||||||
|
, isDefault = False
|
||||||
|
}
|
||||||
|
|
||||||
|
( m, c, s ) =
|
||||||
|
init initData
|
||||||
|
in
|
||||||
|
UpdateResult m c s SubmitNone
|
||||||
|
|
||||||
|
CopyCurrent ->
|
||||||
|
let
|
||||||
|
( current, scope, isDefault ) =
|
||||||
|
Comp.DashboardEdit.getBoard model.edit
|
||||||
|
|
||||||
|
initData =
|
||||||
|
{ flags = flags
|
||||||
|
, dashboard = { current | name = "" }
|
||||||
|
, scope = scope
|
||||||
|
, isDefault = isDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
( m, c, s ) =
|
||||||
|
init initData
|
||||||
|
in
|
||||||
|
UpdateResult m c s SubmitNone
|
||||||
|
|
||||||
|
SetRequestDelete flag ->
|
||||||
|
unit { model | deleteRequested = flag }
|
||||||
|
|
||||||
|
SaveDashboard ->
|
||||||
|
let
|
||||||
|
( tosave, scope, isDefault ) =
|
||||||
|
Comp.DashboardEdit.getBoard model.edit
|
||||||
|
|
||||||
|
saveCmd =
|
||||||
|
Api.replaceDashboard flags
|
||||||
|
model.initData.dashboard.name
|
||||||
|
tosave
|
||||||
|
scope
|
||||||
|
isDefault
|
||||||
|
(SaveResp tosave.name)
|
||||||
|
in
|
||||||
|
if tosave.name == "" then
|
||||||
|
unit { model | formError = Just FormNameEmpty }
|
||||||
|
|
||||||
|
else if tosave.name /= model.initData.dashboard.name && nameExists tosave.name then
|
||||||
|
unit { model | formError = Just FormNameExists }
|
||||||
|
|
||||||
|
else
|
||||||
|
UpdateResult model saveCmd Sub.none SubmitNone
|
||||||
|
|
||||||
|
Cancel ->
|
||||||
|
unitAction model (SubmitCancel model.initData.dashboard.name)
|
||||||
|
|
||||||
|
DeleteDashboard ->
|
||||||
|
let
|
||||||
|
deleteCmd =
|
||||||
|
Api.deleteDashboard flags model.initData.dashboard.name model.initData.scope DeleteResp
|
||||||
|
in
|
||||||
|
UpdateResult model deleteCmd Sub.none SubmitNone
|
||||||
|
|
||||||
|
SaveResp name (Ok result) ->
|
||||||
|
if result.success then
|
||||||
|
unitAction model (SubmitSaved name)
|
||||||
|
|
||||||
|
else
|
||||||
|
unit { model | formError = Just (FormInvalid result.message) }
|
||||||
|
|
||||||
|
SaveResp _ (Err err) ->
|
||||||
|
unit { model | formError = Just (FormHttpError err) }
|
||||||
|
|
||||||
|
DeleteResp (Ok result) ->
|
||||||
|
if result.success then
|
||||||
|
unitAction model SubmitDeleted
|
||||||
|
|
||||||
|
else
|
||||||
|
unit { model | formError = Just (FormInvalid result.message) }
|
||||||
|
|
||||||
|
DeleteResp (Err err) ->
|
||||||
|
unit { model | formError = Just (FormHttpError err) }
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> UpdateResult
|
||||||
|
unit model =
|
||||||
|
UpdateResult model Cmd.none Sub.none SubmitNone
|
||||||
|
|
||||||
|
|
||||||
|
unitAction : Model -> SubmitAction -> UpdateResult
|
||||||
|
unitAction model action =
|
||||||
|
UpdateResult model Cmd.none Sub.none action
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
type alias ViewSettings =
|
||||||
|
{ showDeleteButton : Bool
|
||||||
|
, showCopyButton : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> ViewSettings -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags cfg settings model =
|
||||||
|
div []
|
||||||
|
[ B.contentDimmer model.deleteRequested
|
||||||
|
(div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "text-xl" ]
|
||||||
|
[ i [ class "fa fa-info-circle mr-2" ] []
|
||||||
|
, text texts.reallyDeleteDashboard
|
||||||
|
]
|
||||||
|
, div [ class "mt-4 flex flex-row items-center space-x-2" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.DeleteButton
|
||||||
|
{ tagger = DeleteDashboard
|
||||||
|
, title = ""
|
||||||
|
, label = texts.basics.yes
|
||||||
|
, icon = Just "fa fa-check"
|
||||||
|
}
|
||||||
|
, MB.viewItem <|
|
||||||
|
MB.SecondaryButton
|
||||||
|
{ tagger = SetRequestDelete False
|
||||||
|
, title = ""
|
||||||
|
, label = texts.basics.no
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
, MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = SaveDashboard
|
||||||
|
, title = texts.basics.submitThisForm
|
||||||
|
, icon = Just "fa fa-save"
|
||||||
|
, label = texts.basics.submit
|
||||||
|
}
|
||||||
|
, MB.SecondaryButton
|
||||||
|
{ tagger = Cancel
|
||||||
|
, title = texts.basics.cancel
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
, label = texts.basics.cancel
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, end =
|
||||||
|
[ MB.BasicButton
|
||||||
|
{ tagger = CreateNew
|
||||||
|
, title = texts.createDashboard
|
||||||
|
, icon = Just "fa fa-plus"
|
||||||
|
, label = texts.createDashboard
|
||||||
|
}
|
||||||
|
, MB.CustomButton
|
||||||
|
{ tagger = CopyCurrent
|
||||||
|
, title = texts.copyDashboard
|
||||||
|
, icon = Just "fa fa-copy"
|
||||||
|
, label = texts.copyDashboard
|
||||||
|
, inputClass =
|
||||||
|
[ ( S.secondaryBasicButton, True )
|
||||||
|
, ( "hidden", not cfg.showCopyButton )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, MB.CustomButton
|
||||||
|
{ tagger = SetRequestDelete True
|
||||||
|
, title = texts.basics.delete
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
, label = texts.basics.delete
|
||||||
|
, inputClass =
|
||||||
|
[ ( S.deleteButton, True )
|
||||||
|
, ( "hidden", not cfg.showDeleteButton )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, rootClasses = ""
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ class S.errorMessage
|
||||||
|
, class "mt-2"
|
||||||
|
, classList [ ( "hidden", model.formError == Nothing ) ]
|
||||||
|
]
|
||||||
|
[ errorMessage texts model
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ Html.map EditMsg
|
||||||
|
(Comp.DashboardEdit.view texts.dashboardEdit flags settings model.edit)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
errorMessage : Texts -> Model -> Html Msg
|
||||||
|
errorMessage texts model =
|
||||||
|
case model.formError of
|
||||||
|
Just (FormInvalid errMsg) ->
|
||||||
|
text errMsg
|
||||||
|
|
||||||
|
Just (FormHttpError err) ->
|
||||||
|
text (texts.httpError err)
|
||||||
|
|
||||||
|
Just FormNameEmpty ->
|
||||||
|
text texts.nameEmpty
|
||||||
|
|
||||||
|
Just FormNameExists ->
|
||||||
|
text texts.nameExists
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
text ""
|
137
modules/webapp/src/main/elm/Comp/DashboardView.elm
Normal file
137
modules/webapp/src/main/elm/Comp/DashboardView.elm
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.DashboardView exposing (Model, Msg, init, reloadData, update, view, viewBox)
|
||||||
|
|
||||||
|
import Comp.BoxView
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Html exposing (Html, div)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.DashboardView exposing (Texts)
|
||||||
|
import Util.Update
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ dashboard : Dashboard
|
||||||
|
, boxModels : Dict Int Comp.BoxView.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= BoxMsg Int Comp.BoxView.Msg
|
||||||
|
| ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> Dashboard -> ( Model, Cmd Msg )
|
||||||
|
init flags db =
|
||||||
|
let
|
||||||
|
( boxModels, cmds ) =
|
||||||
|
List.map (Comp.BoxView.init flags) db.boxes
|
||||||
|
|> List.indexedMap (\a -> \( bm, bc ) -> ( bm, Cmd.map (BoxMsg a) bc ))
|
||||||
|
|> List.unzip
|
||||||
|
in
|
||||||
|
( { dashboard = db
|
||||||
|
, boxModels =
|
||||||
|
List.indexedMap Tuple.pair boxModels
|
||||||
|
|> Dict.fromList
|
||||||
|
}
|
||||||
|
, Cmd.batch cmds
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
reloadData : Msg
|
||||||
|
reloadData =
|
||||||
|
ReloadData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
BoxMsg index lm ->
|
||||||
|
case Dict.get index model.boxModels of
|
||||||
|
Just bm ->
|
||||||
|
let
|
||||||
|
( cm, cc, cs ) =
|
||||||
|
Comp.BoxView.update flags lm bm
|
||||||
|
in
|
||||||
|
( { model | boxModels = Dict.insert index cm model.boxModels }
|
||||||
|
, Cmd.map (BoxMsg index) cc
|
||||||
|
, Sub.map (BoxMsg index) cs
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
ReloadData ->
|
||||||
|
let
|
||||||
|
updateAll =
|
||||||
|
List.map (\index -> BoxMsg index Comp.BoxView.reloadData) (Dict.keys model.boxModels)
|
||||||
|
|> List.map (\m -> update flags m)
|
||||||
|
|> Util.Update.andThen2
|
||||||
|
in
|
||||||
|
updateAll model
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
unit model =
|
||||||
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts flags settings model =
|
||||||
|
div
|
||||||
|
[ class (gridStyle model.dashboard)
|
||||||
|
]
|
||||||
|
(List.indexedMap (viewBox texts flags settings) <| Dict.values model.boxModels)
|
||||||
|
|
||||||
|
|
||||||
|
viewBox : Texts -> Flags -> UiSettings -> Int -> Comp.BoxView.Model -> Html Msg
|
||||||
|
viewBox texts flags settings index box =
|
||||||
|
Html.map (BoxMsg index)
|
||||||
|
(Comp.BoxView.view texts.boxView flags settings box)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
{-| note due to tailwinds purging css that is not found in source
|
||||||
|
files, need to spell them out somewhere - which is done it keep.txt in
|
||||||
|
this case.
|
||||||
|
-}
|
||||||
|
gridStyle : Dashboard -> String
|
||||||
|
gridStyle db =
|
||||||
|
let
|
||||||
|
cappedGap =
|
||||||
|
min db.gap 12
|
||||||
|
|
||||||
|
cappedCol =
|
||||||
|
min db.columns 12
|
||||||
|
|
||||||
|
gapStyle =
|
||||||
|
" gap-" ++ String.fromInt cappedGap ++ " "
|
||||||
|
|
||||||
|
colStyle =
|
||||||
|
case db.columns of
|
||||||
|
1 ->
|
||||||
|
""
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
" md:grid-cols-" ++ String.fromInt cappedCol ++ " "
|
||||||
|
in
|
||||||
|
"grid grid-cols-1 " ++ gapStyle ++ colStyle
|
@ -712,10 +712,10 @@ formHeading texts classes model =
|
|||||||
(\_ -> texts.addCustomFieldHeader)
|
(\_ -> texts.addCustomFieldHeader)
|
||||||
|
|
||||||
headIcon =
|
headIcon =
|
||||||
fold (\_ -> Icons.tagIcon2 "mr-2")
|
fold (\_ -> Icons.tagIcon "mr-2")
|
||||||
(\_ -> Icons.personIcon2 "mr-2")
|
(\_ -> Icons.personIcon "mr-2")
|
||||||
(\_ -> Icons.organizationIcon2 "mr-2")
|
(\_ -> Icons.organizationIcon "mr-2")
|
||||||
(\_ -> Icons.equipmentIcon2 "mt-2")
|
(\_ -> Icons.equipmentIcon "mt-2")
|
||||||
(\_ -> Icons.customFieldIcon2 "mr-2")
|
(\_ -> Icons.customFieldIcon2 "mr-2")
|
||||||
in
|
in
|
||||||
div [ class classes ]
|
div [ class classes ]
|
||||||
@ -738,10 +738,10 @@ viewModal2 texts settings mm =
|
|||||||
(\_ -> texts.addCustomFieldHeader)
|
(\_ -> texts.addCustomFieldHeader)
|
||||||
|
|
||||||
headIcon =
|
headIcon =
|
||||||
fold (\_ -> Icons.tagIcon2 "mr-2")
|
fold (\_ -> Icons.tagIcon "mr-2")
|
||||||
(\_ -> Icons.personIcon2 "mr-2")
|
(\_ -> Icons.personIcon "mr-2")
|
||||||
(\_ -> Icons.organizationIcon2 "mr-2")
|
(\_ -> Icons.organizationIcon "mr-2")
|
||||||
(\_ -> Icons.equipmentIcon2 "mt-2")
|
(\_ -> Icons.equipmentIcon "mt-2")
|
||||||
(\_ -> Icons.customFieldIcon2 "mr-2")
|
(\_ -> Icons.customFieldIcon2 "mr-2")
|
||||||
in
|
in
|
||||||
div
|
div
|
||||||
|
@ -132,15 +132,21 @@ filterMime model files =
|
|||||||
--- View2
|
--- View2
|
||||||
|
|
||||||
|
|
||||||
view2 : Texts -> Model -> Html Msg
|
type alias ViewSettings =
|
||||||
view2 texts model =
|
{ light : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view2 : Texts -> ViewSettings -> Model -> Html Msg
|
||||||
|
view2 texts cfg model =
|
||||||
div
|
div
|
||||||
[ classList
|
[ classList
|
||||||
[ ( "bg-opacity-100 bg-blue-100 dark:bg-sky-800", model.state.hover )
|
[ ( "bg-opacity-100 bg-blue-100 dark:bg-sky-800", model.state.hover )
|
||||||
, ( "bg-blue-100 dark:bg-sky-900 bg-opacity-50", not model.state.hover )
|
, ( "bg-indigo-100 dark:bg-sky-900 bg-opacity-50", not model.state.hover )
|
||||||
, ( "disabled", not model.state.active )
|
, ( "disabled", not model.state.active )
|
||||||
]
|
]
|
||||||
, class "flex flex-col justify-center items-center py-2 md:py-12 border-0 border-t-2 border-blue-500 dark:border-sky-500 dropzone"
|
, class "flex flex-col justify-center items-center py-2 md:py-12 dropzone"
|
||||||
|
, classList [ ( " border-0 border-t-2 border-blue-500 dark:border-sky-500", not cfg.light ) ]
|
||||||
, onDragEnter DragEnter
|
, onDragEnter DragEnter
|
||||||
, onDragOver DragEnter
|
, onDragOver DragEnter
|
||||||
, onDragLeave DragLeave
|
, onDragLeave DragLeave
|
||||||
@ -168,7 +174,10 @@ view2 texts model =
|
|||||||
, attrs = [ href "#" ]
|
, attrs = [ href "#" ]
|
||||||
, disabled = not model.state.active
|
, disabled = not model.state.active
|
||||||
}
|
}
|
||||||
, div [ class "text-center opacity-75 text-sm mt-4" ]
|
, div
|
||||||
|
[ class "text-center opacity-75 text-sm mt-4"
|
||||||
|
, classList [ ( "hidden", cfg.light ) ]
|
||||||
|
]
|
||||||
[ text texts.selectInfo
|
[ text texts.selectInfo
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -9,6 +9,7 @@ module Comp.EquipmentManage exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
, emptyModel
|
, emptyModel
|
||||||
|
, init
|
||||||
, update
|
, update
|
||||||
, view2
|
, view2
|
||||||
)
|
)
|
||||||
@ -70,6 +71,11 @@ emptyModel =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
( emptyModel, Api.getEquipments flags emptyModel.query emptyModel.order EquipmentResp )
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= TableMsg Comp.EquipmentTable.Msg
|
= TableMsg Comp.EquipmentTable.Msg
|
||||||
| FormMsg Comp.EquipmentForm.Msg
|
| FormMsg Comp.EquipmentForm.Msg
|
||||||
|
@ -418,7 +418,7 @@ viewRow texts cfg settings flags model item =
|
|||||||
, class "hover:opacity-60"
|
, class "hover:opacity-60"
|
||||||
, title texts.basics.folder
|
, title texts.basics.folder
|
||||||
]
|
]
|
||||||
[ Icons.folderIcon2 "mr-2"
|
[ Icons.folderIcon "mr-2"
|
||||||
, Comp.LinkTarget.makeFolderLink item
|
, Comp.LinkTarget.makeFolderLink item
|
||||||
[ ( "hover:opacity-60", True ) ]
|
[ ( "hover:opacity-60", True ) ]
|
||||||
SetLinkTarget
|
SetLinkTarget
|
||||||
@ -592,7 +592,7 @@ metaDataContent2 texts settings item =
|
|||||||
, class "hover:opacity-60"
|
, class "hover:opacity-60"
|
||||||
, title texts.basics.folder
|
, title texts.basics.folder
|
||||||
]
|
]
|
||||||
[ Icons.folderIcon2 "mr-2"
|
[ Icons.folderIcon "mr-2"
|
||||||
, Comp.LinkTarget.makeFolderLink item
|
, Comp.LinkTarget.makeFolderLink item
|
||||||
[ ( "hover:opacity-60", True ) ]
|
[ ( "hover:opacity-60", True ) ]
|
||||||
SetLinkTarget
|
SetLinkTarget
|
||||||
|
86
modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm
Normal file
86
modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.ItemColumnDropdown exposing (Model, Msg, getSelected, init, update, view)
|
||||||
|
|
||||||
|
import Comp.Dropdown exposing (Option)
|
||||||
|
import Data.DropdownStyle
|
||||||
|
import Data.ItemColumn exposing (ItemColumn(..))
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html)
|
||||||
|
import Messages.Comp.ItemColumnDropdown exposing (Texts)
|
||||||
|
|
||||||
|
|
||||||
|
type Model
|
||||||
|
= Model (Comp.Dropdown.Model ItemColumn)
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= DropdownMsg (Comp.Dropdown.Msg ItemColumn)
|
||||||
|
|
||||||
|
|
||||||
|
init : List ItemColumn -> Model
|
||||||
|
init selected =
|
||||||
|
Model <|
|
||||||
|
Comp.Dropdown.makeMultipleList
|
||||||
|
{ options = Data.ItemColumn.all, selected = selected }
|
||||||
|
|
||||||
|
|
||||||
|
getSelected : Model -> List ItemColumn
|
||||||
|
getSelected (Model dm) =
|
||||||
|
Comp.Dropdown.getSelected dm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||||
|
update msg model =
|
||||||
|
let
|
||||||
|
dmodel =
|
||||||
|
case model of
|
||||||
|
Model a ->
|
||||||
|
a
|
||||||
|
in
|
||||||
|
case msg of
|
||||||
|
DropdownMsg lm ->
|
||||||
|
let
|
||||||
|
( dm, dc ) =
|
||||||
|
Comp.Dropdown.update lm dmodel
|
||||||
|
in
|
||||||
|
( Model dm, Cmd.map DropdownMsg dc )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
itemOption : Texts -> ItemColumn -> Option
|
||||||
|
itemOption texts item =
|
||||||
|
{ text = texts.column.label item
|
||||||
|
, additional = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
let
|
||||||
|
viewSettings =
|
||||||
|
{ makeOption = itemOption texts
|
||||||
|
, placeholder = texts.placeholder
|
||||||
|
, labelColor = \_ -> \_ -> ""
|
||||||
|
, style = Data.DropdownStyle.mainStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
dm =
|
||||||
|
case model of
|
||||||
|
Model a ->
|
||||||
|
a
|
||||||
|
in
|
||||||
|
Html.map DropdownMsg
|
||||||
|
(Comp.Dropdown.view2 viewSettings settings dm)
|
43
modules/webapp/src/main/elm/Comp/ItemColumnView.elm
Normal file
43
modules/webapp/src/main/elm/Comp/ItemColumnView.elm
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.ItemColumnView exposing (..)
|
||||||
|
|
||||||
|
import Api.Model.ItemLight exposing (ItemLight)
|
||||||
|
import Data.ItemColumn exposing (ItemColumn(..))
|
||||||
|
import Data.ItemTemplate exposing (TemplateContext)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Attribute, Html, div, text)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
|
||||||
|
|
||||||
|
renderDiv :
|
||||||
|
TemplateContext
|
||||||
|
-> UiSettings
|
||||||
|
-> ItemColumn
|
||||||
|
-> List (Attribute msg)
|
||||||
|
-> ItemLight
|
||||||
|
-> Html msg
|
||||||
|
renderDiv ctx settings col attr item =
|
||||||
|
case col of
|
||||||
|
Tags ->
|
||||||
|
div attr
|
||||||
|
(List.map
|
||||||
|
(\t ->
|
||||||
|
div
|
||||||
|
[ class "label text-sm"
|
||||||
|
, class <| Data.UiSettings.tagColorString2 t settings
|
||||||
|
]
|
||||||
|
[ text t.name ]
|
||||||
|
)
|
||||||
|
item.tags
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
div attr
|
||||||
|
[ text (Data.ItemColumn.renderString ctx col item)
|
||||||
|
]
|
@ -24,6 +24,11 @@ import Util.Size
|
|||||||
|
|
||||||
view : Texts -> Model -> Html Msg
|
view : Texts -> Model -> Html Msg
|
||||||
view texts model =
|
view texts model =
|
||||||
|
let
|
||||||
|
dropzoneCfg =
|
||||||
|
{ light = True
|
||||||
|
}
|
||||||
|
in
|
||||||
div
|
div
|
||||||
[ classList
|
[ classList
|
||||||
[ ( "hidden", not model.addFilesOpen )
|
[ ( "hidden", not model.addFilesOpen )
|
||||||
@ -35,7 +40,7 @@ view texts model =
|
|||||||
[ text texts.addMoreFilesToItem
|
[ text texts.addMoreFilesToItem
|
||||||
]
|
]
|
||||||
, Html.map AddFilesMsg
|
, Html.map AddFilesMsg
|
||||||
(Comp.Dropzone.view2 texts.dropzone model.addFilesModel)
|
(Comp.Dropzone.view2 texts.dropzone dropzoneCfg model.addFilesModel)
|
||||||
, div [ class "flex flex-row space-x-2 mt-2" ]
|
, div [ class "flex flex-row space-x-2 mt-2" ]
|
||||||
[ button
|
[ button
|
||||||
[ class S.primaryButton
|
[ class S.primaryButton
|
||||||
|
@ -298,7 +298,7 @@ formTabs texts flags settings model =
|
|||||||
[ optional [ Data.Fields.CorrOrg ] <|
|
[ optional [ Data.Fields.CorrOrg ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.organizationIcon2 "mr-2"
|
[ Icons.organizationIcon "mr-2"
|
||||||
, text texts.basics.organization
|
, text texts.basics.organization
|
||||||
, addIconLink texts.addNewOrg StartCorrOrgModal
|
, addIconLink texts.addNewOrg StartCorrOrgModal
|
||||||
, editIconLink texts.editOrg model.corrOrgModel StartEditCorrOrgModal
|
, editIconLink texts.editOrg model.corrOrgModel StartEditCorrOrgModal
|
||||||
@ -314,7 +314,7 @@ formTabs texts flags settings model =
|
|||||||
, optional [ Data.Fields.CorrPerson ] <|
|
, optional [ Data.Fields.CorrPerson ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.personIcon2 "mr-2"
|
[ Icons.personIcon "mr-2"
|
||||||
, text texts.basics.person
|
, text texts.basics.person
|
||||||
, addIconLink texts.addNewCorrespondentPerson StartCorrPersonModal
|
, addIconLink texts.addNewCorrespondentPerson StartCorrPersonModal
|
||||||
, editIconLink texts.editPerson
|
, editIconLink texts.editPerson
|
||||||
@ -348,7 +348,7 @@ formTabs texts flags settings model =
|
|||||||
[ optional [ Data.Fields.ConcPerson ] <|
|
[ optional [ Data.Fields.ConcPerson ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.personIcon2 "mr-2"
|
[ Icons.personIcon "mr-2"
|
||||||
, text texts.basics.person
|
, text texts.basics.person
|
||||||
, addIconLink texts.addNewConcerningPerson StartConcPersonModal
|
, addIconLink texts.addNewConcerningPerson StartConcPersonModal
|
||||||
, editIconLink texts.editPerson
|
, editIconLink texts.editPerson
|
||||||
@ -366,7 +366,7 @@ formTabs texts flags settings model =
|
|||||||
, optional [ Data.Fields.ConcEquip ] <|
|
, optional [ Data.Fields.ConcEquip ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.equipmentIcon2 "mr-2"
|
[ Icons.equipmentIcon "mr-2"
|
||||||
, text texts.basics.equipment
|
, text texts.basics.equipment
|
||||||
, addIconLink texts.addNewEquipment StartEquipModal
|
, addIconLink texts.addNewEquipment StartEquipModal
|
||||||
, editIconLink texts.editEquipment
|
, editIconLink texts.editEquipment
|
||||||
|
@ -98,7 +98,7 @@ view texts settings model =
|
|||||||
[ class itemStyle
|
[ class itemStyle
|
||||||
, title texts.basics.folder
|
, title texts.basics.folder
|
||||||
]
|
]
|
||||||
[ Icons.folderIcon2 "mr-2"
|
[ Icons.folderIcon "mr-2"
|
||||||
, Comp.LinkTarget.makeFolderLink model.item
|
, Comp.LinkTarget.makeFolderLink model.item
|
||||||
[ ( linkStyle, True ) ]
|
[ ( linkStyle, True ) ]
|
||||||
SetLinkTarget
|
SetLinkTarget
|
||||||
|
@ -735,7 +735,7 @@ renderEditForm2 texts flags cfg settings model =
|
|||||||
, body =
|
, body =
|
||||||
[ div [ class "field" ]
|
[ div [ class "field" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.tagsIcon2 ""
|
[ Icons.tagsIcon ""
|
||||||
, text texts.basics.tags
|
, text texts.basics.tags
|
||||||
, a
|
, a
|
||||||
[ class "float-right"
|
[ class "float-right"
|
||||||
@ -841,7 +841,7 @@ renderEditForm2 texts flags cfg settings model =
|
|||||||
[ optional [ Data.Fields.CorrOrg ] <|
|
[ optional [ Data.Fields.CorrOrg ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.organizationIcon2 ""
|
[ Icons.organizationIcon ""
|
||||||
, span [ class "ml-2" ]
|
, span [ class "ml-2" ]
|
||||||
[ text texts.basics.organization
|
[ text texts.basics.organization
|
||||||
]
|
]
|
||||||
@ -856,7 +856,7 @@ renderEditForm2 texts flags cfg settings model =
|
|||||||
, optional [ Data.Fields.CorrPerson ] <|
|
, optional [ Data.Fields.CorrPerson ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.personIcon2 ""
|
[ Icons.personIcon ""
|
||||||
, span [ class "ml-2" ]
|
, span [ class "ml-2" ]
|
||||||
[ text texts.basics.person
|
[ text texts.basics.person
|
||||||
]
|
]
|
||||||
@ -878,7 +878,7 @@ renderEditForm2 texts flags cfg settings model =
|
|||||||
[ optional [ Data.Fields.ConcPerson ] <|
|
[ optional [ Data.Fields.ConcPerson ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.personIcon2 ""
|
[ Icons.personIcon ""
|
||||||
, span [ class "ml-2" ]
|
, span [ class "ml-2" ]
|
||||||
[ text texts.basics.person ]
|
[ text texts.basics.person ]
|
||||||
]
|
]
|
||||||
@ -887,7 +887,7 @@ renderEditForm2 texts flags cfg settings model =
|
|||||||
, optional [ Data.Fields.ConcEquip ] <|
|
, optional [ Data.Fields.ConcEquip ] <|
|
||||||
div [ class "mb-4" ]
|
div [ class "mb-4" ]
|
||||||
[ label [ class S.inputLabel ]
|
[ label [ class S.inputLabel ]
|
||||||
[ Icons.equipmentIcon2 ""
|
[ Icons.equipmentIcon ""
|
||||||
, span [ class "ml-2" ]
|
, span [ class "ml-2" ]
|
||||||
[ text texts.basics.equipment ]
|
[ text texts.basics.equipment ]
|
||||||
]
|
]
|
||||||
|
@ -42,10 +42,7 @@ import Comp.ItemDetail.Model
|
|||||||
, UpdateResult
|
, UpdateResult
|
||||||
, ViewMode(..)
|
, ViewMode(..)
|
||||||
, initSelectViewModel
|
, initSelectViewModel
|
||||||
, initShowQrModel
|
|
||||||
, isEditNotes
|
, isEditNotes
|
||||||
, isShowQrAttach
|
|
||||||
, isShowQrItem
|
|
||||||
, resultModel
|
, resultModel
|
||||||
, resultModelCmd
|
, resultModelCmd
|
||||||
, resultModelCmdSub
|
, resultModelCmdSub
|
||||||
@ -741,7 +738,7 @@ update key flags inav settings msg model =
|
|||||||
resultModelCmd ( model, Page.set key (ItemDetailPage id) )
|
resultModelCmd ( model, Page.set key (ItemDetailPage id) )
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
resultModelCmd ( model, Page.set key HomePage )
|
resultModelCmd ( model, Page.set key (SearchPage Nothing) )
|
||||||
in
|
in
|
||||||
{ result_ | removedItem = Just removedId }
|
{ result_ | removedItem = Just removedId }
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ menuBar texts inav settings model =
|
|||||||
[ MB.CustomElement <|
|
[ MB.CustomElement <|
|
||||||
a
|
a
|
||||||
[ class S.secondaryBasicButton
|
[ class S.secondaryBasicButton
|
||||||
, Page.href HomePage
|
, Page.href (SearchPage Nothing)
|
||||||
, title texts.backToSearchResults
|
, title texts.backToSearchResults
|
||||||
]
|
]
|
||||||
[ i [ class "fa fa-arrow-left" ] []
|
[ i [ class "fa fa-arrow-left" ] []
|
||||||
|
@ -35,6 +35,7 @@ type LinkTarget
|
|||||||
| LinkTag IdName
|
| LinkTag IdName
|
||||||
| LinkCustomField ItemFieldValue
|
| LinkCustomField ItemFieldValue
|
||||||
| LinkSource String
|
| LinkSource String
|
||||||
|
| LinkBookmark String
|
||||||
| LinkNone
|
| LinkNone
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,18 +308,27 @@ makeButton btnType model =
|
|||||||
|
|
||||||
makeCheckbox : CheckboxData msg -> Html msg
|
makeCheckbox : CheckboxData msg -> Html msg
|
||||||
makeCheckbox model =
|
makeCheckbox model =
|
||||||
|
let
|
||||||
|
withId list =
|
||||||
|
if model.id == "" then
|
||||||
|
list
|
||||||
|
|
||||||
|
else
|
||||||
|
id model.id :: list
|
||||||
|
in
|
||||||
div [ class "" ]
|
div [ class "" ]
|
||||||
[ label
|
[ label
|
||||||
[ class "inline-flex space-x-2 items-center"
|
[ class "inline-flex space-x-2 items-center"
|
||||||
, for model.id
|
, for model.id
|
||||||
]
|
]
|
||||||
[ input
|
[ input
|
||||||
|
(withId
|
||||||
[ type_ "checkbox"
|
[ type_ "checkbox"
|
||||||
, onCheck model.tagger
|
, onCheck model.tagger
|
||||||
, checked model.value
|
, checked model.value
|
||||||
, class S.checkboxInput
|
, class S.checkboxInput
|
||||||
, id model.id
|
|
||||||
]
|
]
|
||||||
|
)
|
||||||
[]
|
[]
|
||||||
, span [ class "truncate" ]
|
, span [ class "truncate" ]
|
||||||
[ text model.label
|
[ text model.label
|
||||||
|
@ -9,6 +9,7 @@ module Comp.OrgManage exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
, emptyModel
|
, emptyModel
|
||||||
|
, init
|
||||||
, update
|
, update
|
||||||
, view2
|
, view2
|
||||||
)
|
)
|
||||||
@ -71,6 +72,11 @@ emptyModel =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
( emptyModel, Api.getOrganizations flags emptyModel.query emptyModel.order OrgResp )
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= TableMsg Comp.OrgTable.Msg
|
= TableMsg Comp.OrgTable.Msg
|
||||||
| FormMsg Comp.OrgForm.Msg
|
| FormMsg Comp.OrgForm.Msg
|
||||||
|
@ -9,6 +9,7 @@ module Comp.PersonManage exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
, emptyModel
|
, emptyModel
|
||||||
|
, init
|
||||||
, update
|
, update
|
||||||
, view2
|
, view2
|
||||||
)
|
)
|
||||||
@ -72,6 +73,11 @@ emptyModel =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
( emptyModel, Api.getPersons flags emptyModel.query emptyModel.order PersonResp )
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= TableMsg Comp.PersonTable.Msg
|
= TableMsg Comp.PersonTable.Msg
|
||||||
| FormMsg Comp.PersonForm.Msg
|
| FormMsg Comp.PersonForm.Msg
|
||||||
|
@ -11,6 +11,7 @@ module Comp.PowerSearchInput exposing
|
|||||||
, Msg
|
, Msg
|
||||||
, ViewSettings
|
, ViewSettings
|
||||||
, init
|
, init
|
||||||
|
, initWith
|
||||||
, isValid
|
, isValid
|
||||||
, setSearchString
|
, setSearchString
|
||||||
, update
|
, update
|
||||||
@ -45,6 +46,15 @@ init =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
initWith : String -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
initWith qstr =
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
update (setSearchString qstr) init
|
||||||
|
in
|
||||||
|
( result.model, result.cmd, result.subs )
|
||||||
|
|
||||||
|
|
||||||
isValid : Model -> Bool
|
isValid : Model -> Bool
|
||||||
isValid model =
|
isValid model =
|
||||||
model.input /= Nothing && model.result.success
|
model.input /= Nothing && model.result.success
|
||||||
|
@ -59,7 +59,7 @@ import Data.UiSettings exposing (UiSettings)
|
|||||||
import DatePicker exposing (DatePicker)
|
import DatePicker exposing (DatePicker)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick, onInput)
|
import Html.Events exposing (onInput)
|
||||||
import Http
|
import Http
|
||||||
import Messages.Comp.SearchMenu exposing (Texts)
|
import Messages.Comp.SearchMenu exposing (Texts)
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
@ -385,6 +385,7 @@ type Msg
|
|||||||
| SetConcEquip IdName
|
| SetConcEquip IdName
|
||||||
| SetFolder IdName
|
| SetFolder IdName
|
||||||
| SetTag String
|
| SetTag String
|
||||||
|
| SetBookmark String
|
||||||
| SetCustomField ItemFieldValue
|
| SetCustomField ItemFieldValue
|
||||||
| CustomFieldMsg Comp.CustomFieldMultiInput.Msg
|
| CustomFieldMsg Comp.CustomFieldMultiInput.Msg
|
||||||
| SetSource String
|
| SetSource String
|
||||||
@ -432,6 +433,9 @@ linkTargetMsg linkTarget =
|
|||||||
Comp.LinkTarget.LinkSource str ->
|
Comp.LinkTarget.LinkSource str ->
|
||||||
Just <| ResetToSource str
|
Just <| ResetToSource str
|
||||||
|
|
||||||
|
Comp.LinkTarget.LinkBookmark id ->
|
||||||
|
Just <| SetBookmark id
|
||||||
|
|
||||||
|
|
||||||
type alias NextState =
|
type alias NextState =
|
||||||
{ model : Model
|
{ model : Model
|
||||||
@ -556,6 +560,22 @@ updateDrop ddm flags settings msg model =
|
|||||||
SetTag id ->
|
SetTag id ->
|
||||||
resetAndSet (TagSelectMsg (Comp.TagSelect.toggleTag id))
|
resetAndSet (TagSelectMsg (Comp.TagSelect.toggleTag id))
|
||||||
|
|
||||||
|
SetBookmark id ->
|
||||||
|
let
|
||||||
|
nextModel =
|
||||||
|
resetModel model
|
||||||
|
|
||||||
|
sel =
|
||||||
|
{ bookmarks = Set.singleton id
|
||||||
|
, shares = Set.empty
|
||||||
|
}
|
||||||
|
in
|
||||||
|
{ model = { nextModel | selectedBookmarks = sel }
|
||||||
|
, cmd = Cmd.none
|
||||||
|
, stateChange = sel /= model.selectedBookmarks
|
||||||
|
, dragDrop = DD.DragDropData ddm Nothing
|
||||||
|
}
|
||||||
|
|
||||||
GetAllTagsResp (Ok stats) ->
|
GetAllTagsResp (Ok stats) ->
|
||||||
let
|
let
|
||||||
tagSel =
|
tagSel =
|
||||||
@ -1064,7 +1084,7 @@ updateDrop ddm flags settings msg model =
|
|||||||
AllBookmarksResp (Ok bm) ->
|
AllBookmarksResp (Ok bm) ->
|
||||||
{ model = { model | allBookmarks = Comp.BookmarkChooser.init bm }
|
{ model = { model | allBookmarks = Comp.BookmarkChooser.init bm }
|
||||||
, cmd = Cmd.none
|
, cmd = Cmd.none
|
||||||
, stateChange = False
|
, stateChange = model.allBookmarks /= Comp.BookmarkChooser.init bm
|
||||||
, dragDrop = DD.DragDropData ddm Nothing
|
, dragDrop = DD.DragDropData ddm Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,7 +1102,7 @@ updateDrop ddm flags settings msg model =
|
|||||||
in
|
in
|
||||||
{ model = { model | allBookmarks = next, selectedBookmarks = sel }
|
{ model = { model | allBookmarks = next, selectedBookmarks = sel }
|
||||||
, cmd = Cmd.none
|
, cmd = Cmd.none
|
||||||
, stateChange = sel /= model.selectedBookmarks
|
, stateChange = sel /= model.selectedBookmarks || model.allBookmarks /= next
|
||||||
, dragDrop = DD.DragDropData ddm Nothing
|
, dragDrop = DD.DragDropData ddm Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
module Comp.SearchStatsView exposing
|
module Comp.SearchStatsView exposing
|
||||||
( nameOrLabel
|
( nameOrLabel
|
||||||
, sortFields
|
, sortFields
|
||||||
|
, view
|
||||||
, view2
|
, view2
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,8 +37,13 @@ sortFields fields =
|
|||||||
--- View2
|
--- View2
|
||||||
|
|
||||||
|
|
||||||
view2 : Texts -> String -> SearchStats -> Html msg
|
view : Texts -> String -> SearchStats -> Html msg
|
||||||
view2 texts classes stats =
|
view texts classes stats =
|
||||||
|
view2 texts True classes stats
|
||||||
|
|
||||||
|
|
||||||
|
view2 : Texts -> Bool -> String -> SearchStats -> Html msg
|
||||||
|
view2 texts showCount classes stats =
|
||||||
let
|
let
|
||||||
isNumField f =
|
isNumField f =
|
||||||
f.sum > 0
|
f.sum > 0
|
||||||
@ -78,7 +84,10 @@ view2 texts classes stats =
|
|||||||
in
|
in
|
||||||
div [ class classes ]
|
div [ class classes ]
|
||||||
[ div [ class "flex flex-col md:flex-row" ]
|
[ div [ class "flex flex-col md:flex-row" ]
|
||||||
[ div [ class "px-8 py-4" ]
|
[ div
|
||||||
|
[ class "px-8 py-4"
|
||||||
|
, classList [ ( "hidden", not showCount ) ]
|
||||||
|
]
|
||||||
[ B.stats
|
[ B.stats
|
||||||
{ rootClass = ""
|
{ rootClass = ""
|
||||||
, valueClass = "text-4xl"
|
, valueClass = "text-4xl"
|
||||||
|
@ -85,6 +85,7 @@ init flags =
|
|||||||
, Cmd.batch
|
, Cmd.batch
|
||||||
[ Cmd.map FormMsg fc
|
[ Cmd.map FormMsg fc
|
||||||
, Cmd.map MailMsg mc
|
, Cmd.map MailMsg mc
|
||||||
|
, Api.getShares flags "" True LoadSharesResp
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ init flags =
|
|||||||
[ Cmd.map FormMsg fc
|
[ Cmd.map FormMsg fc
|
||||||
, Ports.initClipboard appClipboardData
|
, Ports.initClipboard appClipboardData
|
||||||
, Ports.initClipboard apiClipboardData
|
, Ports.initClipboard apiClipboardData
|
||||||
|
, Api.getSources flags SourceResp
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ module Comp.TagManage exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
, emptyModel
|
, emptyModel
|
||||||
|
, init
|
||||||
, update
|
, update
|
||||||
, view2
|
, view2
|
||||||
)
|
)
|
||||||
@ -73,6 +74,11 @@ emptyModel =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
( emptyModel, Api.getTags flags emptyModel.query emptyModel.order (TagResp emptyModel.query) )
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= TableMsg Comp.TagTable.Msg
|
= TableMsg Comp.TagTable.Msg
|
||||||
| FormMsg Comp.TagForm.Msg
|
| FormMsg Comp.TagForm.Msg
|
||||||
|
@ -546,7 +546,7 @@ viewTagItem2 ddm settings model tag =
|
|||||||
Data.UiSettings.tagColorFg2 tag.tag settings
|
Data.UiSettings.tagColorFg2 tag.tag settings
|
||||||
|
|
||||||
icon =
|
icon =
|
||||||
getIcon2 state color I.tagIcon2
|
getIcon2 state color I.tagIcon
|
||||||
|
|
||||||
dropActive =
|
dropActive =
|
||||||
DD.getDropId ddm == Just (DD.Tag tag.tag.id)
|
DD.getDropId ddm == Just (DD.Tag tag.tag.id)
|
||||||
@ -587,7 +587,7 @@ viewCategoryItem2 settings model cat =
|
|||||||
Data.UiSettings.catColorFg2 settings cat.name
|
Data.UiSettings.catColorFg2 settings cat.name
|
||||||
|
|
||||||
icon =
|
icon =
|
||||||
getIcon2 state color I.tagsIcon2
|
getIcon2 state color I.tagsIcon
|
||||||
in
|
in
|
||||||
a
|
a
|
||||||
[ class "flex flex-row items-center"
|
[ class "flex flex-row items-center"
|
||||||
|
572
modules/webapp/src/main/elm/Comp/UploadForm.elm
Normal file
572
modules/webapp/src/main/elm/Comp/UploadForm.elm
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
type alias ViewSettings =
|
||||||
|
{ showForm : Bool
|
||||||
|
, sourceId : Maybe String
|
||||||
|
, lightForm : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> ViewSettings -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts viewCfg _ _ model =
|
||||||
|
let
|
||||||
|
showForm =
|
||||||
|
viewCfg.sourceId == Nothing && viewCfg.showForm
|
||||||
|
|
||||||
|
dropzoneCfg =
|
||||||
|
{ light = viewCfg.lightForm
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "mx-auto" ]
|
||||||
|
[ div [ class "px-0 flex flex-col" ]
|
||||||
|
[ if showForm then
|
||||||
|
div [ class "mb-4" ]
|
||||||
|
[ renderForm texts model
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
span [ class "hidden" ] []
|
||||||
|
, div [ class "py-0" ]
|
||||||
|
[ Html.map DropzoneMsg
|
||||||
|
(Comp.Dropzone.view2 texts.dropzone dropzoneCfg 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 viewCfg.sourceId) 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)
|
||||||
|
]
|
||||||
|
]
|
33
modules/webapp/src/main/elm/Data/AccountScope.elm
Normal file
33
modules/webapp/src/main/elm/Data/AccountScope.elm
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.AccountScope exposing (..)
|
||||||
|
|
||||||
|
|
||||||
|
type AccountScope
|
||||||
|
= User
|
||||||
|
| Collective
|
||||||
|
|
||||||
|
|
||||||
|
fold : a -> a -> AccountScope -> a
|
||||||
|
fold user coll scope =
|
||||||
|
case scope of
|
||||||
|
User ->
|
||||||
|
user
|
||||||
|
|
||||||
|
Collective ->
|
||||||
|
coll
|
||||||
|
|
||||||
|
|
||||||
|
isUser : AccountScope -> Bool
|
||||||
|
isUser scope =
|
||||||
|
fold True False scope
|
||||||
|
|
||||||
|
|
||||||
|
isCollective : AccountScope -> Bool
|
||||||
|
isCollective scope =
|
||||||
|
fold False True scope
|
@ -11,6 +11,7 @@ module Data.Bookmarks exposing
|
|||||||
, bookmarksDecoder
|
, bookmarksDecoder
|
||||||
, empty
|
, empty
|
||||||
, exists
|
, exists
|
||||||
|
, findById
|
||||||
, sort
|
, sort
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,6 +35,12 @@ type alias Bookmarks =
|
|||||||
List BookmarkedQuery
|
List BookmarkedQuery
|
||||||
|
|
||||||
|
|
||||||
|
findById : String -> Bookmarks -> Maybe BookmarkedQuery
|
||||||
|
findById id all =
|
||||||
|
List.filter (\e -> e.id == id) all
|
||||||
|
|> List.head
|
||||||
|
|
||||||
|
|
||||||
{-| Checks wether a bookmark of this name already exists.
|
{-| Checks wether a bookmark of this name already exists.
|
||||||
-}
|
-}
|
||||||
exists : String -> Bookmarks -> Bool
|
exists : String -> Bookmarks -> Bool
|
||||||
|
81
modules/webapp/src/main/elm/Data/Box.elm
Normal file
81
modules/webapp/src/main/elm/Data/Box.elm
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.Box exposing (Box, boxIcon, decoder, empty, encode, messageBox, queryBox, statsBox, uploadBox)
|
||||||
|
|
||||||
|
import Data.BoxContent exposing (BoxContent(..))
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
type alias Box =
|
||||||
|
{ name : String
|
||||||
|
, visible : Bool
|
||||||
|
, decoration : Bool
|
||||||
|
, colspan : Int
|
||||||
|
, content : BoxContent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
empty : BoxContent -> Box
|
||||||
|
empty cnt =
|
||||||
|
{ name = ""
|
||||||
|
, visible = True
|
||||||
|
, decoration = True
|
||||||
|
, colspan = 1
|
||||||
|
, content = cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boxIcon : Box -> String
|
||||||
|
boxIcon box =
|
||||||
|
Data.BoxContent.boxContentIcon box.content
|
||||||
|
|
||||||
|
|
||||||
|
queryBox : Box
|
||||||
|
queryBox =
|
||||||
|
empty (BoxQuery Data.BoxContent.emptyQueryData)
|
||||||
|
|
||||||
|
|
||||||
|
statsBox : Box
|
||||||
|
statsBox =
|
||||||
|
empty (BoxStats Data.BoxContent.emptyStatsData)
|
||||||
|
|
||||||
|
|
||||||
|
messageBox : Box
|
||||||
|
messageBox =
|
||||||
|
empty (BoxMessage Data.BoxContent.emptyMessageData)
|
||||||
|
|
||||||
|
|
||||||
|
uploadBox : Box
|
||||||
|
uploadBox =
|
||||||
|
empty (BoxUpload Data.BoxContent.emptyUploadData)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- JSON
|
||||||
|
|
||||||
|
|
||||||
|
decoder : D.Decoder Box
|
||||||
|
decoder =
|
||||||
|
D.map5 Box
|
||||||
|
(D.field "name" D.string)
|
||||||
|
(D.field "visible" D.bool)
|
||||||
|
(D.field "decoration" D.bool)
|
||||||
|
(D.field "colspan" D.int)
|
||||||
|
(D.field "content" Data.BoxContent.boxContentDecoder)
|
||||||
|
|
||||||
|
|
||||||
|
encode : Box -> E.Value
|
||||||
|
encode box =
|
||||||
|
E.object
|
||||||
|
[ ( "name", E.string box.name )
|
||||||
|
, ( "visible", E.bool box.visible )
|
||||||
|
, ( "decoration", E.bool box.decoration )
|
||||||
|
, ( "colspan", E.int box.colspan )
|
||||||
|
, ( "content", Data.BoxContent.boxContentEncode box.content )
|
||||||
|
]
|
319
modules/webapp/src/main/elm/Data/BoxContent.elm
Normal file
319
modules/webapp/src/main/elm/Data/BoxContent.elm
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.BoxContent exposing
|
||||||
|
( BoxContent(..)
|
||||||
|
, MessageData
|
||||||
|
, QueryData
|
||||||
|
, SearchQuery(..)
|
||||||
|
, StatsData
|
||||||
|
, SummaryShow(..)
|
||||||
|
, UploadData
|
||||||
|
, boxContentDecoder
|
||||||
|
, boxContentEncode
|
||||||
|
, boxContentIcon
|
||||||
|
, emptyMessageData
|
||||||
|
, emptyQueryData
|
||||||
|
, emptyStatsData
|
||||||
|
, emptyUploadData
|
||||||
|
)
|
||||||
|
|
||||||
|
import Data.ItemColumn exposing (ItemColumn)
|
||||||
|
import Html exposing (datalist)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
type BoxContent
|
||||||
|
= BoxUpload UploadData
|
||||||
|
| BoxMessage MessageData
|
||||||
|
| BoxQuery QueryData
|
||||||
|
| BoxStats StatsData
|
||||||
|
|
||||||
|
|
||||||
|
type alias MessageData =
|
||||||
|
{ title : String
|
||||||
|
, body : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyMessageData : MessageData
|
||||||
|
emptyMessageData =
|
||||||
|
{ title = ""
|
||||||
|
, body = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias UploadData =
|
||||||
|
{ sourceId : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyUploadData : UploadData
|
||||||
|
emptyUploadData =
|
||||||
|
{ sourceId = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias QueryData =
|
||||||
|
{ query : SearchQuery
|
||||||
|
, limit : Int
|
||||||
|
, details : Bool
|
||||||
|
, columns : List ItemColumn
|
||||||
|
, showHeaders : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyQueryData : QueryData
|
||||||
|
emptyQueryData =
|
||||||
|
{ query = SearchQueryString ""
|
||||||
|
, limit = 5
|
||||||
|
, details = True
|
||||||
|
, columns = []
|
||||||
|
, showHeaders = True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias StatsData =
|
||||||
|
{ query : SearchQuery
|
||||||
|
, show : SummaryShow
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyStatsData : StatsData
|
||||||
|
emptyStatsData =
|
||||||
|
{ query = SearchQueryString ""
|
||||||
|
, show = SummaryShowGeneral
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type SummaryShow
|
||||||
|
= SummaryShowFields Bool
|
||||||
|
| SummaryShowGeneral
|
||||||
|
|
||||||
|
|
||||||
|
type SearchQuery
|
||||||
|
= SearchQueryString String
|
||||||
|
| SearchQueryBookmark String
|
||||||
|
|
||||||
|
|
||||||
|
searchQueryAsString : SearchQuery -> String
|
||||||
|
searchQueryAsString q =
|
||||||
|
case q of
|
||||||
|
SearchQueryBookmark id ->
|
||||||
|
"bookmark:" ++ id
|
||||||
|
|
||||||
|
SearchQueryString str ->
|
||||||
|
"query:" ++ str
|
||||||
|
|
||||||
|
|
||||||
|
searchQueryFromString : String -> Maybe SearchQuery
|
||||||
|
searchQueryFromString str =
|
||||||
|
if String.startsWith "bookmark:" str then
|
||||||
|
Just (SearchQueryBookmark <| String.dropLeft 9 str)
|
||||||
|
|
||||||
|
else if String.startsWith "query:" str then
|
||||||
|
Just (SearchQueryString <| String.dropLeft 6 str)
|
||||||
|
|
||||||
|
else
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
boxContentIcon : BoxContent -> String
|
||||||
|
boxContentIcon content =
|
||||||
|
case content of
|
||||||
|
BoxMessage _ ->
|
||||||
|
"fa fa-comment-alt font-thin"
|
||||||
|
|
||||||
|
BoxUpload _ ->
|
||||||
|
"fa fa-file-upload"
|
||||||
|
|
||||||
|
BoxQuery _ ->
|
||||||
|
"fa fa-search"
|
||||||
|
|
||||||
|
BoxStats _ ->
|
||||||
|
"fa fa-chart-bar font-thin"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- JSON
|
||||||
|
|
||||||
|
|
||||||
|
boxContentDecoder : D.Decoder BoxContent
|
||||||
|
boxContentDecoder =
|
||||||
|
let
|
||||||
|
from discr =
|
||||||
|
case String.toLower discr of
|
||||||
|
"message" ->
|
||||||
|
D.field "data" <|
|
||||||
|
D.map BoxMessage messageDataDecoder
|
||||||
|
|
||||||
|
"upload" ->
|
||||||
|
D.field "data" <|
|
||||||
|
D.map BoxUpload uploadDataDecoder
|
||||||
|
|
||||||
|
"query" ->
|
||||||
|
D.field "data" <|
|
||||||
|
D.map BoxQuery queryDataDecoder
|
||||||
|
|
||||||
|
"stats" ->
|
||||||
|
D.field "data" <|
|
||||||
|
D.map BoxStats statsDataDecoder
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
D.fail ("Unknown box content: " ++ discr)
|
||||||
|
in
|
||||||
|
D.andThen from (D.field discriminator D.string)
|
||||||
|
|
||||||
|
|
||||||
|
boxContentEncode : BoxContent -> E.Value
|
||||||
|
boxContentEncode cnt =
|
||||||
|
case cnt of
|
||||||
|
BoxMessage data ->
|
||||||
|
E.object
|
||||||
|
[ ( discriminator, E.string "message" )
|
||||||
|
, ( "data", messageDataEncode data )
|
||||||
|
]
|
||||||
|
|
||||||
|
BoxUpload data ->
|
||||||
|
E.object
|
||||||
|
[ ( discriminator, E.string "upload" )
|
||||||
|
, ( "data", uploadDataEncode data )
|
||||||
|
]
|
||||||
|
|
||||||
|
BoxQuery data ->
|
||||||
|
E.object
|
||||||
|
[ ( discriminator, E.string "query" )
|
||||||
|
, ( "data", queryDataEncode data )
|
||||||
|
]
|
||||||
|
|
||||||
|
BoxStats data ->
|
||||||
|
E.object
|
||||||
|
[ ( discriminator, E.string "stats" )
|
||||||
|
, ( "data", statsDataEncode data )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
messageDataDecoder : D.Decoder MessageData
|
||||||
|
messageDataDecoder =
|
||||||
|
D.map2 MessageData
|
||||||
|
(D.field "title" D.string)
|
||||||
|
(D.field "body" D.string)
|
||||||
|
|
||||||
|
|
||||||
|
messageDataEncode : MessageData -> E.Value
|
||||||
|
messageDataEncode data =
|
||||||
|
E.object
|
||||||
|
[ ( "title", E.string data.title )
|
||||||
|
, ( "body", E.string data.body )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
uploadDataDecoder : D.Decoder UploadData
|
||||||
|
uploadDataDecoder =
|
||||||
|
D.map UploadData
|
||||||
|
(D.maybe (D.field "sourceId" D.string))
|
||||||
|
|
||||||
|
|
||||||
|
uploadDataEncode : UploadData -> E.Value
|
||||||
|
uploadDataEncode data =
|
||||||
|
E.object
|
||||||
|
[ ( "sourceId", Maybe.map E.string data.sourceId |> Maybe.withDefault E.null )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
queryDataDecoder : D.Decoder QueryData
|
||||||
|
queryDataDecoder =
|
||||||
|
D.map5 QueryData
|
||||||
|
(D.field "query" searchQueryDecoder)
|
||||||
|
(D.field "limit" D.int)
|
||||||
|
(D.field "details" D.bool)
|
||||||
|
(D.field "columns" <| D.list Data.ItemColumn.decode)
|
||||||
|
(D.field "showHeaders" D.bool)
|
||||||
|
|
||||||
|
|
||||||
|
queryDataEncode : QueryData -> E.Value
|
||||||
|
queryDataEncode data =
|
||||||
|
E.object
|
||||||
|
[ ( "query", searchQueryEncode data.query )
|
||||||
|
, ( "limit", E.int data.limit )
|
||||||
|
, ( "details", E.bool data.details )
|
||||||
|
, ( "columns", E.list Data.ItemColumn.encode data.columns )
|
||||||
|
, ( "showHeaders", E.bool data.showHeaders )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
statsDataDecoder : D.Decoder StatsData
|
||||||
|
statsDataDecoder =
|
||||||
|
D.map2 StatsData
|
||||||
|
(D.field "query" searchQueryDecoder)
|
||||||
|
(D.field "show" summaryShowDecoder)
|
||||||
|
|
||||||
|
|
||||||
|
statsDataEncode : StatsData -> E.Value
|
||||||
|
statsDataEncode data =
|
||||||
|
E.object
|
||||||
|
[ ( "query", searchQueryEncode data.query )
|
||||||
|
, ( "show", summaryShowEncode data.show )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
searchQueryDecoder : D.Decoder SearchQuery
|
||||||
|
searchQueryDecoder =
|
||||||
|
let
|
||||||
|
fromString str =
|
||||||
|
case searchQueryFromString str of
|
||||||
|
Just q ->
|
||||||
|
D.succeed q
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
D.fail ("Invalid search query: " ++ str)
|
||||||
|
in
|
||||||
|
D.andThen fromString D.string
|
||||||
|
|
||||||
|
|
||||||
|
searchQueryEncode : SearchQuery -> E.Value
|
||||||
|
searchQueryEncode q =
|
||||||
|
E.string (searchQueryAsString q)
|
||||||
|
|
||||||
|
|
||||||
|
summaryShowDecoder : D.Decoder SummaryShow
|
||||||
|
summaryShowDecoder =
|
||||||
|
let
|
||||||
|
decode discr =
|
||||||
|
case String.toLower discr of
|
||||||
|
"fields" ->
|
||||||
|
D.field "showItemCount" D.bool
|
||||||
|
|> D.map SummaryShowFields
|
||||||
|
|
||||||
|
"general" ->
|
||||||
|
D.succeed SummaryShowGeneral
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
D.fail ("Unknown summary show for: " ++ discr)
|
||||||
|
in
|
||||||
|
D.andThen decode (D.field discriminator D.string)
|
||||||
|
|
||||||
|
|
||||||
|
summaryShowEncode : SummaryShow -> E.Value
|
||||||
|
summaryShowEncode show =
|
||||||
|
case show of
|
||||||
|
SummaryShowFields flag ->
|
||||||
|
E.object
|
||||||
|
[ ( discriminator, E.string "fields" )
|
||||||
|
, ( "showItemCount", E.bool flag )
|
||||||
|
]
|
||||||
|
|
||||||
|
SummaryShowGeneral ->
|
||||||
|
E.object
|
||||||
|
[ ( "discriminator", E.string "general" )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
discriminator : String
|
||||||
|
discriminator =
|
||||||
|
"discriminator"
|
57
modules/webapp/src/main/elm/Data/Dashboard.elm
Normal file
57
modules/webapp/src/main/elm/Data/Dashboard.elm
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.Dashboard exposing (Dashboard, decoder, empty, encode, isEmpty)
|
||||||
|
|
||||||
|
import Data.Box exposing (Box)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
type alias Dashboard =
|
||||||
|
{ name : String
|
||||||
|
, columns : Int
|
||||||
|
, gap : Int
|
||||||
|
, boxes : List Box
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
empty : Dashboard
|
||||||
|
empty =
|
||||||
|
{ name = ""
|
||||||
|
, columns = 1
|
||||||
|
, gap = 2
|
||||||
|
, boxes = []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isEmpty : Dashboard -> Bool
|
||||||
|
isEmpty board =
|
||||||
|
List.isEmpty board.boxes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- JSON
|
||||||
|
|
||||||
|
|
||||||
|
encode : Dashboard -> E.Value
|
||||||
|
encode b =
|
||||||
|
E.object
|
||||||
|
[ ( "name", E.string b.name )
|
||||||
|
, ( "columns", E.int b.columns )
|
||||||
|
, ( "gap", E.int b.gap )
|
||||||
|
, ( "boxes", E.list Data.Box.encode b.boxes )
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
decoder : D.Decoder Dashboard
|
||||||
|
decoder =
|
||||||
|
D.map4 Dashboard
|
||||||
|
(D.field "name" D.string)
|
||||||
|
(D.field "columns" D.int)
|
||||||
|
(D.field "gap" D.int)
|
||||||
|
(D.field "boxes" <| D.list Data.Box.decoder)
|
296
modules/webapp/src/main/elm/Data/Dashboards.elm
Normal file
296
modules/webapp/src/main/elm/Data/Dashboards.elm
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.Dashboards exposing
|
||||||
|
( AllDashboards
|
||||||
|
, Dashboards
|
||||||
|
, countAll
|
||||||
|
, decoder
|
||||||
|
, empty
|
||||||
|
, emptyAll
|
||||||
|
, encode
|
||||||
|
, exists
|
||||||
|
, existsAll
|
||||||
|
, find
|
||||||
|
, findInAll
|
||||||
|
, foldl
|
||||||
|
, getAllDefault
|
||||||
|
, getDefault
|
||||||
|
, getScope
|
||||||
|
, insert
|
||||||
|
, insertIn
|
||||||
|
, isDefaultAll
|
||||||
|
, isEmpty
|
||||||
|
, isEmptyAll
|
||||||
|
, map
|
||||||
|
, remove
|
||||||
|
, removeFromAll
|
||||||
|
, selectBoards
|
||||||
|
, setDefaultAll
|
||||||
|
, singleton
|
||||||
|
, singletonAll
|
||||||
|
, unsetDefaultAll
|
||||||
|
)
|
||||||
|
|
||||||
|
import Data.AccountScope exposing (AccountScope)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
import Util.Maybe
|
||||||
|
|
||||||
|
|
||||||
|
type Dashboards
|
||||||
|
= Dashboards Info
|
||||||
|
|
||||||
|
|
||||||
|
empty : Dashboards
|
||||||
|
empty =
|
||||||
|
Dashboards { default = "", boards = Dict.empty }
|
||||||
|
|
||||||
|
|
||||||
|
isEmpty : Dashboards -> Bool
|
||||||
|
isEmpty (Dashboards info) =
|
||||||
|
Dict.isEmpty info.boards
|
||||||
|
|
||||||
|
|
||||||
|
insert : Dashboard -> Dashboards -> Dashboards
|
||||||
|
insert board (Dashboards info) =
|
||||||
|
let
|
||||||
|
nb =
|
||||||
|
Dict.insert (String.toLower board.name) board info.boards
|
||||||
|
in
|
||||||
|
Dashboards { info | boards = nb }
|
||||||
|
|
||||||
|
|
||||||
|
singleton : Dashboard -> Dashboards
|
||||||
|
singleton board =
|
||||||
|
insert board empty
|
||||||
|
|
||||||
|
|
||||||
|
remove : String -> Dashboards -> Dashboards
|
||||||
|
remove name (Dashboards info) =
|
||||||
|
let
|
||||||
|
nb =
|
||||||
|
Dict.remove (String.toLower name) info.boards
|
||||||
|
in
|
||||||
|
Dashboards { info | boards = nb }
|
||||||
|
|
||||||
|
|
||||||
|
map : (Dashboard -> a) -> Dashboards -> List a
|
||||||
|
map f (Dashboards info) =
|
||||||
|
List.map f (Dict.values info.boards)
|
||||||
|
|
||||||
|
|
||||||
|
find : String -> Dashboards -> Maybe Dashboard
|
||||||
|
find name (Dashboards info) =
|
||||||
|
Dict.get (String.toLower name) info.boards
|
||||||
|
|
||||||
|
|
||||||
|
foldl : (Dashboard -> a -> a) -> a -> Dashboards -> a
|
||||||
|
foldl f init (Dashboards info) =
|
||||||
|
List.foldl f init (Dict.values info.boards)
|
||||||
|
|
||||||
|
|
||||||
|
exists : String -> Dashboards -> Bool
|
||||||
|
exists name (Dashboards info) =
|
||||||
|
Dict.member (String.toLower name) info.boards
|
||||||
|
|
||||||
|
|
||||||
|
getDefault : Dashboards -> Maybe Dashboard
|
||||||
|
getDefault (Dashboards info) =
|
||||||
|
Dict.get (String.toLower info.default) info.boards
|
||||||
|
|
||||||
|
|
||||||
|
isDefault : String -> Dashboards -> Bool
|
||||||
|
isDefault name (Dashboards info) =
|
||||||
|
String.toLower name == String.toLower info.default
|
||||||
|
|
||||||
|
|
||||||
|
setDefault : String -> Dashboards -> Dashboards
|
||||||
|
setDefault name (Dashboards info) =
|
||||||
|
Dashboards { info | default = String.toLower name }
|
||||||
|
|
||||||
|
|
||||||
|
unsetDefault : String -> Dashboards -> Dashboards
|
||||||
|
unsetDefault name dbs =
|
||||||
|
if isDefault name dbs then
|
||||||
|
setDefault "" dbs
|
||||||
|
|
||||||
|
else
|
||||||
|
dbs
|
||||||
|
|
||||||
|
|
||||||
|
getFirst : Dashboards -> Maybe Dashboard
|
||||||
|
getFirst (Dashboards info) =
|
||||||
|
List.head (Dict.values info.boards)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- AllDashboards
|
||||||
|
|
||||||
|
|
||||||
|
type alias AllDashboards =
|
||||||
|
{ collective : Dashboards
|
||||||
|
, user : Dashboards
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyAll : AllDashboards
|
||||||
|
emptyAll =
|
||||||
|
AllDashboards empty empty
|
||||||
|
|
||||||
|
|
||||||
|
isEmptyAll : AllDashboards -> Bool
|
||||||
|
isEmptyAll all =
|
||||||
|
isEmpty all.collective && isEmpty all.user
|
||||||
|
|
||||||
|
|
||||||
|
insertIn : AccountScope -> Dashboard -> AllDashboards -> AllDashboards
|
||||||
|
insertIn scope board all =
|
||||||
|
Data.AccountScope.fold
|
||||||
|
{ user = insert board all.user
|
||||||
|
, collective = all.collective
|
||||||
|
}
|
||||||
|
{ user = all.user
|
||||||
|
, collective = insert board all.collective
|
||||||
|
}
|
||||||
|
scope
|
||||||
|
|
||||||
|
|
||||||
|
selectBoards : AccountScope -> AllDashboards -> Dashboards
|
||||||
|
selectBoards scope all =
|
||||||
|
Data.AccountScope.fold all.user all.collective scope
|
||||||
|
|
||||||
|
|
||||||
|
getAllDefault : AllDashboards -> Maybe Dashboard
|
||||||
|
getAllDefault boards =
|
||||||
|
Util.Maybe.or
|
||||||
|
[ getDefault boards.user
|
||||||
|
, getDefault boards.collective
|
||||||
|
, getFirst boards.user
|
||||||
|
, getFirst boards.collective
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
existsAll : String -> AllDashboards -> Bool
|
||||||
|
existsAll name boards =
|
||||||
|
exists name boards.collective || exists name boards.user
|
||||||
|
|
||||||
|
|
||||||
|
singletonAll : Dashboard -> AllDashboards
|
||||||
|
singletonAll board =
|
||||||
|
AllDashboards empty (singleton board)
|
||||||
|
|
||||||
|
|
||||||
|
isDefaultAll : String -> AllDashboards -> Bool
|
||||||
|
isDefaultAll name all =
|
||||||
|
isDefault name all.user || isDefault name all.collective
|
||||||
|
|
||||||
|
|
||||||
|
findInAll : String -> AllDashboards -> Maybe Dashboard
|
||||||
|
findInAll name all =
|
||||||
|
Util.Maybe.or
|
||||||
|
[ find name all.user
|
||||||
|
, find name all.collective
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
removeFromAll : String -> AllDashboards -> AllDashboards
|
||||||
|
removeFromAll name all =
|
||||||
|
{ user = remove name all.user
|
||||||
|
, collective = remove name all.collective
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setDefaultAll : String -> AllDashboards -> AllDashboards
|
||||||
|
setDefaultAll name all =
|
||||||
|
if isDefaultAll name all then
|
||||||
|
all
|
||||||
|
|
||||||
|
else
|
||||||
|
{ user = setDefault name all.user
|
||||||
|
, collective = setDefault name all.collective
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsetDefaultAll : String -> AllDashboards -> AllDashboards
|
||||||
|
unsetDefaultAll name all =
|
||||||
|
if isDefaultAll name all then
|
||||||
|
{ user = unsetDefault name all.user
|
||||||
|
, collective = unsetDefault name all.collective
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
all
|
||||||
|
|
||||||
|
|
||||||
|
getScope : String -> AllDashboards -> Maybe AccountScope
|
||||||
|
getScope name all =
|
||||||
|
if exists name all.user then
|
||||||
|
Just Data.AccountScope.User
|
||||||
|
|
||||||
|
else if exists name all.collective then
|
||||||
|
Just Data.AccountScope.Collective
|
||||||
|
|
||||||
|
else
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
countAll : AllDashboards -> Int
|
||||||
|
countAll all =
|
||||||
|
List.sum
|
||||||
|
[ foldl (\_ -> \n -> n + 1) 0 all.user
|
||||||
|
, foldl (\_ -> \n -> n + 1) 0 all.collective
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helper
|
||||||
|
|
||||||
|
|
||||||
|
type alias Info =
|
||||||
|
{ boards : Dict String Dashboard
|
||||||
|
, default : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- JSON
|
||||||
|
|
||||||
|
|
||||||
|
decoder : D.Decoder Dashboards
|
||||||
|
decoder =
|
||||||
|
D.oneOf
|
||||||
|
[ D.map Dashboards infoDecoder
|
||||||
|
, emptyObjectDecoder
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
encode : Dashboards -> E.Value
|
||||||
|
encode (Dashboards info) =
|
||||||
|
infoEncode info
|
||||||
|
|
||||||
|
|
||||||
|
infoDecoder : D.Decoder Info
|
||||||
|
infoDecoder =
|
||||||
|
D.map2 Info
|
||||||
|
(D.field "boards" <| D.dict Data.Dashboard.decoder)
|
||||||
|
(D.field "default" D.string)
|
||||||
|
|
||||||
|
|
||||||
|
emptyObjectDecoder : D.Decoder Dashboards
|
||||||
|
emptyObjectDecoder =
|
||||||
|
D.dict (D.fail "non-empty") |> D.map (\_ -> empty)
|
||||||
|
|
||||||
|
|
||||||
|
infoEncode : Info -> E.Value
|
||||||
|
infoEncode info =
|
||||||
|
E.object
|
||||||
|
[ ( "boards", E.dict identity Data.Dashboard.encode info.boards )
|
||||||
|
, ( "default", E.string info.default )
|
||||||
|
]
|
@ -25,6 +25,7 @@ module Data.Icons exposing
|
|||||||
, customFieldTypeIcon
|
, customFieldTypeIcon
|
||||||
, customFieldTypeIconString
|
, customFieldTypeIconString
|
||||||
, customFieldTypeIconString2
|
, customFieldTypeIconString2
|
||||||
|
, dashboardIcon
|
||||||
, date
|
, date
|
||||||
, date2
|
, date2
|
||||||
, dateIcon
|
, dateIcon
|
||||||
@ -33,31 +34,30 @@ module Data.Icons exposing
|
|||||||
, direction2
|
, direction2
|
||||||
, directionIcon
|
, directionIcon
|
||||||
, directionIcon2
|
, directionIcon2
|
||||||
|
, documentationIcon
|
||||||
, dueDate
|
, dueDate
|
||||||
, dueDate2
|
, dueDate2
|
||||||
, dueDateIcon
|
, dueDateIcon
|
||||||
, dueDateIcon2
|
, dueDateIcon2
|
||||||
, editNotes
|
, editIcon
|
||||||
, editNotesIcon
|
|
||||||
, equipment
|
, equipment
|
||||||
, equipment2
|
|
||||||
, equipmentIcon
|
, equipmentIcon
|
||||||
, equipmentIcon2
|
, fileUploadIcon
|
||||||
, folder
|
, folder
|
||||||
, folder2
|
|
||||||
, folderIcon
|
, folderIcon
|
||||||
, folderIcon2
|
|
||||||
, gotifyIcon
|
, gotifyIcon
|
||||||
, itemDatesIcon
|
, itemDatesIcon
|
||||||
, matrixIcon
|
, matrixIcon
|
||||||
|
, metadata
|
||||||
|
, metadataIcon
|
||||||
|
, notificationHooks
|
||||||
|
, notificationHooksIcon
|
||||||
, organization
|
, organization
|
||||||
, organization2
|
|
||||||
, organizationIcon
|
, organizationIcon
|
||||||
, organizationIcon2
|
, periodicTasks
|
||||||
|
, periodicTasksIcon
|
||||||
, person
|
, person
|
||||||
, person2
|
|
||||||
, personIcon
|
, personIcon
|
||||||
, personIcon2
|
|
||||||
, search
|
, search
|
||||||
, searchIcon
|
, searchIcon
|
||||||
, share
|
, share
|
||||||
@ -67,11 +67,9 @@ module Data.Icons exposing
|
|||||||
, source2
|
, source2
|
||||||
, sourceIcon2
|
, sourceIcon2
|
||||||
, tag
|
, tag
|
||||||
, tag2
|
|
||||||
, tagIcon
|
, tagIcon
|
||||||
, tagIcon2
|
, tags
|
||||||
, tags2
|
, tagsIcon
|
||||||
, tagsIcon2
|
|
||||||
, trash
|
, trash
|
||||||
, trashIcon
|
, trashIcon
|
||||||
)
|
)
|
||||||
@ -83,6 +81,56 @@ import Svg
|
|||||||
import Svg.Attributes as SA
|
import Svg.Attributes as SA
|
||||||
|
|
||||||
|
|
||||||
|
documentation : String
|
||||||
|
documentation =
|
||||||
|
"fa fa-question-circle"
|
||||||
|
|
||||||
|
|
||||||
|
documentationIcon : String -> Html msg
|
||||||
|
documentationIcon classes =
|
||||||
|
i [ class classes, class documentation ] []
|
||||||
|
|
||||||
|
|
||||||
|
dashboard : String
|
||||||
|
dashboard =
|
||||||
|
"fa fa-house-user"
|
||||||
|
|
||||||
|
|
||||||
|
dashboardIcon : String -> Html msg
|
||||||
|
dashboardIcon classes =
|
||||||
|
i [ class classes, class dashboard ] []
|
||||||
|
|
||||||
|
|
||||||
|
periodicTasks : String
|
||||||
|
periodicTasks =
|
||||||
|
"fa fa-history"
|
||||||
|
|
||||||
|
|
||||||
|
periodicTasksIcon : String -> Html msg
|
||||||
|
periodicTasksIcon classes =
|
||||||
|
i [ class classes, class periodicTasks ] []
|
||||||
|
|
||||||
|
|
||||||
|
notificationHooks : String
|
||||||
|
notificationHooks =
|
||||||
|
"fa fa-comment font-thin"
|
||||||
|
|
||||||
|
|
||||||
|
notificationHooksIcon : String -> Html msg
|
||||||
|
notificationHooksIcon classes =
|
||||||
|
i [ class classes, class notificationHooks ] []
|
||||||
|
|
||||||
|
|
||||||
|
metadata : String
|
||||||
|
metadata =
|
||||||
|
"fa fa-cubes"
|
||||||
|
|
||||||
|
|
||||||
|
metadataIcon : String -> Html msg
|
||||||
|
metadataIcon classes =
|
||||||
|
i [ class classes, class metadata ] []
|
||||||
|
|
||||||
|
|
||||||
trash : String
|
trash : String
|
||||||
trash =
|
trash =
|
||||||
"fa fa-trash-alt text-red-500 dark:text-orange-600"
|
"fa fa-trash-alt text-red-500 dark:text-orange-600"
|
||||||
@ -112,6 +160,16 @@ source2 =
|
|||||||
"fa fa-upload"
|
"fa fa-upload"
|
||||||
|
|
||||||
|
|
||||||
|
fileUpload : String
|
||||||
|
fileUpload =
|
||||||
|
"fa fa-file-upload"
|
||||||
|
|
||||||
|
|
||||||
|
fileUploadIcon : String -> Html msg
|
||||||
|
fileUploadIcon classes =
|
||||||
|
i [ class classes, class fileUpload ] []
|
||||||
|
|
||||||
|
|
||||||
sourceIcon2 : String -> Html msg
|
sourceIcon2 : String -> Html msg
|
||||||
sourceIcon2 classes =
|
sourceIcon2 classes =
|
||||||
i [ class (source2 ++ " " ++ classes) ] []
|
i [ class (source2 ++ " " ++ classes) ] []
|
||||||
@ -203,7 +261,7 @@ customFieldIcon2 classes =
|
|||||||
|
|
||||||
search : String
|
search : String
|
||||||
search =
|
search =
|
||||||
"search icon"
|
"fa fa-search"
|
||||||
|
|
||||||
|
|
||||||
searchIcon : String -> Html msg
|
searchIcon : String -> Html msg
|
||||||
@ -213,11 +271,6 @@ searchIcon classes =
|
|||||||
|
|
||||||
folder : String
|
folder : String
|
||||||
folder =
|
folder =
|
||||||
"folder outline icon"
|
|
||||||
|
|
||||||
|
|
||||||
folder2 : String
|
|
||||||
folder2 =
|
|
||||||
"fa fa-folder font-thin "
|
"fa fa-folder font-thin "
|
||||||
|
|
||||||
|
|
||||||
@ -226,11 +279,6 @@ folderIcon classes =
|
|||||||
i [ class (folder ++ " " ++ classes) ] []
|
i [ class (folder ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
folderIcon2 : String -> Html msg
|
|
||||||
folderIcon2 classes =
|
|
||||||
i [ class (folder2 ++ " " ++ classes) ] []
|
|
||||||
|
|
||||||
|
|
||||||
concerned : String
|
concerned : String
|
||||||
concerned =
|
concerned =
|
||||||
"crosshairs icon"
|
"crosshairs icon"
|
||||||
@ -329,14 +377,14 @@ dueDateIcon2 classes =
|
|||||||
i [ class (dueDate2 ++ " " ++ classes) ] []
|
i [ class (dueDate2 ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
editNotes : String
|
edit : String
|
||||||
editNotes =
|
edit =
|
||||||
"comment alternate outline icon"
|
"fa fa-edit font-thin"
|
||||||
|
|
||||||
|
|
||||||
editNotesIcon : Html msg
|
editIcon : String -> Html msg
|
||||||
editNotesIcon =
|
editIcon classes =
|
||||||
i [ class editNotes ] []
|
i [ class edit, class classes ] []
|
||||||
|
|
||||||
|
|
||||||
addFiles2 : String
|
addFiles2 : String
|
||||||
@ -361,11 +409,6 @@ showQrIcon classes =
|
|||||||
|
|
||||||
tag : String
|
tag : String
|
||||||
tag =
|
tag =
|
||||||
"tag icon"
|
|
||||||
|
|
||||||
|
|
||||||
tag2 : String
|
|
||||||
tag2 =
|
|
||||||
"fa fa-tag"
|
"fa fa-tag"
|
||||||
|
|
||||||
|
|
||||||
@ -374,19 +417,14 @@ tagIcon classes =
|
|||||||
i [ class (tag ++ " " ++ classes) ] []
|
i [ class (tag ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
tagIcon2 : String -> Html msg
|
tags : String
|
||||||
tagIcon2 classes =
|
tags =
|
||||||
i [ class (tag2 ++ " " ++ classes) ] []
|
|
||||||
|
|
||||||
|
|
||||||
tags2 : String
|
|
||||||
tags2 =
|
|
||||||
"fa fa-tags"
|
"fa fa-tags"
|
||||||
|
|
||||||
|
|
||||||
tagsIcon2 : String -> Html msg
|
tagsIcon : String -> Html msg
|
||||||
tagsIcon2 classes =
|
tagsIcon classes =
|
||||||
i [ class (tags2 ++ " " ++ classes) ] []
|
i [ class (tags ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
direction : String
|
direction : String
|
||||||
@ -411,11 +449,6 @@ directionIcon2 classes =
|
|||||||
|
|
||||||
person : String
|
person : String
|
||||||
person =
|
person =
|
||||||
"user icon"
|
|
||||||
|
|
||||||
|
|
||||||
person2 : String
|
|
||||||
person2 =
|
|
||||||
"fa fa-user"
|
"fa fa-user"
|
||||||
|
|
||||||
|
|
||||||
@ -424,18 +457,8 @@ personIcon classes =
|
|||||||
i [ class (person ++ " " ++ classes) ] []
|
i [ class (person ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
personIcon2 : String -> Html msg
|
|
||||||
personIcon2 classes =
|
|
||||||
i [ class (person2 ++ " " ++ classes) ] []
|
|
||||||
|
|
||||||
|
|
||||||
organization : String
|
organization : String
|
||||||
organization =
|
organization =
|
||||||
"factory icon"
|
|
||||||
|
|
||||||
|
|
||||||
organization2 : String
|
|
||||||
organization2 =
|
|
||||||
"fa fa-industry"
|
"fa fa-industry"
|
||||||
|
|
||||||
|
|
||||||
@ -444,18 +467,8 @@ organizationIcon classes =
|
|||||||
i [ class (organization ++ " " ++ classes) ] []
|
i [ class (organization ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
organizationIcon2 : String -> Html msg
|
|
||||||
organizationIcon2 classes =
|
|
||||||
i [ class (organization2 ++ " " ++ classes) ] []
|
|
||||||
|
|
||||||
|
|
||||||
equipment : String
|
equipment : String
|
||||||
equipment =
|
equipment =
|
||||||
"box icon"
|
|
||||||
|
|
||||||
|
|
||||||
equipment2 : String
|
|
||||||
equipment2 =
|
|
||||||
"fa fa-box"
|
"fa fa-box"
|
||||||
|
|
||||||
|
|
||||||
@ -464,11 +477,6 @@ equipmentIcon classes =
|
|||||||
i [ class (equipment ++ " " ++ classes) ] []
|
i [ class (equipment ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
equipmentIcon2 : String -> Html msg
|
|
||||||
equipmentIcon2 classes =
|
|
||||||
i [ class (equipment2 ++ " " ++ classes) ] []
|
|
||||||
|
|
||||||
|
|
||||||
matrixIcon : String -> Html msg
|
matrixIcon : String -> Html msg
|
||||||
matrixIcon classes =
|
matrixIcon classes =
|
||||||
Svg.svg
|
Svg.svg
|
||||||
|
146
modules/webapp/src/main/elm/Data/ItemColumn.elm
Normal file
146
modules/webapp/src/main/elm/Data/ItemColumn.elm
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.ItemColumn exposing (..)
|
||||||
|
|
||||||
|
import Api.Model.ItemLight exposing (ItemLight)
|
||||||
|
import Data.ItemTemplate as IT exposing (TemplateContext)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
type ItemColumn
|
||||||
|
= Name
|
||||||
|
| DateLong
|
||||||
|
| DateShort
|
||||||
|
| DueDateLong
|
||||||
|
| DueDateShort
|
||||||
|
| Folder
|
||||||
|
| Correspondent
|
||||||
|
| Concerning
|
||||||
|
| Tags
|
||||||
|
|
||||||
|
|
||||||
|
all : List ItemColumn
|
||||||
|
all =
|
||||||
|
[ Name, DateLong, DateShort, DueDateLong, DueDateShort, Folder, Correspondent, Concerning, Tags ]
|
||||||
|
|
||||||
|
|
||||||
|
renderString : TemplateContext -> ItemColumn -> ItemLight -> String
|
||||||
|
renderString ctx col item =
|
||||||
|
case col of
|
||||||
|
Name ->
|
||||||
|
IT.render IT.name ctx item
|
||||||
|
|
||||||
|
DateShort ->
|
||||||
|
IT.render IT.dateShort ctx item
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
IT.render IT.dateLong ctx item
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
IT.render IT.dueDateShort ctx item
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
IT.render IT.dueDateLong ctx item
|
||||||
|
|
||||||
|
Folder ->
|
||||||
|
IT.render IT.folder ctx item
|
||||||
|
|
||||||
|
Correspondent ->
|
||||||
|
IT.render IT.correspondent ctx item
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
IT.render IT.concerning ctx item
|
||||||
|
|
||||||
|
Tags ->
|
||||||
|
List.map .name item.tags
|
||||||
|
|> String.join ", "
|
||||||
|
|
||||||
|
|
||||||
|
asString : ItemColumn -> String
|
||||||
|
asString col =
|
||||||
|
case col of
|
||||||
|
Name ->
|
||||||
|
"name"
|
||||||
|
|
||||||
|
DateShort ->
|
||||||
|
"dateshort"
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
"datelong"
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
"duedateshort"
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
"duedatelong"
|
||||||
|
|
||||||
|
Folder ->
|
||||||
|
"folder"
|
||||||
|
|
||||||
|
Correspondent ->
|
||||||
|
"correspondent"
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
"concerning"
|
||||||
|
|
||||||
|
Tags ->
|
||||||
|
"tags"
|
||||||
|
|
||||||
|
|
||||||
|
fromString : String -> Maybe ItemColumn
|
||||||
|
fromString str =
|
||||||
|
case String.toLower str of
|
||||||
|
"name" ->
|
||||||
|
Just Name
|
||||||
|
|
||||||
|
"dateshort" ->
|
||||||
|
Just DateShort
|
||||||
|
|
||||||
|
"datelong" ->
|
||||||
|
Just DateLong
|
||||||
|
|
||||||
|
"duedateshort" ->
|
||||||
|
Just DueDateShort
|
||||||
|
|
||||||
|
"duedatelong" ->
|
||||||
|
Just DueDateLong
|
||||||
|
|
||||||
|
"folder" ->
|
||||||
|
Just Folder
|
||||||
|
|
||||||
|
"correspondent" ->
|
||||||
|
Just Correspondent
|
||||||
|
|
||||||
|
"concerning" ->
|
||||||
|
Just Concerning
|
||||||
|
|
||||||
|
"tags" ->
|
||||||
|
Just Tags
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
encode : ItemColumn -> E.Value
|
||||||
|
encode col =
|
||||||
|
asString col |> E.string
|
||||||
|
|
||||||
|
|
||||||
|
decode : D.Decoder ItemColumn
|
||||||
|
decode =
|
||||||
|
let
|
||||||
|
from str =
|
||||||
|
case fromString str of
|
||||||
|
Just col ->
|
||||||
|
D.succeed col
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
D.fail ("Invalid column: " ++ str)
|
||||||
|
in
|
||||||
|
D.andThen from D.string
|
@ -16,8 +16,10 @@ module Data.UiSettings exposing
|
|||||||
, catColorFg2
|
, catColorFg2
|
||||||
, catColorString2
|
, catColorString2
|
||||||
, defaults
|
, defaults
|
||||||
|
, documentationSite
|
||||||
, fieldHidden
|
, fieldHidden
|
||||||
, fieldVisible
|
, fieldVisible
|
||||||
|
, getUiLanguage
|
||||||
, merge
|
, merge
|
||||||
, mergeDefaults
|
, mergeDefaults
|
||||||
, pdfUrl
|
, pdfUrl
|
||||||
@ -93,6 +95,9 @@ storedUiSettingsDecoder =
|
|||||||
|
|
||||||
maybeString =
|
maybeString =
|
||||||
Decode.maybe Decode.string
|
Decode.maybe Decode.string
|
||||||
|
|
||||||
|
def =
|
||||||
|
defaults
|
||||||
in
|
in
|
||||||
Decode.succeed StoredUiSettings
|
Decode.succeed StoredUiSettings
|
||||||
|> P.optional "itemSearchPageSize" maybeInt Nothing
|
|> P.optional "itemSearchPageSize" maybeInt Nothing
|
||||||
@ -104,19 +109,19 @@ storedUiSettingsDecoder =
|
|||||||
|> P.optional "searchMenuTagCount" maybeInt Nothing
|
|> P.optional "searchMenuTagCount" maybeInt Nothing
|
||||||
|> P.optional "searchMenuTagCatCount" maybeInt Nothing
|
|> P.optional "searchMenuTagCatCount" maybeInt Nothing
|
||||||
|> P.optional "formFields" (Decode.maybe <| Decode.list Decode.string) Nothing
|
|> P.optional "formFields" (Decode.maybe <| Decode.list Decode.string) Nothing
|
||||||
|> P.optional "itemDetailShortcuts" Decode.bool False
|
|> P.optional "itemDetailShortcuts" Decode.bool def.itemDetailShortcuts
|
||||||
|> P.optional "searchMenuVisible" Decode.bool False
|
|> P.optional "searchMenuVisible" Decode.bool def.searchMenuVisible
|
||||||
|> P.optional "editMenuVisible" Decode.bool False
|
|> P.optional "editMenuVisible" Decode.bool def.editMenuVisible
|
||||||
|> P.optional "cardPreviewSize" maybeString Nothing
|
|> P.optional "cardPreviewSize" maybeString Nothing
|
||||||
|> P.optional "cardTitleTemplate" maybeString Nothing
|
|> P.optional "cardTitleTemplate" maybeString Nothing
|
||||||
|> P.optional "cardSubtitleTemplate" maybeString Nothing
|
|> P.optional "cardSubtitleTemplate" maybeString Nothing
|
||||||
|> P.optional "searchStatsVisible" Decode.bool False
|
|> P.optional "searchStatsVisible" Decode.bool def.searchStatsVisible
|
||||||
|> P.optional "cardPreviewFullWidth" Decode.bool False
|
|> P.optional "cardPreviewFullWidth" Decode.bool def.cardPreviewFullWidth
|
||||||
|> P.optional "uiTheme" maybeString Nothing
|
|> P.optional "uiTheme" maybeString Nothing
|
||||||
|> P.optional "sideMenuVisible" Decode.bool False
|
|> P.optional "sideMenuVisible" Decode.bool def.sideMenuVisible
|
||||||
|> P.optional "powerSearchEnabled" Decode.bool False
|
|> P.optional "powerSearchEnabled" Decode.bool def.powerSearchEnabled
|
||||||
|> P.optional "uiLang" maybeString Nothing
|
|> P.optional "uiLang" maybeString Nothing
|
||||||
|> P.optional "itemSearchShowGroups" Decode.bool True
|
|> P.optional "itemSearchShowGroups" Decode.bool def.itemSearchShowGroups
|
||||||
|> P.optional "itemSearchArrange" maybeString Nothing
|
|> P.optional "itemSearchArrange" maybeString Nothing
|
||||||
|
|
||||||
|
|
||||||
@ -444,6 +449,21 @@ pdfUrl settings flags originalUrl =
|
|||||||
Data.Pdf.serverUrl originalUrl
|
Data.Pdf.serverUrl originalUrl
|
||||||
|
|
||||||
|
|
||||||
|
getUiLanguage : Flags -> UiSettings -> UiLanguage -> UiLanguage
|
||||||
|
getUiLanguage flags settings default =
|
||||||
|
case flags.account of
|
||||||
|
Just _ ->
|
||||||
|
settings.uiLang
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
default
|
||||||
|
|
||||||
|
|
||||||
|
documentationSite : String
|
||||||
|
documentationSite =
|
||||||
|
"https://docspell.org/docs"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Helpers
|
--- Helpers
|
||||||
|
|
||||||
|
@ -14,13 +14,14 @@ module Messages exposing
|
|||||||
|
|
||||||
import Messages.App
|
import Messages.App
|
||||||
import Messages.Page.CollectiveSettings
|
import Messages.Page.CollectiveSettings
|
||||||
import Messages.Page.Home
|
import Messages.Page.Dashboard
|
||||||
import Messages.Page.ItemDetail
|
import Messages.Page.ItemDetail
|
||||||
import Messages.Page.Login
|
import Messages.Page.Login
|
||||||
import Messages.Page.ManageData
|
import Messages.Page.ManageData
|
||||||
import Messages.Page.NewInvite
|
import Messages.Page.NewInvite
|
||||||
import Messages.Page.Queue
|
import Messages.Page.Queue
|
||||||
import Messages.Page.Register
|
import Messages.Page.Register
|
||||||
|
import Messages.Page.Search
|
||||||
import Messages.Page.Share
|
import Messages.Page.Share
|
||||||
import Messages.Page.ShareDetail
|
import Messages.Page.ShareDetail
|
||||||
import Messages.Page.Upload
|
import Messages.Page.Upload
|
||||||
@ -45,9 +46,10 @@ type alias Messages =
|
|||||||
, queue : Messages.Page.Queue.Texts
|
, queue : Messages.Page.Queue.Texts
|
||||||
, userSettings : Messages.Page.UserSettings.Texts
|
, userSettings : Messages.Page.UserSettings.Texts
|
||||||
, manageData : Messages.Page.ManageData.Texts
|
, manageData : Messages.Page.ManageData.Texts
|
||||||
, home : Messages.Page.Home.Texts
|
, search : Messages.Page.Search.Texts
|
||||||
, share : Messages.Page.Share.Texts
|
, share : Messages.Page.Share.Texts
|
||||||
, shareDetail : Messages.Page.ShareDetail.Texts
|
, shareDetail : Messages.Page.ShareDetail.Texts
|
||||||
|
, dashboard : Messages.Page.Dashboard.Texts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,9 +114,10 @@ gb =
|
|||||||
, queue = Messages.Page.Queue.gb
|
, queue = Messages.Page.Queue.gb
|
||||||
, userSettings = Messages.Page.UserSettings.gb
|
, userSettings = Messages.Page.UserSettings.gb
|
||||||
, manageData = Messages.Page.ManageData.gb
|
, manageData = Messages.Page.ManageData.gb
|
||||||
, home = Messages.Page.Home.gb
|
, search = Messages.Page.Search.gb
|
||||||
, share = Messages.Page.Share.gb
|
, share = Messages.Page.Share.gb
|
||||||
, shareDetail = Messages.Page.ShareDetail.gb
|
, shareDetail = Messages.Page.ShareDetail.gb
|
||||||
|
, dashboard = Messages.Page.Dashboard.gb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -134,7 +137,8 @@ de =
|
|||||||
, queue = Messages.Page.Queue.de
|
, queue = Messages.Page.Queue.de
|
||||||
, userSettings = Messages.Page.UserSettings.de
|
, userSettings = Messages.Page.UserSettings.de
|
||||||
, manageData = Messages.Page.ManageData.de
|
, manageData = Messages.Page.ManageData.de
|
||||||
, home = Messages.Page.Home.de
|
, search = Messages.Page.Search.de
|
||||||
, share = Messages.Page.Share.de
|
, share = Messages.Page.Share.de
|
||||||
, shareDetail = Messages.Page.ShareDetail.de
|
, shareDetail = Messages.Page.ShareDetail.de
|
||||||
|
, dashboard = Messages.Page.Dashboard.de
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ type alias Texts =
|
|||||||
, newInvites : String
|
, newInvites : String
|
||||||
, help : String
|
, help : String
|
||||||
, newItemsArrived : String
|
, newItemsArrived : String
|
||||||
|
, dashboard : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ gb =
|
|||||||
, newInvites = "New Invites"
|
, newInvites = "New Invites"
|
||||||
, help = "Help"
|
, help = "Help"
|
||||||
, newItemsArrived = "New items arrived!"
|
, newItemsArrived = "New items arrived!"
|
||||||
|
, dashboard = "Dashboard"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -56,4 +58,5 @@ de =
|
|||||||
, newInvites = "Neue Einladung"
|
, newInvites = "Neue Einladung"
|
||||||
, help = "Hilfe (English)"
|
, help = "Hilfe (English)"
|
||||||
, newItemsArrived = "Neue Dokumente eingetroffen!"
|
, newItemsArrived = "Neue Dokumente eingetroffen!"
|
||||||
|
, dashboard = "Dashboard"
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,10 @@ type alias Texts =
|
|||||||
, customFields : String
|
, customFields : String
|
||||||
, direction : String
|
, direction : String
|
||||||
, folderNotOwnerWarning : String
|
, folderNotOwnerWarning : String
|
||||||
|
, shares : String
|
||||||
|
, sources : String
|
||||||
|
, periodicQueries : String
|
||||||
|
, notificationHooks : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,6 +91,10 @@ You are **not a member** of this folder. This item will be **hidden**
|
|||||||
from any search now. Use a folder where you are a member of to make this
|
from any search now. Use a folder where you are a member of to make this
|
||||||
item visible. This message will disappear then.
|
item visible. This message will disappear then.
|
||||||
"""
|
"""
|
||||||
|
, shares = "Shares"
|
||||||
|
, sources = "Sources"
|
||||||
|
, periodicQueries = "Periodic Queries"
|
||||||
|
, notificationHooks = "Webhooks"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -130,4 +138,8 @@ URL hochgeladen werden, sind für dich in der Suche *nicht* sichtbar.
|
|||||||
Nutze lieber einen Ordner, dem Du als Mitglied zugeordnet bist. Diese
|
Nutze lieber einen Ordner, dem Du als Mitglied zugeordnet bist. Diese
|
||||||
Nachricht verschwindet dann.
|
Nachricht verschwindet dann.
|
||||||
"""
|
"""
|
||||||
|
, shares = "Freigaben"
|
||||||
|
, sources = "Quellen"
|
||||||
|
, periodicQueries = "Periodische Abfragen"
|
||||||
|
, notificationHooks = "Webhooks"
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,9 @@ module Messages.Comp.BookmarkChooser exposing
|
|||||||
, gb
|
, gb
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Data.AccountScope exposing (AccountScope(..))
|
||||||
import Messages.Basics
|
import Messages.Basics
|
||||||
|
import Messages.Data.AccountScope
|
||||||
|
|
||||||
|
|
||||||
type alias Texts =
|
type alias Texts =
|
||||||
@ -25,8 +27,8 @@ type alias Texts =
|
|||||||
gb : Texts
|
gb : Texts
|
||||||
gb =
|
gb =
|
||||||
{ basics = Messages.Basics.gb
|
{ basics = Messages.Basics.gb
|
||||||
, userLabel = "Personal"
|
, userLabel = Messages.Data.AccountScope.gb User
|
||||||
, collectiveLabel = "Collective"
|
, collectiveLabel = Messages.Data.AccountScope.gb Collective
|
||||||
, shareLabel = "Shares"
|
, shareLabel = "Shares"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ gb =
|
|||||||
de : Texts
|
de : Texts
|
||||||
de =
|
de =
|
||||||
{ basics = Messages.Basics.de
|
{ basics = Messages.Basics.de
|
||||||
, userLabel = "Persönlich"
|
, userLabel = Messages.Data.AccountScope.de User
|
||||||
, collectiveLabel = "Kollektiv"
|
, collectiveLabel = Messages.Data.AccountScope.de Collective
|
||||||
, shareLabel = "Freigaben"
|
, shareLabel = "Freigaben"
|
||||||
}
|
}
|
||||||
|
74
modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm
Normal file
74
modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.BoxMessageEdit
|
||||||
|
import Messages.Comp.BoxQueryEdit
|
||||||
|
import Messages.Comp.BoxStatsEdit
|
||||||
|
import Messages.Comp.BoxUploadEdit
|
||||||
|
import Messages.Data.BoxContent
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ messageEdit : Messages.Comp.BoxMessageEdit.Texts
|
||||||
|
, uploadEdit : Messages.Comp.BoxUploadEdit.Texts
|
||||||
|
, queryEdit : Messages.Comp.BoxQueryEdit.Texts
|
||||||
|
, statsEdit : Messages.Comp.BoxStatsEdit.Texts
|
||||||
|
, boxContent : Messages.Data.BoxContent.Texts
|
||||||
|
, basics : Messages.Basics.Texts
|
||||||
|
, namePlaceholder : String
|
||||||
|
, visible : String
|
||||||
|
, decorations : String
|
||||||
|
, colspan : String
|
||||||
|
, contentProperties : String
|
||||||
|
, reallyDeleteBox : String
|
||||||
|
, moveToLeft : String
|
||||||
|
, moveToRight : String
|
||||||
|
, deleteBox : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ messageEdit = Messages.Comp.BoxMessageEdit.gb
|
||||||
|
, uploadEdit = Messages.Comp.BoxUploadEdit.gb
|
||||||
|
, queryEdit = Messages.Comp.BoxQueryEdit.gb
|
||||||
|
, statsEdit = Messages.Comp.BoxStatsEdit.gb
|
||||||
|
, boxContent = Messages.Data.BoxContent.gb
|
||||||
|
, basics = Messages.Basics.gb
|
||||||
|
, namePlaceholder = "Box name"
|
||||||
|
, visible = "Visible"
|
||||||
|
, decorations = "Box decorations"
|
||||||
|
, colspan = "Column span"
|
||||||
|
, contentProperties = "Content"
|
||||||
|
, reallyDeleteBox = "Really delete this box?"
|
||||||
|
, moveToLeft = "Move to left"
|
||||||
|
, moveToRight = "Move to right"
|
||||||
|
, deleteBox = "Delete box"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ messageEdit = Messages.Comp.BoxMessageEdit.de
|
||||||
|
, uploadEdit = Messages.Comp.BoxUploadEdit.de
|
||||||
|
, queryEdit = Messages.Comp.BoxQueryEdit.de
|
||||||
|
, statsEdit = Messages.Comp.BoxStatsEdit.de
|
||||||
|
, boxContent = Messages.Data.BoxContent.de
|
||||||
|
, basics = Messages.Basics.de
|
||||||
|
, namePlaceholder = "Boxname"
|
||||||
|
, visible = "Sichtbar"
|
||||||
|
, decorations = "Kachel-Dekoration anzeigen"
|
||||||
|
, colspan = "Spalten überspannen"
|
||||||
|
, contentProperties = "Inhalt"
|
||||||
|
, reallyDeleteBox = "Die Kachel wirklich entfernen?"
|
||||||
|
, moveToLeft = "Nach links verschieben"
|
||||||
|
, moveToRight = "Nach rechts verschieben"
|
||||||
|
, deleteBox = "Kachel entfernen"
|
||||||
|
}
|
37
modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm
Normal file
37
modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxMessageEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ titleLabel : String
|
||||||
|
, titlePlaceholder : String
|
||||||
|
, bodyLabel : String
|
||||||
|
, bodyPlaceholder : String
|
||||||
|
, infoText : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ titleLabel = "Title"
|
||||||
|
, titlePlaceholder = "Message title…"
|
||||||
|
, bodyLabel = "Body"
|
||||||
|
, bodyPlaceholder = "Message body…"
|
||||||
|
, infoText = "Markdown can be used in both fields for simple formatting."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ titleLabel = "Titel"
|
||||||
|
, titlePlaceholder = "Titel…"
|
||||||
|
, bodyLabel = "Nachricht"
|
||||||
|
, bodyPlaceholder = "Text…"
|
||||||
|
, infoText = "Markdown kann in beiden Feldern für einfache Formatierung verwendet werden."
|
||||||
|
}
|
34
modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm
Normal file
34
modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxQueryEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.BoxSearchQueryInput
|
||||||
|
import Messages.Comp.ItemColumnDropdown
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ columnDropdown : Messages.Comp.ItemColumnDropdown.Texts
|
||||||
|
, searchQuery : Messages.Comp.BoxSearchQueryInput.Texts
|
||||||
|
, showColumnHeaders : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ columnDropdown = Messages.Comp.ItemColumnDropdown.gb
|
||||||
|
, searchQuery = Messages.Comp.BoxSearchQueryInput.gb
|
||||||
|
, showColumnHeaders = "Show column headers"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ columnDropdown = Messages.Comp.ItemColumnDropdown.de
|
||||||
|
, searchQuery = Messages.Comp.BoxSearchQueryInput.de
|
||||||
|
, showColumnHeaders = "Spaltennamen anzeigen"
|
||||||
|
}
|
57
modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm
Normal file
57
modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxQueryView exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Data.ItemTemplate as IT
|
||||||
|
import Http
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.HttpError
|
||||||
|
import Messages.Data.Direction
|
||||||
|
import Messages.Data.ItemColumn
|
||||||
|
import Messages.DateFormat as DF
|
||||||
|
import Messages.UiLanguage
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ httpError : Http.Error -> String
|
||||||
|
, errorOccurred : String
|
||||||
|
, basics : Messages.Basics.Texts
|
||||||
|
, noResults : String
|
||||||
|
, templateCtx : IT.TemplateContext
|
||||||
|
, itemColumn : Messages.Data.ItemColumn.Texts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ httpError = Messages.Comp.HttpError.gb
|
||||||
|
, errorOccurred = "Error retrieving data."
|
||||||
|
, basics = Messages.Basics.gb
|
||||||
|
, noResults = "No items found."
|
||||||
|
, templateCtx =
|
||||||
|
{ dateFormatLong = DF.formatDateLong Messages.UiLanguage.English
|
||||||
|
, dateFormatShort = DF.formatDateShort Messages.UiLanguage.English
|
||||||
|
, directionLabel = Messages.Data.Direction.gb
|
||||||
|
}
|
||||||
|
, itemColumn = Messages.Data.ItemColumn.gb
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ httpError = Messages.Comp.HttpError.de
|
||||||
|
, errorOccurred = "Fehler beim Laden der Daten."
|
||||||
|
, basics = Messages.Basics.de
|
||||||
|
, noResults = "Keine Dokumente gefunden."
|
||||||
|
, templateCtx =
|
||||||
|
{ dateFormatLong = DF.formatDateLong Messages.UiLanguage.German
|
||||||
|
, dateFormatShort = DF.formatDateShort Messages.UiLanguage.German
|
||||||
|
, directionLabel = Messages.Data.Direction.de
|
||||||
|
}
|
||||||
|
, itemColumn = Messages.Data.ItemColumn.de
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxSearchQueryInput exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.BookmarkDropdown
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ bookmarkDropdown : Messages.Comp.BookmarkDropdown.Texts
|
||||||
|
, switchToBookmark : String
|
||||||
|
, switchToQuery : String
|
||||||
|
, searchPlaceholder : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ bookmarkDropdown = Messages.Comp.BookmarkDropdown.gb
|
||||||
|
, switchToBookmark = "Bookmarks"
|
||||||
|
, switchToQuery = "Search query"
|
||||||
|
, searchPlaceholder = "Search…"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ bookmarkDropdown = Messages.Comp.BookmarkDropdown.de
|
||||||
|
, switchToBookmark = "Bookmarks"
|
||||||
|
, switchToQuery = "Suchabfrage"
|
||||||
|
, searchPlaceholder = "Abfrage…"
|
||||||
|
}
|
39
modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm
Normal file
39
modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxStatsEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.BoxSearchQueryInput
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ searchQuery : Messages.Comp.BoxSearchQueryInput.Texts
|
||||||
|
, fieldStatistics : String
|
||||||
|
, basicNumbers : String
|
||||||
|
, showLabel : String
|
||||||
|
, showItemCount : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ searchQuery = Messages.Comp.BoxSearchQueryInput.gb
|
||||||
|
, fieldStatistics = "Field statistics"
|
||||||
|
, basicNumbers = "Basic numbers"
|
||||||
|
, showLabel = "Display"
|
||||||
|
, showItemCount = "Show item count"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ searchQuery = Messages.Comp.BoxSearchQueryInput.de
|
||||||
|
, fieldStatistics = "Benutzerfeld Statistiken"
|
||||||
|
, basicNumbers = "Allgemeine Zahlen"
|
||||||
|
, showLabel = "Anzeige"
|
||||||
|
, showItemCount = "Gesamtanzahl Dokumente mit anzeigen"
|
||||||
|
}
|
39
modules/webapp/src/main/elm/Messages/Comp/BoxStatsView.elm
Normal file
39
modules/webapp/src/main/elm/Messages/Comp/BoxStatsView.elm
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxStatsView exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Http
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.HttpError
|
||||||
|
import Messages.Comp.SearchStatsView
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ httpError : Http.Error -> String
|
||||||
|
, errorOccurred : String
|
||||||
|
, statsView : Messages.Comp.SearchStatsView.Texts
|
||||||
|
, basics : Messages.Basics.Texts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ httpError = Messages.Comp.HttpError.gb
|
||||||
|
, errorOccurred = "Error retrieving data."
|
||||||
|
, statsView = Messages.Comp.SearchStatsView.gb
|
||||||
|
, basics = Messages.Basics.gb
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ httpError = Messages.Comp.HttpError.de
|
||||||
|
, errorOccurred = "Fehler beim Laden der Daten."
|
||||||
|
, statsView = Messages.Comp.SearchStatsView.de
|
||||||
|
, basics = Messages.Basics.de
|
||||||
|
}
|
31
modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm
Normal file
31
modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxUploadEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ sourceLabel : String
|
||||||
|
, sourcePlaceholder : String
|
||||||
|
, infoText : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ sourceLabel = "Source"
|
||||||
|
, sourcePlaceholder = "Choose source…"
|
||||||
|
, infoText = "Optionally choose a source otherwise default settings apply to all uploads."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ sourceLabel = "Quelle"
|
||||||
|
, sourcePlaceholder = "Quelle…"
|
||||||
|
, infoText = "Optional kann eine Quelle als Einstellung gewählt werden, sonst werden Standardeinstellungen verwendet."
|
||||||
|
}
|
30
modules/webapp/src/main/elm/Messages/Comp/BoxUploadView.elm
Normal file
30
modules/webapp/src/main/elm/Messages/Comp/BoxUploadView.elm
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxUploadView exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.UploadForm
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ uploadForm : Messages.Comp.UploadForm.Texts
|
||||||
|
, moreOptions : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ uploadForm = Messages.Comp.UploadForm.gb
|
||||||
|
, moreOptions = "More options…"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ uploadForm = Messages.Comp.UploadForm.de
|
||||||
|
, moreOptions = "More options…"
|
||||||
|
}
|
35
modules/webapp/src/main/elm/Messages/Comp/BoxView.elm
Normal file
35
modules/webapp/src/main/elm/Messages/Comp/BoxView.elm
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.BoxView exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.BoxQueryView
|
||||||
|
import Messages.Comp.BoxStatsView
|
||||||
|
import Messages.Comp.BoxUploadView
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ queryView : Messages.Comp.BoxQueryView.Texts
|
||||||
|
, statsView : Messages.Comp.BoxStatsView.Texts
|
||||||
|
, uploadView : Messages.Comp.BoxUploadView.Texts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ queryView = Messages.Comp.BoxQueryView.gb
|
||||||
|
, statsView = Messages.Comp.BoxStatsView.gb
|
||||||
|
, uploadView = Messages.Comp.BoxUploadView.gb
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ queryView = Messages.Comp.BoxQueryView.de
|
||||||
|
, statsView = Messages.Comp.BoxStatsView.de
|
||||||
|
, uploadView = Messages.Comp.BoxUploadView.de
|
||||||
|
}
|
57
modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm
Normal file
57
modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.DashboardEdit exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.BoxEdit
|
||||||
|
import Messages.Data.AccountScope
|
||||||
|
import Messages.Data.BoxContent
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ boxView : Messages.Comp.BoxEdit.Texts
|
||||||
|
, boxContent : Messages.Data.BoxContent.Texts
|
||||||
|
, basics : Messages.Basics.Texts
|
||||||
|
, accountScope : Messages.Data.AccountScope.Texts
|
||||||
|
, namePlaceholder : String
|
||||||
|
, columns : String
|
||||||
|
, dashboardBoxes : String
|
||||||
|
, newBox : String
|
||||||
|
, defaultDashboard : String
|
||||||
|
, gap : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ boxView = Messages.Comp.BoxEdit.gb
|
||||||
|
, boxContent = Messages.Data.BoxContent.gb
|
||||||
|
, basics = Messages.Basics.gb
|
||||||
|
, accountScope = Messages.Data.AccountScope.gb
|
||||||
|
, namePlaceholder = "Dashboard name"
|
||||||
|
, columns = "Columns"
|
||||||
|
, dashboardBoxes = "Dashboard Boxes"
|
||||||
|
, newBox = "New box"
|
||||||
|
, defaultDashboard = "Default Dashboard"
|
||||||
|
, gap = "Gap"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ boxView = Messages.Comp.BoxEdit.de
|
||||||
|
, boxContent = Messages.Data.BoxContent.de
|
||||||
|
, basics = Messages.Basics.de
|
||||||
|
, accountScope = Messages.Data.AccountScope.de
|
||||||
|
, namePlaceholder = "Dashboardname"
|
||||||
|
, columns = "Spalten"
|
||||||
|
, dashboardBoxes = "Dashboard Kacheln"
|
||||||
|
, newBox = "Neue Kachel"
|
||||||
|
, defaultDashboard = "Standard Dashboard"
|
||||||
|
, gap = "Abstand"
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.DashboardManage exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Http
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.DashboardEdit
|
||||||
|
import Messages.Comp.HttpError
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, dashboardEdit : Messages.Comp.DashboardEdit.Texts
|
||||||
|
, httpError : Http.Error -> String
|
||||||
|
, reallyDeleteDashboard : String
|
||||||
|
, nameEmpty : String
|
||||||
|
, nameExists : String
|
||||||
|
, createDashboard : String
|
||||||
|
, copyDashboard : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, dashboardEdit = Messages.Comp.DashboardEdit.gb
|
||||||
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
|
, reallyDeleteDashboard = "Really delete this dashboard?"
|
||||||
|
, nameEmpty = "The name must not be empty."
|
||||||
|
, nameExists = "The name is already in use."
|
||||||
|
, createDashboard = "New"
|
||||||
|
, copyDashboard = "Copy"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, dashboardEdit = Messages.Comp.DashboardEdit.de
|
||||||
|
, httpError = Messages.Comp.HttpError.de
|
||||||
|
, reallyDeleteDashboard = "Das Dashboard wirklich entfernen?"
|
||||||
|
, nameEmpty = "Ein Name muss angegeben werden."
|
||||||
|
, nameExists = "Der Name wird bereits verwendet."
|
||||||
|
, createDashboard = "Neu"
|
||||||
|
, copyDashboard = "Kopie"
|
||||||
|
}
|
27
modules/webapp/src/main/elm/Messages/Comp/DashboardView.elm
Normal file
27
modules/webapp/src/main/elm/Messages/Comp/DashboardView.elm
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.DashboardView exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Comp.BoxView
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ boxView : Messages.Comp.BoxView.Texts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ boxView = Messages.Comp.BoxView.gb
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ boxView = Messages.Comp.BoxView.de
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.ItemColumnDropdown exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Data.ItemColumn
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, column : Messages.Data.ItemColumn.Texts
|
||||||
|
, placeholder : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, column = Messages.Data.ItemColumn.gb
|
||||||
|
, placeholder = "Choose…"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, column = Messages.Data.ItemColumn.de
|
||||||
|
, placeholder = "Wähle…"
|
||||||
|
}
|
98
modules/webapp/src/main/elm/Messages/Comp/UploadForm.elm
Normal file
98
modules/webapp/src/main/elm/Messages/Comp/UploadForm.elm
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
24
modules/webapp/src/main/elm/Messages/Data/AccountScope.elm
Normal file
24
modules/webapp/src/main/elm/Messages/Data/AccountScope.elm
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Data.AccountScope exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Data.AccountScope exposing (AccountScope)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
AccountScope -> String
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
Data.AccountScope.fold "Personal" "Collective"
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
Data.AccountScope.fold "Persönlich" "Kollektiv"
|
61
modules/webapp/src/main/elm/Messages/Data/BoxContent.elm
Normal file
61
modules/webapp/src/main/elm/Messages/Data/BoxContent.elm
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Data.BoxContent exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Data.BoxContent exposing (BoxContent(..))
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ forContent : BoxContent -> String
|
||||||
|
, queryBox : String
|
||||||
|
, statsBox : String
|
||||||
|
, messageBox : String
|
||||||
|
, uploadBox : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
updateForContent
|
||||||
|
{ forContent = \_ -> ""
|
||||||
|
, queryBox = "Query box"
|
||||||
|
, statsBox = "Statistics box"
|
||||||
|
, messageBox = "Message box"
|
||||||
|
, uploadBox = "Upload box"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
updateForContent
|
||||||
|
{ forContent = \_ -> ""
|
||||||
|
, queryBox = "Suchabfrage Kachel"
|
||||||
|
, statsBox = "Statistik Kachel"
|
||||||
|
, messageBox = "Mitteilung Kachel"
|
||||||
|
, uploadBox = "Datei hochladen Kachel"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateForContent : Texts -> Texts
|
||||||
|
updateForContent init =
|
||||||
|
{ init
|
||||||
|
| forContent =
|
||||||
|
\cnt ->
|
||||||
|
case cnt of
|
||||||
|
BoxMessage _ ->
|
||||||
|
init.messageBox
|
||||||
|
|
||||||
|
BoxUpload _ ->
|
||||||
|
init.uploadBox
|
||||||
|
|
||||||
|
BoxQuery _ ->
|
||||||
|
init.queryBox
|
||||||
|
|
||||||
|
BoxStats _ ->
|
||||||
|
init.statsBox
|
||||||
|
}
|
122
modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm
Normal file
122
modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Data.ItemColumn exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Data.ItemColumn exposing (ItemColumn(..))
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ header : ItemColumn -> String
|
||||||
|
, label : ItemColumn -> String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
let
|
||||||
|
headerName col =
|
||||||
|
case col of
|
||||||
|
Name ->
|
||||||
|
"Name"
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
"Date"
|
||||||
|
|
||||||
|
DateShort ->
|
||||||
|
"Date"
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
"Due date"
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
"Due date"
|
||||||
|
|
||||||
|
Folder ->
|
||||||
|
"Folder"
|
||||||
|
|
||||||
|
Correspondent ->
|
||||||
|
"Correspondent"
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
"Concerning"
|
||||||
|
|
||||||
|
Tags ->
|
||||||
|
"Tags"
|
||||||
|
in
|
||||||
|
{ header = headerName
|
||||||
|
, label =
|
||||||
|
\col ->
|
||||||
|
case col of
|
||||||
|
DateShort ->
|
||||||
|
headerName col ++ " (short)"
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
headerName col ++ " (long)"
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
headerName col ++ " (short)"
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
headerName col ++ " (long)"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
headerName col
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
let
|
||||||
|
headerName col =
|
||||||
|
case col of
|
||||||
|
Name ->
|
||||||
|
"Name"
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
"Datum"
|
||||||
|
|
||||||
|
DateShort ->
|
||||||
|
"Datum"
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
"Fälligkeitsdatum"
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
"Fälligkeitsdatum"
|
||||||
|
|
||||||
|
Folder ->
|
||||||
|
"Ordner"
|
||||||
|
|
||||||
|
Correspondent ->
|
||||||
|
"Korrespondent"
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
"Betreffend"
|
||||||
|
|
||||||
|
Tags ->
|
||||||
|
"Tags"
|
||||||
|
in
|
||||||
|
{ header = headerName
|
||||||
|
, label =
|
||||||
|
\col ->
|
||||||
|
case col of
|
||||||
|
DateShort ->
|
||||||
|
headerName col ++ " (kurz)"
|
||||||
|
|
||||||
|
DateLong ->
|
||||||
|
headerName col ++ " (lang)"
|
||||||
|
|
||||||
|
DueDateShort ->
|
||||||
|
headerName col ++ " (kurz)"
|
||||||
|
|
||||||
|
DueDateLong ->
|
||||||
|
headerName col ++ " (lang)"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
headerName col
|
||||||
|
}
|
@ -10,6 +10,7 @@ module Messages.DateFormat exposing
|
|||||||
, formatDateLong
|
, formatDateLong
|
||||||
, formatDateShort
|
, formatDateShort
|
||||||
, formatDateTimeLong
|
, formatDateTimeLong
|
||||||
|
, formatDateTimeShort
|
||||||
)
|
)
|
||||||
|
|
||||||
import DateFormat exposing (Token)
|
import DateFormat exposing (Token)
|
||||||
@ -68,6 +69,11 @@ formatDateShort lang millis =
|
|||||||
format lang .dateShort millis
|
format lang .dateShort millis
|
||||||
|
|
||||||
|
|
||||||
|
formatDateTimeShort : UiLanguage -> Int -> String
|
||||||
|
formatDateTimeShort lang millis =
|
||||||
|
format lang .dateTimeShort millis
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Language Definitions
|
--- Language Definitions
|
||||||
|
|
||||||
|
@ -29,10 +29,8 @@ type alias Texts =
|
|||||||
, httpError : Http.Error -> String
|
, httpError : Http.Error -> String
|
||||||
, collectiveSettings : String
|
, collectiveSettings : String
|
||||||
, insights : String
|
, insights : String
|
||||||
, sources : String
|
|
||||||
, settings : String
|
, settings : String
|
||||||
, users : String
|
, users : String
|
||||||
, shares : String
|
|
||||||
, user : String
|
, user : String
|
||||||
, collective : String
|
, collective : String
|
||||||
, size : String
|
, size : String
|
||||||
@ -51,10 +49,8 @@ gb =
|
|||||||
, httpError = Messages.Comp.HttpError.gb
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
, collectiveSettings = "Collective Settings"
|
, collectiveSettings = "Collective Settings"
|
||||||
, insights = "Insights"
|
, insights = "Insights"
|
||||||
, sources = "Sources"
|
|
||||||
, settings = "Settings"
|
, settings = "Settings"
|
||||||
, users = "Users"
|
, users = "Users"
|
||||||
, shares = "Shares"
|
|
||||||
, user = "User"
|
, user = "User"
|
||||||
, collective = "Collective"
|
, collective = "Collective"
|
||||||
, size = "Size"
|
, size = "Size"
|
||||||
@ -73,10 +69,8 @@ de =
|
|||||||
, httpError = Messages.Comp.HttpError.de
|
, httpError = Messages.Comp.HttpError.de
|
||||||
, collectiveSettings = "Kollektiveinstellungen"
|
, collectiveSettings = "Kollektiveinstellungen"
|
||||||
, insights = "Statistiken"
|
, insights = "Statistiken"
|
||||||
, sources = "Quellen"
|
|
||||||
, settings = "Einstellungen"
|
, settings = "Einstellungen"
|
||||||
, users = "Benutzer"
|
, users = "Benutzer"
|
||||||
, shares = "Freigaben"
|
|
||||||
, user = "Benutzer"
|
, user = "Benutzer"
|
||||||
, collective = "Kollektiv"
|
, collective = "Kollektiv"
|
||||||
, size = "Größe"
|
, size = "Größe"
|
||||||
|
117
modules/webapp/src/main/elm/Messages/Page/Dashboard.elm
Normal file
117
modules/webapp/src/main/elm/Messages/Page/Dashboard.elm
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Page.Dashboard exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.BookmarkChooser
|
||||||
|
import Messages.Comp.DashboardManage
|
||||||
|
import Messages.Comp.DashboardView
|
||||||
|
import Messages.Comp.EquipmentManage
|
||||||
|
import Messages.Comp.FolderManage
|
||||||
|
import Messages.Comp.NotificationHookManage
|
||||||
|
import Messages.Comp.OrgManage
|
||||||
|
import Messages.Comp.PeriodicQueryTaskManage
|
||||||
|
import Messages.Comp.PersonManage
|
||||||
|
import Messages.Comp.ShareManage
|
||||||
|
import Messages.Comp.SourceManage
|
||||||
|
import Messages.Comp.TagManage
|
||||||
|
import Messages.Comp.UploadForm
|
||||||
|
import Messages.Data.AccountScope
|
||||||
|
import Messages.Page.DefaultDashboard
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, bookmarkChooser : Messages.Comp.BookmarkChooser.Texts
|
||||||
|
, notificationHookManage : Messages.Comp.NotificationHookManage.Texts
|
||||||
|
, periodicQueryManage : Messages.Comp.PeriodicQueryTaskManage.Texts
|
||||||
|
, sourceManage : Messages.Comp.SourceManage.Texts
|
||||||
|
, shareManage : Messages.Comp.ShareManage.Texts
|
||||||
|
, organizationManage : Messages.Comp.OrgManage.Texts
|
||||||
|
, personManage : Messages.Comp.PersonManage.Texts
|
||||||
|
, equipManage : Messages.Comp.EquipmentManage.Texts
|
||||||
|
, tagManage : Messages.Comp.TagManage.Texts
|
||||||
|
, folderManage : Messages.Comp.FolderManage.Texts
|
||||||
|
, uploadForm : Messages.Comp.UploadForm.Texts
|
||||||
|
, dashboard : Messages.Comp.DashboardView.Texts
|
||||||
|
, dashboardManage : Messages.Comp.DashboardManage.Texts
|
||||||
|
, defaultDashboard : Messages.Page.DefaultDashboard.Texts
|
||||||
|
, accountScope : Messages.Data.AccountScope.Texts
|
||||||
|
, manage : String
|
||||||
|
, dashboardLink : String
|
||||||
|
, bookmarks : String
|
||||||
|
, misc : String
|
||||||
|
, settings : String
|
||||||
|
, documentation : String
|
||||||
|
, uploadFiles : String
|
||||||
|
, editDashboard : String
|
||||||
|
, dashboards : String
|
||||||
|
, predefinedMessage : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, bookmarkChooser = Messages.Comp.BookmarkChooser.gb
|
||||||
|
, notificationHookManage = Messages.Comp.NotificationHookManage.gb
|
||||||
|
, periodicQueryManage = Messages.Comp.PeriodicQueryTaskManage.gb
|
||||||
|
, sourceManage = Messages.Comp.SourceManage.gb
|
||||||
|
, shareManage = Messages.Comp.ShareManage.gb
|
||||||
|
, organizationManage = Messages.Comp.OrgManage.gb
|
||||||
|
, personManage = Messages.Comp.PersonManage.gb
|
||||||
|
, equipManage = Messages.Comp.EquipmentManage.gb
|
||||||
|
, tagManage = Messages.Comp.TagManage.gb
|
||||||
|
, folderManage = Messages.Comp.FolderManage.gb
|
||||||
|
, uploadForm = Messages.Comp.UploadForm.gb
|
||||||
|
, dashboard = Messages.Comp.DashboardView.gb
|
||||||
|
, dashboardManage = Messages.Comp.DashboardManage.gb
|
||||||
|
, defaultDashboard = Messages.Page.DefaultDashboard.gb
|
||||||
|
, accountScope = Messages.Data.AccountScope.gb
|
||||||
|
, manage = "Manage"
|
||||||
|
, dashboardLink = "Dasbhoard"
|
||||||
|
, bookmarks = "Bookmarks"
|
||||||
|
, misc = "Misc"
|
||||||
|
, settings = "Settings"
|
||||||
|
, documentation = "Documentation"
|
||||||
|
, uploadFiles = "Upload documents"
|
||||||
|
, editDashboard = "Edit Dashboard"
|
||||||
|
, dashboards = "Dashboards"
|
||||||
|
, predefinedMessage = "This dashboard is predefined one that cannot be deleted. It is replaced with the first one you save."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, bookmarkChooser = Messages.Comp.BookmarkChooser.de
|
||||||
|
, notificationHookManage = Messages.Comp.NotificationHookManage.de
|
||||||
|
, periodicQueryManage = Messages.Comp.PeriodicQueryTaskManage.de
|
||||||
|
, sourceManage = Messages.Comp.SourceManage.de
|
||||||
|
, shareManage = Messages.Comp.ShareManage.de
|
||||||
|
, organizationManage = Messages.Comp.OrgManage.de
|
||||||
|
, personManage = Messages.Comp.PersonManage.de
|
||||||
|
, equipManage = Messages.Comp.EquipmentManage.de
|
||||||
|
, tagManage = Messages.Comp.TagManage.de
|
||||||
|
, folderManage = Messages.Comp.FolderManage.de
|
||||||
|
, uploadForm = Messages.Comp.UploadForm.de
|
||||||
|
, dashboard = Messages.Comp.DashboardView.de
|
||||||
|
, dashboardManage = Messages.Comp.DashboardManage.de
|
||||||
|
, defaultDashboard = Messages.Page.DefaultDashboard.de
|
||||||
|
, accountScope = Messages.Data.AccountScope.de
|
||||||
|
, manage = "Verwalten"
|
||||||
|
, dashboardLink = "Dasbhoard"
|
||||||
|
, bookmarks = "Bookmarks"
|
||||||
|
, misc = "Anderes"
|
||||||
|
, settings = "Einstellungen"
|
||||||
|
, documentation = "Dokumentation"
|
||||||
|
, uploadFiles = "Dokumente hochladen"
|
||||||
|
, editDashboard = "Dashboard ändern"
|
||||||
|
, dashboards = "Dashboards"
|
||||||
|
, predefinedMessage = "Dieses Dashboard ist vordefiniert und kann nicht entfernt werden. Es wird durch ein gespeichertes ersetzt."
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Page.DefaultDashboard exposing (Texts, de, gb)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, default : String
|
||||||
|
, welcomeName : String
|
||||||
|
, welcomeTitle : String
|
||||||
|
, welcomeBody : String
|
||||||
|
, summaryName : String
|
||||||
|
, dueInDays : Int -> String
|
||||||
|
, newDocsName : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, default = "Default"
|
||||||
|
, welcomeName = "Welcome Message"
|
||||||
|
, welcomeTitle = "# Welcome to Docspell"
|
||||||
|
, welcomeBody = "Docspell keeps your documents organized."
|
||||||
|
, summaryName = "Summary"
|
||||||
|
, dueInDays = \n -> "Due in " ++ String.fromInt n ++ " days"
|
||||||
|
, newDocsName = "New Documents"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, default = "Standard"
|
||||||
|
, welcomeName = "Willkommens-Nachricht"
|
||||||
|
, welcomeTitle = "# Willkommen zu Docspell"
|
||||||
|
, welcomeBody = "Docspell behält die Übersicht über deine Dokumene."
|
||||||
|
, summaryName = "Zahlen"
|
||||||
|
, dueInDays = \n -> "Fällig in " ++ String.fromInt n ++ " Tagen"
|
||||||
|
, newDocsName = "Neue Dokumente"
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Messages.Page.Home exposing
|
module Messages.Page.Search exposing
|
||||||
( Texts
|
( Texts
|
||||||
, de
|
, de
|
||||||
, gb
|
, gb
|
||||||
@ -17,14 +17,14 @@ import Messages.Comp.ItemCardList
|
|||||||
import Messages.Comp.ItemMerge
|
import Messages.Comp.ItemMerge
|
||||||
import Messages.Comp.PublishItems
|
import Messages.Comp.PublishItems
|
||||||
import Messages.Comp.SearchStatsView
|
import Messages.Comp.SearchStatsView
|
||||||
import Messages.Page.HomeSideMenu
|
import Messages.Page.SearchSideMenu
|
||||||
|
|
||||||
|
|
||||||
type alias Texts =
|
type alias Texts =
|
||||||
{ basics : Messages.Basics.Texts
|
{ basics : Messages.Basics.Texts
|
||||||
, itemCardList : Messages.Comp.ItemCardList.Texts
|
, itemCardList : Messages.Comp.ItemCardList.Texts
|
||||||
, searchStatsView : Messages.Comp.SearchStatsView.Texts
|
, searchStatsView : Messages.Comp.SearchStatsView.Texts
|
||||||
, sideMenu : Messages.Page.HomeSideMenu.Texts
|
, sideMenu : Messages.Page.SearchSideMenu.Texts
|
||||||
, itemMerge : Messages.Comp.ItemMerge.Texts
|
, itemMerge : Messages.Comp.ItemMerge.Texts
|
||||||
, publishItems : Messages.Comp.PublishItems.Texts
|
, publishItems : Messages.Comp.PublishItems.Texts
|
||||||
, bookmarkManage : Messages.Comp.BookmarkQueryManage.Texts
|
, bookmarkManage : Messages.Comp.BookmarkQueryManage.Texts
|
||||||
@ -66,7 +66,7 @@ gb =
|
|||||||
{ basics = Messages.Basics.gb
|
{ basics = Messages.Basics.gb
|
||||||
, itemCardList = Messages.Comp.ItemCardList.gb
|
, itemCardList = Messages.Comp.ItemCardList.gb
|
||||||
, searchStatsView = Messages.Comp.SearchStatsView.gb
|
, searchStatsView = Messages.Comp.SearchStatsView.gb
|
||||||
, sideMenu = Messages.Page.HomeSideMenu.gb
|
, sideMenu = Messages.Page.SearchSideMenu.gb
|
||||||
, itemMerge = Messages.Comp.ItemMerge.gb
|
, itemMerge = Messages.Comp.ItemMerge.gb
|
||||||
, publishItems = Messages.Comp.PublishItems.gb
|
, publishItems = Messages.Comp.PublishItems.gb
|
||||||
, bookmarkManage = Messages.Comp.BookmarkQueryManage.gb
|
, bookmarkManage = Messages.Comp.BookmarkQueryManage.gb
|
||||||
@ -108,7 +108,7 @@ de =
|
|||||||
{ basics = Messages.Basics.de
|
{ basics = Messages.Basics.de
|
||||||
, itemCardList = Messages.Comp.ItemCardList.de
|
, itemCardList = Messages.Comp.ItemCardList.de
|
||||||
, searchStatsView = Messages.Comp.SearchStatsView.de
|
, searchStatsView = Messages.Comp.SearchStatsView.de
|
||||||
, sideMenu = Messages.Page.HomeSideMenu.de
|
, sideMenu = Messages.Page.SearchSideMenu.de
|
||||||
, itemMerge = Messages.Comp.ItemMerge.de
|
, itemMerge = Messages.Comp.ItemMerge.de
|
||||||
, publishItems = Messages.Comp.PublishItems.de
|
, publishItems = Messages.Comp.PublishItems.de
|
||||||
, bookmarkManage = Messages.Comp.BookmarkQueryManage.de
|
, bookmarkManage = Messages.Comp.BookmarkQueryManage.de
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Messages.Page.HomeSideMenu exposing
|
module Messages.Page.SearchSideMenu exposing
|
||||||
( Texts
|
( Texts
|
||||||
, de
|
, de
|
||||||
, gb
|
, gb
|
@ -11,92 +11,21 @@ module Messages.Page.Upload exposing
|
|||||||
, gb
|
, gb
|
||||||
)
|
)
|
||||||
|
|
||||||
import Data.Language exposing (Language)
|
import Messages.Comp.UploadForm
|
||||||
import Messages.Basics
|
|
||||||
import Messages.Comp.Dropzone
|
|
||||||
import Messages.Data.Language
|
|
||||||
|
|
||||||
|
|
||||||
type alias Texts =
|
type alias Texts =
|
||||||
{ basics : Messages.Basics.Texts
|
{ uploadForm : Messages.Comp.UploadForm.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 : Texts
|
||||||
gb =
|
gb =
|
||||||
{ basics = Messages.Basics.gb
|
{ uploadForm = Messages.Comp.UploadForm.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 : Texts
|
||||||
de =
|
de =
|
||||||
{ basics = Messages.Basics.de
|
{ uploadForm = Messages.Comp.UploadForm.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
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ module Messages.Page.UserSettings exposing
|
|||||||
, gb
|
, gb
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
import Messages.Comp.ChangePasswordForm
|
import Messages.Comp.ChangePasswordForm
|
||||||
import Messages.Comp.DueItemsTaskManage
|
import Messages.Comp.DueItemsTaskManage
|
||||||
import Messages.Comp.EmailSettingsManage
|
import Messages.Comp.EmailSettingsManage
|
||||||
@ -24,7 +25,8 @@ import Messages.Comp.UiSettingsManage
|
|||||||
|
|
||||||
|
|
||||||
type alias Texts =
|
type alias Texts =
|
||||||
{ changePasswordForm : Messages.Comp.ChangePasswordForm.Texts
|
{ basics : Messages.Basics.Texts
|
||||||
|
, changePasswordForm : Messages.Comp.ChangePasswordForm.Texts
|
||||||
, uiSettingsManage : Messages.Comp.UiSettingsManage.Texts
|
, uiSettingsManage : Messages.Comp.UiSettingsManage.Texts
|
||||||
, emailSettingsManage : Messages.Comp.EmailSettingsManage.Texts
|
, emailSettingsManage : Messages.Comp.EmailSettingsManage.Texts
|
||||||
, imapSettingsManage : Messages.Comp.ImapSettingsManage.Texts
|
, imapSettingsManage : Messages.Comp.ImapSettingsManage.Texts
|
||||||
@ -46,8 +48,6 @@ type alias Texts =
|
|||||||
, scanMailboxInfo1 : String
|
, scanMailboxInfo1 : String
|
||||||
, scanMailboxInfo2 : String
|
, scanMailboxInfo2 : String
|
||||||
, otpMenu : String
|
, otpMenu : String
|
||||||
, webhooks : String
|
|
||||||
, genericQueries : String
|
|
||||||
, dueItems : String
|
, dueItems : String
|
||||||
, notificationInfoText : String
|
, notificationInfoText : String
|
||||||
, webhookInfoText : String
|
, webhookInfoText : String
|
||||||
@ -60,7 +60,8 @@ type alias Texts =
|
|||||||
|
|
||||||
gb : Texts
|
gb : Texts
|
||||||
gb =
|
gb =
|
||||||
{ changePasswordForm = Messages.Comp.ChangePasswordForm.gb
|
{ basics = Messages.Basics.gb
|
||||||
|
, changePasswordForm = Messages.Comp.ChangePasswordForm.gb
|
||||||
, uiSettingsManage = Messages.Comp.UiSettingsManage.gb
|
, uiSettingsManage = Messages.Comp.UiSettingsManage.gb
|
||||||
, emailSettingsManage = Messages.Comp.EmailSettingsManage.gb
|
, emailSettingsManage = Messages.Comp.EmailSettingsManage.gb
|
||||||
, imapSettingsManage = Messages.Comp.ImapSettingsManage.gb
|
, imapSettingsManage = Messages.Comp.ImapSettingsManage.gb
|
||||||
@ -96,8 +97,6 @@ gb =
|
|||||||
adjust the schedule to avoid reading over the same mails
|
adjust the schedule to avoid reading over the same mails
|
||||||
again."""
|
again."""
|
||||||
, otpMenu = "Two Factor Authentication"
|
, otpMenu = "Two Factor Authentication"
|
||||||
, webhooks = "Webhooks"
|
|
||||||
, genericQueries = "Generic Queries"
|
|
||||||
, dueItems = "Due Items Query"
|
, dueItems = "Due Items Query"
|
||||||
, notificationInfoText = """
|
, notificationInfoText = """
|
||||||
|
|
||||||
@ -125,7 +124,8 @@ must be created before.
|
|||||||
|
|
||||||
de : Texts
|
de : Texts
|
||||||
de =
|
de =
|
||||||
{ changePasswordForm = Messages.Comp.ChangePasswordForm.de
|
{ basics = Messages.Basics.de
|
||||||
|
, changePasswordForm = Messages.Comp.ChangePasswordForm.de
|
||||||
, uiSettingsManage = Messages.Comp.UiSettingsManage.de
|
, uiSettingsManage = Messages.Comp.UiSettingsManage.de
|
||||||
, emailSettingsManage = Messages.Comp.EmailSettingsManage.de
|
, emailSettingsManage = Messages.Comp.EmailSettingsManage.de
|
||||||
, imapSettingsManage = Messages.Comp.ImapSettingsManage.de
|
, imapSettingsManage = Messages.Comp.ImapSettingsManage.de
|
||||||
@ -161,8 +161,6 @@ E-Mail-Einstellungen (IMAP) notwendig."""
|
|||||||
gleichen E-Mails möglichst nicht noch einmal eingelesen
|
gleichen E-Mails möglichst nicht noch einmal eingelesen
|
||||||
werden."""
|
werden."""
|
||||||
, otpMenu = "Zwei-Faktor-Authentifizierung"
|
, otpMenu = "Zwei-Faktor-Authentifizierung"
|
||||||
, webhooks = "Webhooks"
|
|
||||||
, genericQueries = "Periodische Abfragen"
|
|
||||||
, dueItems = "Fällige Dokumente"
|
, dueItems = "Fällige Dokumente"
|
||||||
, notificationInfoText = """
|
, notificationInfoText = """
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ module Page exposing
|
|||||||
, goto
|
, goto
|
||||||
, hasSidebar
|
, hasSidebar
|
||||||
, href
|
, href
|
||||||
|
, isDashboardPage
|
||||||
, isOpen
|
, isOpen
|
||||||
|
, isSearchPage
|
||||||
, isSecured
|
, isSecured
|
||||||
, loginPage
|
, loginPage
|
||||||
, loginPageReferrer
|
, loginPageReferrer
|
||||||
@ -51,7 +53,7 @@ emptyLoginData =
|
|||||||
|
|
||||||
|
|
||||||
type Page
|
type Page
|
||||||
= HomePage
|
= SearchPage (Maybe String)
|
||||||
| LoginPage LoginData
|
| LoginPage LoginData
|
||||||
| ManageDataPage
|
| ManageDataPage
|
||||||
| CollectiveSettingPage
|
| CollectiveSettingPage
|
||||||
@ -63,12 +65,16 @@ type Page
|
|||||||
| ItemDetailPage String
|
| ItemDetailPage String
|
||||||
| SharePage String
|
| SharePage String
|
||||||
| ShareDetailPage String String
|
| ShareDetailPage String String
|
||||||
|
| DashboardPage
|
||||||
|
|
||||||
|
|
||||||
isSecured : Page -> Bool
|
isSecured : Page -> Bool
|
||||||
isSecured page =
|
isSecured page =
|
||||||
case page of
|
case page of
|
||||||
HomePage ->
|
DashboardPage ->
|
||||||
|
True
|
||||||
|
|
||||||
|
SearchPage _ ->
|
||||||
True
|
True
|
||||||
|
|
||||||
LoginPage _ ->
|
LoginPage _ ->
|
||||||
@ -138,11 +144,34 @@ loginPage p =
|
|||||||
LoginPage { emptyLoginData | referrer = Just p }
|
LoginPage { emptyLoginData | referrer = Just p }
|
||||||
|
|
||||||
|
|
||||||
|
isSearchPage : Page -> Bool
|
||||||
|
isSearchPage page =
|
||||||
|
case page of
|
||||||
|
SearchPage _ ->
|
||||||
|
True
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
|
||||||
|
|
||||||
|
isDashboardPage : Page -> Bool
|
||||||
|
isDashboardPage page =
|
||||||
|
case page of
|
||||||
|
DashboardPage ->
|
||||||
|
True
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
|
||||||
|
|
||||||
pageName : Page -> String
|
pageName : Page -> String
|
||||||
pageName page =
|
pageName page =
|
||||||
case page of
|
case page of
|
||||||
HomePage ->
|
DashboardPage ->
|
||||||
"Home"
|
"dashboard"
|
||||||
|
|
||||||
|
SearchPage _ ->
|
||||||
|
"Search"
|
||||||
|
|
||||||
LoginPage _ ->
|
LoginPage _ ->
|
||||||
"Login"
|
"Login"
|
||||||
@ -226,8 +255,16 @@ uploadId page =
|
|||||||
pageToString : Page -> String
|
pageToString : Page -> String
|
||||||
pageToString page =
|
pageToString page =
|
||||||
case page of
|
case page of
|
||||||
HomePage ->
|
DashboardPage ->
|
||||||
"/app/home"
|
"/app/dashboard"
|
||||||
|
|
||||||
|
SearchPage bmId ->
|
||||||
|
case bmId of
|
||||||
|
Just id ->
|
||||||
|
"/app/search?bm=" ++ id
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
"/app/search"
|
||||||
|
|
||||||
LoginPage data ->
|
LoginPage data ->
|
||||||
case data.referrer of
|
case data.referrer of
|
||||||
@ -312,12 +349,14 @@ pathPrefix =
|
|||||||
parser : Parser (Page -> a) a
|
parser : Parser (Page -> a) a
|
||||||
parser =
|
parser =
|
||||||
oneOf
|
oneOf
|
||||||
[ Parser.map HomePage
|
[ Parser.map DashboardPage
|
||||||
(oneOf
|
(oneOf
|
||||||
[ Parser.top
|
[ Parser.top
|
||||||
, s pathPrefix </> s "home"
|
, s pathPrefix
|
||||||
|
, s pathPrefix </> s "dashboard"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
, Parser.map SearchPage (s pathPrefix </> s "search" <?> Query.string "bm")
|
||||||
, Parser.map LoginPage (s pathPrefix </> s "login" <?> loginPageParser)
|
, Parser.map LoginPage (s pathPrefix </> s "login" <?> loginPageParser)
|
||||||
, Parser.map ManageDataPage (s pathPrefix </> s "managedata")
|
, Parser.map ManageDataPage (s pathPrefix </> s "managedata")
|
||||||
, Parser.map CollectiveSettingPage (s pathPrefix </> s "csettings")
|
, Parser.map CollectiveSettingPage (s pathPrefix </> s "csettings")
|
||||||
|
@ -59,7 +59,7 @@ viewSidebar texts visible _ _ model =
|
|||||||
[ Icons.sourceIcon2 ""
|
[ Icons.sourceIcon2 ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.sources ]
|
[ text texts.basics.sources ]
|
||||||
]
|
]
|
||||||
, a
|
, a
|
||||||
[ href "#"
|
[ href "#"
|
||||||
@ -70,7 +70,7 @@ viewSidebar texts visible _ _ model =
|
|||||||
[ Icons.shareIcon ""
|
[ Icons.shareIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.shares ]
|
[ text texts.basics.shares ]
|
||||||
]
|
]
|
||||||
, a
|
, a
|
||||||
[ href "#"
|
[ href "#"
|
||||||
@ -238,7 +238,7 @@ viewSources texts flags settings model =
|
|||||||
]
|
]
|
||||||
[ Icons.sourceIcon2 ""
|
[ Icons.sourceIcon2 ""
|
||||||
, div [ class "ml-3" ]
|
, div [ class "ml-3" ]
|
||||||
[ text texts.sources
|
[ text texts.basics.sources
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, Html.map SourceMsg (Comp.SourceManage.view2 texts.sourceManage flags settings model.sourceModel)
|
, Html.map SourceMsg (Comp.SourceManage.view2 texts.sourceManage flags settings model.sourceModel)
|
||||||
@ -253,7 +253,7 @@ viewShares texts settings flags model =
|
|||||||
]
|
]
|
||||||
[ Icons.shareIcon ""
|
[ Icons.shareIcon ""
|
||||||
, div [ class "ml-3" ]
|
, div [ class "ml-3" ]
|
||||||
[ text texts.shares
|
[ text texts.basics.shares
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, Html.map ShareMsg (Comp.ShareManage.view texts.shareManage settings flags model.shareModel)
|
, Html.map ShareMsg (Comp.ShareManage.view texts.shareManage settings flags model.shareModel)
|
||||||
|
200
modules/webapp/src/main/elm/Page/Dashboard/Data.elm
Normal file
200
modules/webapp/src/main/elm/Page/Dashboard/Data.elm
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Page.Dashboard.Data exposing
|
||||||
|
( Content(..)
|
||||||
|
, Model
|
||||||
|
, Msg(..)
|
||||||
|
, PageError(..)
|
||||||
|
, SideMenuModel
|
||||||
|
, init
|
||||||
|
, isDashboardDefault
|
||||||
|
, isDashboardVisible
|
||||||
|
, isHomeContent
|
||||||
|
, reinitCmd
|
||||||
|
, reloadDashboardData
|
||||||
|
, reloadUiSettings
|
||||||
|
)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Comp.BookmarkChooser
|
||||||
|
import Comp.DashboardManage
|
||||||
|
import Comp.DashboardView
|
||||||
|
import Comp.EquipmentManage
|
||||||
|
import Comp.FolderManage
|
||||||
|
import Comp.NotificationHookManage
|
||||||
|
import Comp.OrgManage
|
||||||
|
import Comp.PeriodicQueryTaskManage
|
||||||
|
import Comp.PersonManage
|
||||||
|
import Comp.ShareManage
|
||||||
|
import Comp.SourceManage
|
||||||
|
import Comp.TagManage
|
||||||
|
import Comp.UploadForm
|
||||||
|
import Data.Bookmarks exposing (AllBookmarks)
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Dashboards exposing (AllDashboards)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Http
|
||||||
|
|
||||||
|
|
||||||
|
type alias SideMenuModel =
|
||||||
|
{ bookmarkChooser : Comp.BookmarkChooser.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ sideMenu : SideMenuModel
|
||||||
|
, content : Content
|
||||||
|
, pageError : Maybe PageError
|
||||||
|
, dashboards : AllDashboards
|
||||||
|
, isPredefined : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= GetBookmarksResp AllBookmarks
|
||||||
|
| GetAllDashboardsResp (Maybe Msg) (Result Http.Error AllDashboards)
|
||||||
|
| BookmarkMsg Comp.BookmarkChooser.Msg
|
||||||
|
| NotificationHookMsg Comp.NotificationHookManage.Msg
|
||||||
|
| PeriodicQueryMsg Comp.PeriodicQueryTaskManage.Msg
|
||||||
|
| SourceMsg Comp.SourceManage.Msg
|
||||||
|
| ShareMsg Comp.ShareManage.Msg
|
||||||
|
| OrganizationMsg Comp.OrgManage.Msg
|
||||||
|
| PersonMsg Comp.PersonManage.Msg
|
||||||
|
| EquipmentMsg Comp.EquipmentManage.Msg
|
||||||
|
| TagMsg Comp.TagManage.Msg
|
||||||
|
| FolderMsg Comp.FolderManage.Msg
|
||||||
|
| UploadMsg Comp.UploadForm.Msg
|
||||||
|
| DashboardMsg Comp.DashboardView.Msg
|
||||||
|
| DashboardManageMsg Comp.DashboardManage.Msg
|
||||||
|
| InitNotificationHook
|
||||||
|
| InitPeriodicQuery
|
||||||
|
| InitSource
|
||||||
|
| InitShare
|
||||||
|
| InitOrganization
|
||||||
|
| InitPerson
|
||||||
|
| InitEquipment
|
||||||
|
| InitTags
|
||||||
|
| InitFolder
|
||||||
|
| InitUpload
|
||||||
|
| InitEditDashboard
|
||||||
|
| ReloadDashboardData
|
||||||
|
| HardReloadDashboard
|
||||||
|
| SetDashboard Dashboard
|
||||||
|
| SetDashboardByName String
|
||||||
|
| SetDefaultDashboard
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
let
|
||||||
|
( dm, dc ) =
|
||||||
|
Comp.DashboardView.init flags Data.Dashboard.empty
|
||||||
|
in
|
||||||
|
( { sideMenu =
|
||||||
|
{ bookmarkChooser = Comp.BookmarkChooser.init Data.Bookmarks.empty
|
||||||
|
}
|
||||||
|
, content = Home dm
|
||||||
|
, pageError = Nothing
|
||||||
|
, dashboards = Data.Dashboards.emptyAll
|
||||||
|
, isPredefined = True
|
||||||
|
}
|
||||||
|
, Cmd.batch
|
||||||
|
[ initCmd flags
|
||||||
|
, Cmd.map DashboardMsg dc
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initCmd : Flags -> Cmd Msg
|
||||||
|
initCmd flags =
|
||||||
|
makeInitCmd flags SetDefaultDashboard
|
||||||
|
|
||||||
|
|
||||||
|
reinitCmd : Flags -> Cmd Msg
|
||||||
|
reinitCmd flags =
|
||||||
|
makeInitCmd flags ReloadDashboardData
|
||||||
|
|
||||||
|
|
||||||
|
makeInitCmd : Flags -> Msg -> Cmd Msg
|
||||||
|
makeInitCmd flags nextMsg =
|
||||||
|
let
|
||||||
|
ignoreBookmarkError r =
|
||||||
|
Result.withDefault Data.Bookmarks.empty r
|
||||||
|
|> GetBookmarksResp
|
||||||
|
in
|
||||||
|
Cmd.batch
|
||||||
|
[ Api.getBookmarks flags ignoreBookmarkError
|
||||||
|
, Api.getAllDashboards flags (GetAllDashboardsResp (Just nextMsg))
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
reloadDashboardData : Msg
|
||||||
|
reloadDashboardData =
|
||||||
|
ReloadDashboardData
|
||||||
|
|
||||||
|
|
||||||
|
reloadUiSettings : Msg
|
||||||
|
reloadUiSettings =
|
||||||
|
HardReloadDashboard
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Content
|
||||||
|
|
||||||
|
|
||||||
|
type Content
|
||||||
|
= Home Comp.DashboardView.Model
|
||||||
|
| Webhook Comp.NotificationHookManage.Model
|
||||||
|
| PeriodicQuery Comp.PeriodicQueryTaskManage.Model
|
||||||
|
| Source Comp.SourceManage.Model
|
||||||
|
| Share Comp.ShareManage.Model
|
||||||
|
| Organization Comp.OrgManage.Model
|
||||||
|
| Person Comp.PersonManage.Model
|
||||||
|
| Equipment Comp.EquipmentManage.Model
|
||||||
|
| Tags Comp.TagManage.Model
|
||||||
|
| Folder Comp.FolderManage.Model
|
||||||
|
| Upload Comp.UploadForm.Model
|
||||||
|
| Edit Comp.DashboardManage.Model
|
||||||
|
|
||||||
|
|
||||||
|
isHomeContent : Content -> Bool
|
||||||
|
isHomeContent cnt =
|
||||||
|
case cnt of
|
||||||
|
Home _ ->
|
||||||
|
True
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
|
||||||
|
|
||||||
|
isDashboardVisible : Model -> String -> Bool
|
||||||
|
isDashboardVisible model name =
|
||||||
|
case model.content of
|
||||||
|
Home m ->
|
||||||
|
m.dashboard.name == name
|
||||||
|
|
||||||
|
Edit m ->
|
||||||
|
m.initData.dashboard.name == name
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
|
||||||
|
|
||||||
|
isDashboardDefault : Model -> String -> Bool
|
||||||
|
isDashboardDefault model name =
|
||||||
|
Data.Dashboards.isDefaultAll name model.dashboards
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Errors
|
||||||
|
|
||||||
|
|
||||||
|
type PageError
|
||||||
|
= PageErrorHttp Http.Error
|
||||||
|
| PageErrorNoDashboard
|
||||||
|
| PageErrorInvalid String
|
143
modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm
Normal file
143
modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Page.Dashboard.DefaultDashboard exposing (getDefaultDashboard, value)
|
||||||
|
|
||||||
|
import Data.Box exposing (Box)
|
||||||
|
import Data.BoxContent exposing (BoxContent(..), SearchQuery(..), SummaryShow(..))
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.ItemColumn as IC
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Messages
|
||||||
|
import Messages.Page.DefaultDashboard exposing (Texts)
|
||||||
|
import Messages.UiLanguage
|
||||||
|
|
||||||
|
|
||||||
|
value : Texts -> Dashboard
|
||||||
|
value texts =
|
||||||
|
{ name = texts.default
|
||||||
|
, columns = 4
|
||||||
|
, gap = 2
|
||||||
|
, boxes =
|
||||||
|
[ messageBox texts
|
||||||
|
, fieldStats
|
||||||
|
, newDocuments texts
|
||||||
|
, dueDocuments texts
|
||||||
|
, upload
|
||||||
|
, summary texts
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getDefaultDashboard : Flags -> UiSettings -> Dashboard
|
||||||
|
getDefaultDashboard flags settings =
|
||||||
|
let
|
||||||
|
lang =
|
||||||
|
Data.UiSettings.getUiLanguage flags settings Messages.UiLanguage.English
|
||||||
|
|
||||||
|
texts =
|
||||||
|
Messages.get lang
|
||||||
|
in
|
||||||
|
value texts.dashboard.defaultDashboard
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Boxes
|
||||||
|
|
||||||
|
|
||||||
|
messageBox : Texts -> Box
|
||||||
|
messageBox texts =
|
||||||
|
{ name = texts.welcomeName
|
||||||
|
, visible = True
|
||||||
|
, decoration = False
|
||||||
|
, colspan = 4
|
||||||
|
, content =
|
||||||
|
BoxMessage
|
||||||
|
{ title = texts.welcomeTitle
|
||||||
|
, body = texts.welcomeBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
newDocuments : Texts -> Box
|
||||||
|
newDocuments texts =
|
||||||
|
{ name = texts.newDocsName
|
||||||
|
, visible = True
|
||||||
|
, decoration = True
|
||||||
|
, colspan = 2
|
||||||
|
, content =
|
||||||
|
BoxQuery
|
||||||
|
{ query = SearchQueryString "inbox:yes"
|
||||||
|
, limit = 5
|
||||||
|
, details = True
|
||||||
|
, showHeaders = False
|
||||||
|
, columns = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dueDocuments : Texts -> Box
|
||||||
|
dueDocuments texts =
|
||||||
|
{ name = texts.dueInDays 10
|
||||||
|
, visible = True
|
||||||
|
, decoration = True
|
||||||
|
, colspan = 2
|
||||||
|
, content =
|
||||||
|
BoxQuery
|
||||||
|
{ query = SearchQueryString "due>today;-10d due<today;+10d"
|
||||||
|
, limit = 5
|
||||||
|
, details = True
|
||||||
|
, showHeaders = True
|
||||||
|
, columns =
|
||||||
|
[ IC.Name
|
||||||
|
, IC.Correspondent
|
||||||
|
, IC.DueDateShort
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
summary : Texts -> Box
|
||||||
|
summary texts =
|
||||||
|
{ name = texts.summaryName
|
||||||
|
, visible = True
|
||||||
|
, decoration = True
|
||||||
|
, colspan = 1
|
||||||
|
, content =
|
||||||
|
BoxStats
|
||||||
|
{ query = SearchQueryString ""
|
||||||
|
, show = SummaryShowGeneral
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fieldStats : Box
|
||||||
|
fieldStats =
|
||||||
|
{ name = ""
|
||||||
|
, visible = True
|
||||||
|
, decoration = False
|
||||||
|
, colspan = 4
|
||||||
|
, content =
|
||||||
|
BoxStats
|
||||||
|
{ query = SearchQueryString ""
|
||||||
|
, show = SummaryShowFields False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
upload : Box
|
||||||
|
upload =
|
||||||
|
{ name = ""
|
||||||
|
, visible = True
|
||||||
|
, decoration = True
|
||||||
|
, colspan = 3
|
||||||
|
, content =
|
||||||
|
BoxUpload
|
||||||
|
{ sourceId = Nothing
|
||||||
|
}
|
||||||
|
}
|
180
modules/webapp/src/main/elm/Page/Dashboard/SideMenu.elm
Normal file
180
modules/webapp/src/main/elm/Page/Dashboard/SideMenu.elm
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Page.Dashboard.SideMenu exposing (view)
|
||||||
|
|
||||||
|
import Api.Model.VersionInfo exposing (VersionInfo)
|
||||||
|
import Comp.BookmarkChooser
|
||||||
|
import Data.AccountScope
|
||||||
|
import Data.Dashboard exposing (Dashboard)
|
||||||
|
import Data.Dashboards
|
||||||
|
import Data.Icons as Icons
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Attribute, Html, a, div, h3, i, span, text)
|
||||||
|
import Html.Attributes exposing (class, classList, href, target, title)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
|
import Messages.Page.Dashboard exposing (Texts)
|
||||||
|
import Page exposing (Page(..))
|
||||||
|
import Page.Dashboard.Data exposing (Model, Msg(..), isDashboardDefault, isDashboardVisible, isHomeContent)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> VersionInfo -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts versionInfo _ model =
|
||||||
|
div [ class "flex flex-col flex-grow" ]
|
||||||
|
[ div [ class "mt-2" ]
|
||||||
|
[ menuLink [ onClick SetDefaultDashboard, href "#" ] (Icons.dashboardIcon "") texts.dashboardLink
|
||||||
|
, menuLink [ Page.href (SearchPage Nothing) ] (Icons.searchIcon "") texts.basics.items
|
||||||
|
, menuLink [ onClick InitUpload, href "#" ] (Icons.fileUploadIcon "") texts.uploadFiles
|
||||||
|
]
|
||||||
|
, h3
|
||||||
|
[ class S.header3
|
||||||
|
, class "italic mt-3"
|
||||||
|
]
|
||||||
|
[ text texts.bookmarks
|
||||||
|
]
|
||||||
|
, div [ class "ml-2" ]
|
||||||
|
[ Html.map BookmarkMsg
|
||||||
|
(Comp.BookmarkChooser.viewWith
|
||||||
|
{ showUser = True, showCollective = True, showShares = False }
|
||||||
|
texts.bookmarkChooser
|
||||||
|
model.sideMenu.bookmarkChooser
|
||||||
|
Comp.BookmarkChooser.emptySelection
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, h3
|
||||||
|
[ class S.header3
|
||||||
|
, class "italic mt-3"
|
||||||
|
]
|
||||||
|
[ text texts.settings
|
||||||
|
]
|
||||||
|
, div [ class "ml-2 mb-2" ]
|
||||||
|
[ menuLink [ onClick InitNotificationHook, href "#" ] (Icons.notificationHooksIcon "") texts.basics.notificationHooks
|
||||||
|
, menuLink [ onClick InitPeriodicQuery, href "#" ] (Icons.periodicTasksIcon "") texts.basics.periodicQueries
|
||||||
|
, menuLink [ onClick InitSource, href "#" ] (Icons.sourceIcon2 "") texts.basics.sources
|
||||||
|
, menuLink [ onClick InitShare, href "#" ] (Icons.shareIcon "") texts.basics.shares
|
||||||
|
]
|
||||||
|
, h3
|
||||||
|
[ class S.header3
|
||||||
|
, class "italic mt-3"
|
||||||
|
]
|
||||||
|
[ text texts.manage
|
||||||
|
]
|
||||||
|
, div [ class "ml-2 mb-2" ]
|
||||||
|
[ menuLink [ onClick InitOrganization, href "#" ] (Icons.organizationIcon "") texts.basics.organization
|
||||||
|
, menuLink [ onClick InitPerson, href "#" ] (Icons.personIcon "") texts.basics.person
|
||||||
|
, menuLink [ onClick InitEquipment, href "#" ] (Icons.equipmentIcon "") texts.basics.equipment
|
||||||
|
, menuLink [ onClick InitTags, href "#" ] (Icons.tagsIcon "") texts.basics.tags
|
||||||
|
, menuLink [ onClick InitFolder, href "#" ] (Icons.folderIcon "") texts.basics.folder
|
||||||
|
]
|
||||||
|
, h3
|
||||||
|
[ class S.header3
|
||||||
|
, class "italic mt-3"
|
||||||
|
, classList [ ( "hidden", Data.Dashboards.countAll model.dashboards <= 1 ) ]
|
||||||
|
]
|
||||||
|
[ text texts.dashboards
|
||||||
|
]
|
||||||
|
, div
|
||||||
|
[ class "ml-2"
|
||||||
|
, classList [ ( "hidden", Data.Dashboards.countAll model.dashboards <= 1 ) ]
|
||||||
|
]
|
||||||
|
[ titleDiv <| texts.accountScope Data.AccountScope.User
|
||||||
|
, div
|
||||||
|
[ classList [ ( "hidden", Data.Dashboards.isEmpty model.dashboards.user ) ]
|
||||||
|
]
|
||||||
|
(Data.Dashboards.map (dashboardLink texts model) model.dashboards.user)
|
||||||
|
, titleDiv <| texts.accountScope Data.AccountScope.Collective
|
||||||
|
, div
|
||||||
|
[ classList [ ( "hidden", Data.Dashboards.isEmpty model.dashboards.collective ) ]
|
||||||
|
]
|
||||||
|
(Data.Dashboards.map (dashboardLink texts model) model.dashboards.collective)
|
||||||
|
]
|
||||||
|
, h3
|
||||||
|
[ class S.header3
|
||||||
|
, class "italic mt-3"
|
||||||
|
]
|
||||||
|
[ text texts.misc
|
||||||
|
]
|
||||||
|
, div [ class "ml-2" ]
|
||||||
|
[ menuLink
|
||||||
|
[ onClick InitEditDashboard
|
||||||
|
, classList [ ( "hidden", not (isHomeContent model.content) ) ]
|
||||||
|
, href "#"
|
||||||
|
]
|
||||||
|
(Icons.editIcon "")
|
||||||
|
texts.editDashboard
|
||||||
|
, div [ class "mt-2 opacity-75" ]
|
||||||
|
[ menuLink [ href Data.UiSettings.documentationSite, target "_blank" ]
|
||||||
|
(Icons.documentationIcon "")
|
||||||
|
texts.documentation
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "flex flex-grow items-end" ]
|
||||||
|
[ div [ class "text-center text-xs w-full opacity-50" ]
|
||||||
|
[ text "Docspell "
|
||||||
|
, text versionInfo.version
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
titleDiv : String -> Html msg
|
||||||
|
titleDiv label =
|
||||||
|
div [ class "text-sm opacity-75 py-0.5 italic" ]
|
||||||
|
[ text label
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
menuLinkStyle : String
|
||||||
|
menuLinkStyle =
|
||||||
|
"my-1 flex flex-row items-center rounded px-1 py-1 hover:bg-blue-100 dark:hover:bg-slate-600"
|
||||||
|
|
||||||
|
|
||||||
|
menuLink : List (Attribute Msg) -> Html Msg -> String -> Html Msg
|
||||||
|
menuLink attrs icon label =
|
||||||
|
a
|
||||||
|
(attrs ++ [ class menuLinkStyle ])
|
||||||
|
[ icon
|
||||||
|
, span [ class "ml-2" ]
|
||||||
|
[ text label
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
dashboardLink : Texts -> Model -> Dashboard -> Html Msg
|
||||||
|
dashboardLink texts model db =
|
||||||
|
let
|
||||||
|
( visible, default ) =
|
||||||
|
( isDashboardVisible model db.name
|
||||||
|
, isDashboardDefault model db.name
|
||||||
|
)
|
||||||
|
in
|
||||||
|
a
|
||||||
|
[ class menuLinkStyle
|
||||||
|
, classList [ ( "italic", visible ) ]
|
||||||
|
, href "#"
|
||||||
|
, onClick (SetDashboard db)
|
||||||
|
]
|
||||||
|
[ if visible then
|
||||||
|
i [ class "fa fa-check mr-2" ] []
|
||||||
|
|
||||||
|
else
|
||||||
|
i [ class "fa fa-columns mr-2" ] []
|
||||||
|
, div [ class "flex flex-row flex-grow space-x-1" ]
|
||||||
|
[ div [ class "flex flex-grow" ]
|
||||||
|
[ text db.name
|
||||||
|
]
|
||||||
|
, div [ class "opacity-50" ]
|
||||||
|
[ i
|
||||||
|
[ classList [ ( "hidden", not default ) ]
|
||||||
|
, class "fa fa-house-user"
|
||||||
|
, title texts.defaultDashboard.default
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
451
modules/webapp/src/main/elm/Page/Dashboard/Update.elm
Normal file
451
modules/webapp/src/main/elm/Page/Dashboard/Update.elm
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Page.Dashboard.Update exposing (update)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Browser.Navigation as Nav
|
||||||
|
import Comp.BookmarkChooser
|
||||||
|
import Comp.DashboardManage
|
||||||
|
import Comp.DashboardView
|
||||||
|
import Comp.EquipmentManage
|
||||||
|
import Comp.FolderManage
|
||||||
|
import Comp.NotificationHookManage
|
||||||
|
import Comp.OrgManage
|
||||||
|
import Comp.PeriodicQueryTaskManage
|
||||||
|
import Comp.PersonManage
|
||||||
|
import Comp.ShareManage
|
||||||
|
import Comp.SourceManage
|
||||||
|
import Comp.TagManage
|
||||||
|
import Comp.UploadForm
|
||||||
|
import Data.AccountScope
|
||||||
|
import Data.Dashboards
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Messages.Page.Dashboard exposing (Texts)
|
||||||
|
import Page exposing (Page(..))
|
||||||
|
import Page.Dashboard.Data exposing (..)
|
||||||
|
import Page.Dashboard.DefaultDashboard
|
||||||
|
import Set
|
||||||
|
|
||||||
|
|
||||||
|
update : Texts -> UiSettings -> Nav.Key -> Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update texts settings navKey flags msg model =
|
||||||
|
let
|
||||||
|
nextRun amsg =
|
||||||
|
nextRunModel amsg model
|
||||||
|
|
||||||
|
nextRunModel amsg amodel =
|
||||||
|
update texts settings navKey flags amsg amodel
|
||||||
|
in
|
||||||
|
case msg of
|
||||||
|
GetBookmarksResp list ->
|
||||||
|
let
|
||||||
|
sideMenu =
|
||||||
|
model.sideMenu
|
||||||
|
in
|
||||||
|
unit
|
||||||
|
{ model | sideMenu = { sideMenu | bookmarkChooser = Comp.BookmarkChooser.init list } }
|
||||||
|
|
||||||
|
GetAllDashboardsResp next (Ok boards) ->
|
||||||
|
let
|
||||||
|
nextModel =
|
||||||
|
if Data.Dashboards.isEmptyAll boards then
|
||||||
|
{ model
|
||||||
|
| dashboards =
|
||||||
|
Data.Dashboards.singletonAll <|
|
||||||
|
Page.Dashboard.DefaultDashboard.value texts.defaultDashboard
|
||||||
|
, isPredefined = True
|
||||||
|
, pageError = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{ model | dashboards = boards, isPredefined = False, pageError = Nothing }
|
||||||
|
in
|
||||||
|
case next of
|
||||||
|
Just nextMsg ->
|
||||||
|
nextRunModel nextMsg nextModel
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
unit nextModel
|
||||||
|
|
||||||
|
GetAllDashboardsResp _ (Err err) ->
|
||||||
|
unit { model | pageError = Just <| PageErrorHttp err }
|
||||||
|
|
||||||
|
BookmarkMsg lm ->
|
||||||
|
let
|
||||||
|
sideMenu =
|
||||||
|
model.sideMenu
|
||||||
|
|
||||||
|
( bm, sel ) =
|
||||||
|
Comp.BookmarkChooser.update
|
||||||
|
lm
|
||||||
|
sideMenu.bookmarkChooser
|
||||||
|
Comp.BookmarkChooser.emptySelection
|
||||||
|
|
||||||
|
bmId =
|
||||||
|
Set.toList sel.bookmarks |> List.head
|
||||||
|
in
|
||||||
|
( { model | sideMenu = { sideMenu | bookmarkChooser = bm } }
|
||||||
|
, Page.set navKey (SearchPage bmId)
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
ReloadDashboardData ->
|
||||||
|
let
|
||||||
|
lm =
|
||||||
|
DashboardMsg Comp.DashboardView.reloadData
|
||||||
|
in
|
||||||
|
update texts settings navKey flags lm model
|
||||||
|
|
||||||
|
HardReloadDashboard ->
|
||||||
|
case model.content of
|
||||||
|
Home dm ->
|
||||||
|
let
|
||||||
|
board =
|
||||||
|
dm.dashboard
|
||||||
|
|
||||||
|
( dm_, dc ) =
|
||||||
|
Comp.DashboardView.init flags board
|
||||||
|
in
|
||||||
|
( { model | content = Home dm_ }, Cmd.map DashboardMsg dc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
SetDashboard db ->
|
||||||
|
let
|
||||||
|
isVisible =
|
||||||
|
case model.content of
|
||||||
|
Home dm ->
|
||||||
|
dm.dashboard.name == db.name
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
in
|
||||||
|
if isVisible then
|
||||||
|
update texts settings navKey flags ReloadDashboardData model
|
||||||
|
|
||||||
|
else
|
||||||
|
let
|
||||||
|
( dbm, dbc ) =
|
||||||
|
Comp.DashboardView.init flags db
|
||||||
|
in
|
||||||
|
( { model | content = Home dbm, pageError = Nothing }
|
||||||
|
, Cmd.map DashboardMsg dbc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
SetDefaultDashboard ->
|
||||||
|
case Data.Dashboards.getAllDefault model.dashboards of
|
||||||
|
Just db ->
|
||||||
|
nextRun (SetDashboard db)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
SetDashboardByName name ->
|
||||||
|
case Data.Dashboards.findInAll name model.dashboards of
|
||||||
|
Just db ->
|
||||||
|
nextRun (SetDashboard db)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
InitNotificationHook ->
|
||||||
|
let
|
||||||
|
( nhm, nhc ) =
|
||||||
|
Comp.NotificationHookManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Webhook nhm }, Cmd.map NotificationHookMsg nhc, Sub.none )
|
||||||
|
|
||||||
|
InitPeriodicQuery ->
|
||||||
|
let
|
||||||
|
( pqm, pqc ) =
|
||||||
|
Comp.PeriodicQueryTaskManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = PeriodicQuery pqm }, Cmd.map PeriodicQueryMsg pqc, Sub.none )
|
||||||
|
|
||||||
|
InitSource ->
|
||||||
|
let
|
||||||
|
( sm, sc ) =
|
||||||
|
Comp.SourceManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Source sm }, Cmd.map SourceMsg sc, Sub.none )
|
||||||
|
|
||||||
|
InitShare ->
|
||||||
|
let
|
||||||
|
( sm, sc ) =
|
||||||
|
Comp.ShareManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Share sm }, Cmd.map ShareMsg sc, Sub.none )
|
||||||
|
|
||||||
|
InitOrganization ->
|
||||||
|
let
|
||||||
|
( om, oc ) =
|
||||||
|
Comp.OrgManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Organization om }, Cmd.map OrganizationMsg oc, Sub.none )
|
||||||
|
|
||||||
|
InitPerson ->
|
||||||
|
let
|
||||||
|
( pm, pc ) =
|
||||||
|
Comp.PersonManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Person pm }, Cmd.map PersonMsg pc, Sub.none )
|
||||||
|
|
||||||
|
InitEquipment ->
|
||||||
|
let
|
||||||
|
( em, ec ) =
|
||||||
|
Comp.EquipmentManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Equipment em }, Cmd.map EquipmentMsg ec, Sub.none )
|
||||||
|
|
||||||
|
InitTags ->
|
||||||
|
let
|
||||||
|
( tm, tc ) =
|
||||||
|
Comp.TagManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Tags tm }, Cmd.map TagMsg tc, Sub.none )
|
||||||
|
|
||||||
|
InitFolder ->
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.FolderManage.init flags
|
||||||
|
in
|
||||||
|
( { model | content = Folder fm }, Cmd.map FolderMsg fc, Sub.none )
|
||||||
|
|
||||||
|
InitUpload ->
|
||||||
|
let
|
||||||
|
um =
|
||||||
|
Comp.UploadForm.init
|
||||||
|
in
|
||||||
|
( { model | content = Upload um }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
InitEditDashboard ->
|
||||||
|
case model.content of
|
||||||
|
Home m ->
|
||||||
|
let
|
||||||
|
default =
|
||||||
|
Data.Dashboards.isDefaultAll m.dashboard.name model.dashboards
|
||||||
|
|
||||||
|
scope =
|
||||||
|
Data.Dashboards.getScope m.dashboard.name model.dashboards
|
||||||
|
|> Maybe.withDefault Data.AccountScope.User
|
||||||
|
|
||||||
|
( dm, dc, ds ) =
|
||||||
|
Comp.DashboardManage.init
|
||||||
|
{ flags = flags
|
||||||
|
, dashboard = m.dashboard
|
||||||
|
, scope = scope
|
||||||
|
, isDefault = default
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( { model | content = Edit dm }
|
||||||
|
, Cmd.map DashboardManageMsg dc
|
||||||
|
, Sub.map DashboardManageMsg ds
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
NotificationHookMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Webhook nhm ->
|
||||||
|
let
|
||||||
|
( nhm_, nhc ) =
|
||||||
|
Comp.NotificationHookManage.update flags lm nhm
|
||||||
|
in
|
||||||
|
( { model | content = Webhook nhm_ }, Cmd.map NotificationHookMsg nhc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
PeriodicQueryMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
PeriodicQuery pqm ->
|
||||||
|
let
|
||||||
|
( pqm_, pqc, pqs ) =
|
||||||
|
Comp.PeriodicQueryTaskManage.update flags lm pqm
|
||||||
|
in
|
||||||
|
( { model | content = PeriodicQuery pqm_ }
|
||||||
|
, Cmd.map PeriodicQueryMsg pqc
|
||||||
|
, Sub.map PeriodicQueryMsg pqs
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
SourceMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Source m ->
|
||||||
|
let
|
||||||
|
( sm, sc ) =
|
||||||
|
Comp.SourceManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Source sm }, Cmd.map SourceMsg sc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
ShareMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Share m ->
|
||||||
|
let
|
||||||
|
( sm, sc, subs ) =
|
||||||
|
Comp.ShareManage.update texts.shareManage flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Share sm }
|
||||||
|
, Cmd.map ShareMsg sc
|
||||||
|
, Sub.map ShareMsg subs
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
OrganizationMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Organization m ->
|
||||||
|
let
|
||||||
|
( om, oc ) =
|
||||||
|
Comp.OrgManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Organization om }, Cmd.map OrganizationMsg oc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
PersonMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Person m ->
|
||||||
|
let
|
||||||
|
( pm, pc ) =
|
||||||
|
Comp.PersonManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Person pm }, Cmd.map PersonMsg pc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
EquipmentMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Equipment m ->
|
||||||
|
let
|
||||||
|
( em, ec ) =
|
||||||
|
Comp.EquipmentManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Equipment em }, Cmd.map EquipmentMsg ec, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
TagMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Tags m ->
|
||||||
|
let
|
||||||
|
( tm, tc ) =
|
||||||
|
Comp.TagManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Tags tm }, Cmd.map TagMsg tc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
FolderMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Folder m ->
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.FolderManage.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Folder fm }, Cmd.map FolderMsg fc, Sub.none )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
UploadMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Upload m ->
|
||||||
|
let
|
||||||
|
( um, uc, us ) =
|
||||||
|
Comp.UploadForm.update Nothing flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Upload um }, Cmd.map UploadMsg uc, Sub.map UploadMsg us )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
DashboardMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Home m ->
|
||||||
|
let
|
||||||
|
( dm, dc, ds ) =
|
||||||
|
Comp.DashboardView.update flags lm m
|
||||||
|
in
|
||||||
|
( { model | content = Home dm }, Cmd.map DashboardMsg dc, Sub.map DashboardMsg ds )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
DashboardManageMsg lm ->
|
||||||
|
case model.content of
|
||||||
|
Edit m ->
|
||||||
|
let
|
||||||
|
nameExists name =
|
||||||
|
Data.Dashboards.existsAll name model.dashboards
|
||||||
|
|
||||||
|
result =
|
||||||
|
Comp.DashboardManage.update flags nameExists lm m
|
||||||
|
in
|
||||||
|
case result.action of
|
||||||
|
Comp.DashboardManage.SubmitNone ->
|
||||||
|
( { model | content = Edit result.model }
|
||||||
|
, Cmd.map DashboardManageMsg result.cmd
|
||||||
|
, Sub.map DashboardManageMsg result.sub
|
||||||
|
)
|
||||||
|
|
||||||
|
Comp.DashboardManage.SubmitSaved name ->
|
||||||
|
( { model | content = Edit result.model }
|
||||||
|
, Cmd.batch
|
||||||
|
[ Cmd.map DashboardManageMsg result.cmd
|
||||||
|
, getDashboards flags (Just <| SetDashboardByName name)
|
||||||
|
]
|
||||||
|
, Sub.map DashboardManageMsg result.sub
|
||||||
|
)
|
||||||
|
|
||||||
|
Comp.DashboardManage.SubmitCancel name ->
|
||||||
|
case Data.Dashboards.findInAll name model.dashboards of
|
||||||
|
Just db ->
|
||||||
|
update texts settings navKey flags (SetDashboard db) model
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( { model | content = Edit result.model }
|
||||||
|
, Cmd.map DashboardManageMsg result.cmd
|
||||||
|
, Sub.map DashboardManageMsg result.sub
|
||||||
|
)
|
||||||
|
|
||||||
|
Comp.DashboardManage.SubmitDeleted ->
|
||||||
|
( { model | content = Edit result.model }
|
||||||
|
, Cmd.batch
|
||||||
|
[ Cmd.map DashboardManageMsg result.cmd
|
||||||
|
, getDashboards flags (Just SetDefaultDashboard)
|
||||||
|
]
|
||||||
|
, Sub.map DashboardManageMsg result.sub
|
||||||
|
)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
unit model
|
||||||
|
|
||||||
|
|
||||||
|
unit : Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
unit m =
|
||||||
|
( m, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
|
||||||
|
getDashboards : Flags -> Maybe Msg -> Cmd Msg
|
||||||
|
getDashboards flags nextMsg =
|
||||||
|
Api.getAllDashboards flags (GetAllDashboardsResp nextMsg)
|
226
modules/webapp/src/main/elm/Page/Dashboard/View.elm
Normal file
226
modules/webapp/src/main/elm/Page/Dashboard/View.elm
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Page.Dashboard.View exposing (viewContent, viewSidebar)
|
||||||
|
|
||||||
|
import Api.Model.VersionInfo exposing (VersionInfo)
|
||||||
|
import Comp.DashboardManage
|
||||||
|
import Comp.DashboardView
|
||||||
|
import Comp.EquipmentManage
|
||||||
|
import Comp.FolderManage
|
||||||
|
import Comp.NotificationHookManage
|
||||||
|
import Comp.OrgManage
|
||||||
|
import Comp.PeriodicQueryTaskManage
|
||||||
|
import Comp.PersonManage
|
||||||
|
import Comp.ShareManage
|
||||||
|
import Comp.SourceManage
|
||||||
|
import Comp.TagManage
|
||||||
|
import Comp.UploadForm
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Messages.Page.Dashboard exposing (Texts)
|
||||||
|
import Page.Dashboard.Data exposing (..)
|
||||||
|
import Page.Dashboard.SideMenu as SideMenu
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
viewSidebar : Texts -> Bool -> Flags -> VersionInfo -> UiSettings -> Model -> Html Msg
|
||||||
|
viewSidebar texts visible _ versionInfo settings model =
|
||||||
|
div
|
||||||
|
[ id "sidebar"
|
||||||
|
, class S.sidebar
|
||||||
|
, class S.sidebarBg
|
||||||
|
, classList [ ( "hidden", not visible ) ]
|
||||||
|
]
|
||||||
|
[ SideMenu.view texts versionInfo settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
|
viewContent texts flags settings model =
|
||||||
|
let
|
||||||
|
editSettings =
|
||||||
|
{ showDeleteButton = not model.isPredefined
|
||||||
|
, showCopyButton = not model.isPredefined
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ id "content"
|
||||||
|
, class S.content
|
||||||
|
]
|
||||||
|
[ case model.content of
|
||||||
|
Home m ->
|
||||||
|
div [ class "mt-1" ]
|
||||||
|
[ Html.map DashboardMsg
|
||||||
|
(Comp.DashboardView.view texts.dashboard flags settings m)
|
||||||
|
]
|
||||||
|
|
||||||
|
Edit m ->
|
||||||
|
div [ class "mt-1" ]
|
||||||
|
[ div
|
||||||
|
[ class S.infoMessage
|
||||||
|
, class "my-1"
|
||||||
|
, classList [ ( "hidden", not model.isPredefined ) ]
|
||||||
|
]
|
||||||
|
[ text texts.predefinedMessage ]
|
||||||
|
, Html.map DashboardManageMsg
|
||||||
|
(Comp.DashboardManage.view texts.dashboardManage flags editSettings settings m)
|
||||||
|
]
|
||||||
|
|
||||||
|
Webhook m ->
|
||||||
|
viewHookManage texts settings m
|
||||||
|
|
||||||
|
PeriodicQuery m ->
|
||||||
|
viewPeriodicQuery texts settings m
|
||||||
|
|
||||||
|
Source m ->
|
||||||
|
viewSource texts flags settings m
|
||||||
|
|
||||||
|
Share m ->
|
||||||
|
viewShare texts flags settings m
|
||||||
|
|
||||||
|
Organization m ->
|
||||||
|
viewOrganization texts settings m
|
||||||
|
|
||||||
|
Person m ->
|
||||||
|
viewPerson texts settings m
|
||||||
|
|
||||||
|
Equipment m ->
|
||||||
|
viewEquipment texts m
|
||||||
|
|
||||||
|
Tags m ->
|
||||||
|
viewTags texts settings m
|
||||||
|
|
||||||
|
Folder m ->
|
||||||
|
viewFolder texts flags m
|
||||||
|
|
||||||
|
Upload m ->
|
||||||
|
viewUplod texts flags settings m
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
viewUplod : Texts -> Flags -> UiSettings -> Comp.UploadForm.Model -> Html Msg
|
||||||
|
viewUplod texts flags settings model =
|
||||||
|
let
|
||||||
|
viewCfg =
|
||||||
|
{ showForm = True
|
||||||
|
, sourceId = Nothing
|
||||||
|
, lightForm = False
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.uploadFiles
|
||||||
|
]
|
||||||
|
, Html.map UploadMsg <|
|
||||||
|
Comp.UploadForm.view texts.uploadForm viewCfg flags settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewFolder : Texts -> Flags -> Comp.FolderManage.Model -> Html Msg
|
||||||
|
viewFolder texts flags model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.folder
|
||||||
|
]
|
||||||
|
, Html.map FolderMsg <|
|
||||||
|
Comp.FolderManage.view2 texts.folderManage flags model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewTags : Texts -> UiSettings -> Comp.TagManage.Model -> Html Msg
|
||||||
|
viewTags texts settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.tags
|
||||||
|
]
|
||||||
|
, Html.map TagMsg <|
|
||||||
|
Comp.TagManage.view2 texts.tagManage settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewEquipment : Texts -> Comp.EquipmentManage.Model -> Html Msg
|
||||||
|
viewEquipment texts model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.equipment
|
||||||
|
]
|
||||||
|
, Html.map EquipmentMsg <|
|
||||||
|
Comp.EquipmentManage.view2 texts.equipManage model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewPerson : Texts -> UiSettings -> Comp.PersonManage.Model -> Html Msg
|
||||||
|
viewPerson texts settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.person
|
||||||
|
]
|
||||||
|
, Html.map PersonMsg <|
|
||||||
|
Comp.PersonManage.view2 texts.personManage settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewOrganization : Texts -> UiSettings -> Comp.OrgManage.Model -> Html Msg
|
||||||
|
viewOrganization texts settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.organization
|
||||||
|
]
|
||||||
|
, Html.map OrganizationMsg <|
|
||||||
|
Comp.OrgManage.view2 texts.organizationManage settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewShare : Texts -> Flags -> UiSettings -> Comp.ShareManage.Model -> Html Msg
|
||||||
|
viewShare texts flags settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.shares
|
||||||
|
]
|
||||||
|
, Html.map ShareMsg <|
|
||||||
|
Comp.ShareManage.view texts.shareManage settings flags model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewSource : Texts -> Flags -> UiSettings -> Comp.SourceManage.Model -> Html Msg
|
||||||
|
viewSource texts flags settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.sources
|
||||||
|
]
|
||||||
|
, Html.map SourceMsg <|
|
||||||
|
Comp.SourceManage.view2 texts.sourceManage flags settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewPeriodicQuery : Texts -> UiSettings -> Comp.PeriodicQueryTaskManage.Model -> Html Msg
|
||||||
|
viewPeriodicQuery texts settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.periodicQueries
|
||||||
|
]
|
||||||
|
, Html.map PeriodicQueryMsg <|
|
||||||
|
Comp.PeriodicQueryTaskManage.view texts.periodicQueryManage settings model
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewHookManage : Texts -> UiSettings -> Comp.NotificationHookManage.Model -> Html Msg
|
||||||
|
viewHookManage texts settings model =
|
||||||
|
div []
|
||||||
|
[ h1 [ class S.header1 ]
|
||||||
|
[ text texts.basics.notificationHooks
|
||||||
|
]
|
||||||
|
, Html.map NotificationHookMsg <|
|
||||||
|
Comp.NotificationHookManage.view texts.notificationHookManage settings model
|
||||||
|
]
|
@ -60,7 +60,7 @@ update key flags inav settings msg model =
|
|||||||
Cmd.none
|
Cmd.none
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
Page.set key HomePage
|
Page.set key (SearchPage Nothing)
|
||||||
in
|
in
|
||||||
{ model = { model | detail = result.model }
|
{ model = { model | detail = result.model }
|
||||||
, cmd = Cmd.batch [ pageSwitch, Cmd.map ItemDetailMsg result.cmd ]
|
, cmd = Cmd.batch [ pageSwitch, Cmd.map ItemDetailMsg result.cmd ]
|
||||||
|
@ -53,7 +53,7 @@ update loginData flags msg model =
|
|||||||
AuthResp (Ok lr) ->
|
AuthResp (Ok lr) ->
|
||||||
let
|
let
|
||||||
gotoRef =
|
gotoRef =
|
||||||
Maybe.withDefault HomePage loginData.referrer |> Page.goto
|
Maybe.withDefault DashboardPage loginData.referrer |> Page.goto
|
||||||
in
|
in
|
||||||
if lr.success && not lr.requireSecondFactor then
|
if lr.success && not lr.requireSecondFactor then
|
||||||
( { model | formState = AuthSuccess lr, password = "" }
|
( { model | formState = AuthSuccess lr, password = "" }
|
||||||
|
@ -46,7 +46,7 @@ viewSidebar texts visible _ settings model =
|
|||||||
, class S.sidebarLink
|
, class S.sidebarLink
|
||||||
, menuEntryActive model TagTab
|
, menuEntryActive model TagTab
|
||||||
]
|
]
|
||||||
[ Icons.tagIcon2 ""
|
[ Icons.tagIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.basics.tags
|
[ text texts.basics.tags
|
||||||
@ -58,7 +58,7 @@ viewSidebar texts visible _ settings model =
|
|||||||
, menuEntryActive model EquipTab
|
, menuEntryActive model EquipTab
|
||||||
, class S.sidebarLink
|
, class S.sidebarLink
|
||||||
]
|
]
|
||||||
[ Icons.equipmentIcon2 ""
|
[ Icons.equipmentIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.basics.equipment
|
[ text texts.basics.equipment
|
||||||
@ -70,7 +70,7 @@ viewSidebar texts visible _ settings model =
|
|||||||
, menuEntryActive model OrgTab
|
, menuEntryActive model OrgTab
|
||||||
, class S.sidebarLink
|
, class S.sidebarLink
|
||||||
]
|
]
|
||||||
[ Icons.organizationIcon2 ""
|
[ Icons.organizationIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.basics.organization
|
[ text texts.basics.organization
|
||||||
@ -82,7 +82,7 @@ viewSidebar texts visible _ settings model =
|
|||||||
, menuEntryActive model PersonTab
|
, menuEntryActive model PersonTab
|
||||||
, class S.sidebarLink
|
, class S.sidebarLink
|
||||||
]
|
]
|
||||||
[ Icons.personIcon2 ""
|
[ Icons.personIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.basics.person
|
[ text texts.basics.person
|
||||||
@ -99,7 +99,7 @@ viewSidebar texts visible _ settings model =
|
|||||||
, menuEntryActive model FolderTab
|
, menuEntryActive model FolderTab
|
||||||
, class S.sidebarLink
|
, class S.sidebarLink
|
||||||
]
|
]
|
||||||
[ Icons.folderIcon2 ""
|
[ Icons.folderIcon ""
|
||||||
, span
|
, span
|
||||||
[ class "ml-3" ]
|
[ class "ml-3" ]
|
||||||
[ text texts.basics.folder
|
[ text texts.basics.folder
|
||||||
@ -186,7 +186,7 @@ viewTags texts settings model =
|
|||||||
[ class S.header1
|
[ class S.header1
|
||||||
, class "inline-flex items-center"
|
, class "inline-flex items-center"
|
||||||
]
|
]
|
||||||
[ Icons.tagIcon2 ""
|
[ Icons.tagIcon ""
|
||||||
, div [ class "ml-2" ]
|
, div [ class "ml-2" ]
|
||||||
[ text texts.basics.tags
|
[ text texts.basics.tags
|
||||||
]
|
]
|
||||||
@ -206,7 +206,7 @@ viewEquip texts model =
|
|||||||
[ class S.header1
|
[ class S.header1
|
||||||
, class "inline-flex items-center"
|
, class "inline-flex items-center"
|
||||||
]
|
]
|
||||||
[ Icons.equipmentIcon2 ""
|
[ Icons.equipmentIcon ""
|
||||||
, div [ class "ml-2" ]
|
, div [ class "ml-2" ]
|
||||||
[ text texts.basics.equipment
|
[ text texts.basics.equipment
|
||||||
]
|
]
|
||||||
@ -224,7 +224,7 @@ viewOrg texts settings model =
|
|||||||
[ class S.header1
|
[ class S.header1
|
||||||
, class "inline-flex items-center"
|
, class "inline-flex items-center"
|
||||||
]
|
]
|
||||||
[ Icons.organizationIcon2 ""
|
[ Icons.organizationIcon ""
|
||||||
, div [ class "ml-2" ]
|
, div [ class "ml-2" ]
|
||||||
[ text texts.basics.organization
|
[ text texts.basics.organization
|
||||||
]
|
]
|
||||||
@ -243,7 +243,7 @@ viewPerson texts settings model =
|
|||||||
[ class S.header1
|
[ class S.header1
|
||||||
, class "inline-flex items-center"
|
, class "inline-flex items-center"
|
||||||
]
|
]
|
||||||
[ Icons.personIcon2 ""
|
[ Icons.personIcon ""
|
||||||
, div [ class "ml-2" ]
|
, div [ class "ml-2" ]
|
||||||
[ text texts.basics.person
|
[ text texts.basics.person
|
||||||
]
|
]
|
||||||
@ -262,7 +262,7 @@ viewFolder texts flags _ model =
|
|||||||
[ class S.header1
|
[ class S.header1
|
||||||
, class "inline-flex items-center"
|
, class "inline-flex items-center"
|
||||||
]
|
]
|
||||||
[ Icons.folderIcon2 ""
|
[ Icons.folderIcon ""
|
||||||
, div
|
, div
|
||||||
[ class "ml-2"
|
[ class "ml-2"
|
||||||
]
|
]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Page.Home.Data exposing
|
module Page.Search.Data exposing
|
||||||
( ConfirmModalValue(..)
|
( ConfirmModalValue(..)
|
||||||
, Model
|
, Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
@ -48,7 +48,6 @@ import Data.Items
|
|||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import Http
|
import Http
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
import Throttle exposing (Throttle)
|
|
||||||
import Util.Html exposing (KeyCode(..))
|
import Util.Html exposing (KeyCode(..))
|
||||||
import Util.ItemDragDrop as DD
|
import Util.ItemDragDrop as DD
|
||||||
|
|
||||||
@ -61,7 +60,6 @@ type alias Model =
|
|||||||
, searchOffset : Int
|
, searchOffset : Int
|
||||||
, moreAvailable : Bool
|
, moreAvailable : Bool
|
||||||
, moreInProgress : Bool
|
, moreInProgress : Bool
|
||||||
, throttle : Throttle Msg
|
|
||||||
, searchTypeDropdownValue : SearchType
|
, searchTypeDropdownValue : SearchType
|
||||||
, lastSearchType : SearchType
|
, lastSearchType : SearchType
|
||||||
, dragDropData : DD.DragDropData
|
, dragDropData : DD.DragDropData
|
||||||
@ -129,7 +127,6 @@ init flags viewMode =
|
|||||||
, searchOffset = 0
|
, searchOffset = 0
|
||||||
, moreAvailable = True
|
, moreAvailable = True
|
||||||
, moreInProgress = False
|
, moreInProgress = False
|
||||||
, throttle = Throttle.create 1
|
|
||||||
, searchTypeDropdownValue =
|
, searchTypeDropdownValue =
|
||||||
if Comp.SearchMenu.isFulltextSearch searchMenuModel then
|
if Comp.SearchMenu.isFulltextSearch searchMenuModel then
|
||||||
ContentOnlySearch
|
ContentOnlySearch
|
||||||
@ -199,6 +196,7 @@ editActive model =
|
|||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= Init
|
= Init
|
||||||
|
| DoNothing
|
||||||
| SearchMenuMsg Comp.SearchMenu.Msg
|
| SearchMenuMsg Comp.SearchMenu.Msg
|
||||||
| ResetSearch
|
| ResetSearch
|
||||||
| ItemCardListMsg Comp.ItemCardList.Msg
|
| ItemCardListMsg Comp.ItemCardList.Msg
|
||||||
@ -208,7 +206,6 @@ type Msg
|
|||||||
| ToggleSearchMenu
|
| ToggleSearchMenu
|
||||||
| ToggleSelectView
|
| ToggleSelectView
|
||||||
| LoadMore
|
| LoadMore
|
||||||
| UpdateThrottle
|
|
||||||
| SetBasicSearch String
|
| SetBasicSearch String
|
||||||
| ToggleSearchType
|
| ToggleSearchType
|
||||||
| KeyUpSearchbarMsg (Maybe KeyCode)
|
| KeyUpSearchbarMsg (Maybe KeyCode)
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Page.Home.SideMenu exposing (view)
|
module Page.Search.SideMenu exposing (view)
|
||||||
|
|
||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
import Comp.ItemDetail.MultiEditMenu
|
import Comp.ItemDetail.MultiEditMenu
|
||||||
@ -16,8 +16,8 @@ import Data.UiSettings exposing (UiSettings)
|
|||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick)
|
import Html.Events exposing (onClick)
|
||||||
import Messages.Page.HomeSideMenu exposing (Texts)
|
import Messages.Page.SearchSideMenu exposing (Texts)
|
||||||
import Page.Home.Data exposing (..)
|
import Page.Search.Data exposing (..)
|
||||||
import Set
|
import Set
|
||||||
import Styles as S
|
import Styles as S
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Page.Home.Update exposing
|
module Page.Search.Update exposing
|
||||||
( UpdateResult
|
( UpdateResult
|
||||||
, update
|
, update
|
||||||
)
|
)
|
||||||
@ -28,15 +28,13 @@ import Data.ItemSelection
|
|||||||
import Data.Items
|
import Data.Items
|
||||||
import Data.SearchMode exposing (SearchMode)
|
import Data.SearchMode exposing (SearchMode)
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import Messages.Page.Home exposing (Texts)
|
import Messages.Page.Search exposing (Texts)
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Page.Home.Data exposing (..)
|
import Page.Search.Data exposing (..)
|
||||||
import Process
|
import Process
|
||||||
import Scroll
|
import Scroll
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
import Task
|
import Task
|
||||||
import Throttle
|
|
||||||
import Time
|
|
||||||
import Util.Html exposing (KeyCode(..))
|
import Util.Html exposing (KeyCode(..))
|
||||||
import Util.ItemDragDrop as DD
|
import Util.ItemDragDrop as DD
|
||||||
import Util.Update
|
import Util.Update
|
||||||
@ -50,8 +48,8 @@ type alias UpdateResult =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
update : Maybe String -> Nav.Key -> Flags -> Texts -> UiSettings -> Msg -> Model -> UpdateResult
|
update : Maybe String -> Maybe String -> Nav.Key -> Flags -> Texts -> UiSettings -> Msg -> Model -> UpdateResult
|
||||||
update mId key flags texts settings msg model =
|
update bookmarkId mId key flags texts settings msg model =
|
||||||
case msg of
|
case msg of
|
||||||
Init ->
|
Init ->
|
||||||
let
|
let
|
||||||
@ -62,20 +60,28 @@ update mId key flags texts settings msg model =
|
|||||||
, offset = 0
|
, offset = 0
|
||||||
, scroll = True
|
, scroll = True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setBookmark =
|
||||||
|
Maybe.map (\bmId -> SearchMenuMsg <| Comp.SearchMenu.SetBookmark bmId) bookmarkId
|
||||||
|
|> Maybe.withDefault DoNothing
|
||||||
in
|
in
|
||||||
makeResult <|
|
makeResult <|
|
||||||
Util.Update.andThen3
|
Util.Update.andThen3
|
||||||
[ update mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.Init)
|
[ update bookmarkId mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.Init)
|
||||||
|
, update bookmarkId mId key flags texts settings setBookmark
|
||||||
, doSearch searchParam
|
, doSearch searchParam
|
||||||
]
|
]
|
||||||
model
|
model
|
||||||
|
|
||||||
|
DoNothing ->
|
||||||
|
UpdateResult model Cmd.none Sub.none Nothing
|
||||||
|
|
||||||
ResetSearch ->
|
ResetSearch ->
|
||||||
let
|
let
|
||||||
nm =
|
nm =
|
||||||
{ model | searchOffset = 0, powerSearchInput = Comp.PowerSearchInput.init }
|
{ model | searchOffset = 0, powerSearchInput = Comp.PowerSearchInput.init }
|
||||||
in
|
in
|
||||||
update mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm
|
update bookmarkId mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm
|
||||||
|
|
||||||
SearchMenuMsg m ->
|
SearchMenuMsg m ->
|
||||||
let
|
let
|
||||||
@ -121,7 +127,7 @@ update mId key flags texts settings msg model =
|
|||||||
SetLinkTarget lt ->
|
SetLinkTarget lt ->
|
||||||
case linkTargetMsg lt of
|
case linkTargetMsg lt of
|
||||||
Just m ->
|
Just m ->
|
||||||
update mId key flags texts settings m model
|
update bookmarkId mId key flags texts settings m model
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
makeResult ( model, Cmd.none, Sub.none )
|
makeResult ( model, Cmd.none, Sub.none )
|
||||||
@ -193,7 +199,7 @@ update mId key flags texts settings msg model =
|
|||||||
in
|
in
|
||||||
makeResult <|
|
makeResult <|
|
||||||
Util.Update.andThen3
|
Util.Update.andThen3
|
||||||
[ update mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.SetResults list))
|
[ update bookmarkId mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.SetResults list))
|
||||||
, if scroll then
|
, if scroll then
|
||||||
scrollToCard mId
|
scrollToCard mId
|
||||||
|
|
||||||
@ -215,7 +221,7 @@ update mId key flags texts settings msg model =
|
|||||||
, moreAvailable = list.groups /= []
|
, moreAvailable = list.groups /= []
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
update mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) m
|
update bookmarkId mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) m
|
||||||
|
|
||||||
ItemSearchAddResp (Err _) ->
|
ItemSearchAddResp (Err _) ->
|
||||||
withSub
|
withSub
|
||||||
@ -319,30 +325,23 @@ update mId key flags texts settings msg model =
|
|||||||
else
|
else
|
||||||
withSub ( model, Cmd.none )
|
withSub ( model, Cmd.none )
|
||||||
|
|
||||||
UpdateThrottle ->
|
|
||||||
let
|
|
||||||
( newThrottle, cmd ) =
|
|
||||||
Throttle.update model.throttle
|
|
||||||
in
|
|
||||||
withSub ( { model | throttle = newThrottle }, cmd )
|
|
||||||
|
|
||||||
SetBasicSearch str ->
|
SetBasicSearch str ->
|
||||||
let
|
let
|
||||||
smMsg =
|
smMsg =
|
||||||
SearchMenuMsg (Comp.SearchMenu.SetTextSearch str)
|
SearchMenuMsg (Comp.SearchMenu.SetTextSearch str)
|
||||||
in
|
in
|
||||||
update mId key flags texts settings smMsg model
|
update bookmarkId mId key flags texts settings smMsg model
|
||||||
|
|
||||||
ToggleSearchType ->
|
ToggleSearchType ->
|
||||||
case model.searchTypeDropdownValue of
|
case model.searchTypeDropdownValue of
|
||||||
BasicSearch ->
|
BasicSearch ->
|
||||||
update mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.SetFulltextSearch) model
|
update bookmarkId mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.SetFulltextSearch) model
|
||||||
|
|
||||||
ContentOnlySearch ->
|
ContentOnlySearch ->
|
||||||
update mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.SetNamesSearch) model
|
update bookmarkId mId key flags texts settings (SearchMenuMsg Comp.SearchMenu.SetNamesSearch) model
|
||||||
|
|
||||||
KeyUpSearchbarMsg (Just Enter) ->
|
KeyUpSearchbarMsg (Just Enter) ->
|
||||||
update mId key flags texts settings (DoSearch model.searchTypeDropdownValue) model
|
update bookmarkId mId key flags texts settings (DoSearch model.searchTypeDropdownValue) model
|
||||||
|
|
||||||
KeyUpSearchbarMsg _ ->
|
KeyUpSearchbarMsg _ ->
|
||||||
withSub ( model, Cmd.none )
|
withSub ( model, Cmd.none )
|
||||||
@ -653,7 +652,8 @@ update mId key flags texts settings msg model =
|
|||||||
{ model | viewMode = nextView }
|
{ model | viewMode = nextView }
|
||||||
in
|
in
|
||||||
if result.outcome == Comp.ItemMerge.OutcomeMerged then
|
if result.outcome == Comp.ItemMerge.OutcomeMerged then
|
||||||
update mId
|
update bookmarkId
|
||||||
|
mId
|
||||||
key
|
key
|
||||||
flags
|
flags
|
||||||
texts
|
texts
|
||||||
@ -733,7 +733,8 @@ update mId key flags texts settings msg model =
|
|||||||
{ model | viewMode = nextView }
|
{ model | viewMode = nextView }
|
||||||
in
|
in
|
||||||
if result.outcome == Comp.PublishItems.OutcomeDone then
|
if result.outcome == Comp.PublishItems.OutcomeDone then
|
||||||
update mId
|
update bookmarkId
|
||||||
|
mId
|
||||||
key
|
key
|
||||||
flags
|
flags
|
||||||
texts
|
texts
|
||||||
@ -853,7 +854,7 @@ update mId key flags texts settings msg model =
|
|||||||
model_ =
|
model_ =
|
||||||
{ model | viewMode = viewMode }
|
{ model | viewMode = viewMode }
|
||||||
in
|
in
|
||||||
update mId key flags texts settings (DoSearch model.lastSearchType) model_
|
update bookmarkId mId key flags texts settings (DoSearch model.lastSearchType) model_
|
||||||
|
|
||||||
SearchStatsResp result ->
|
SearchStatsResp result ->
|
||||||
let
|
let
|
||||||
@ -863,7 +864,7 @@ update mId key flags texts settings msg model =
|
|||||||
stats =
|
stats =
|
||||||
Result.withDefault model.searchStats result
|
Result.withDefault model.searchStats result
|
||||||
in
|
in
|
||||||
update mId key flags texts settings lm { model | searchStats = stats }
|
update bookmarkId mId key flags texts settings lm { model | searchStats = stats }
|
||||||
|
|
||||||
TogglePreviewFullWidth ->
|
TogglePreviewFullWidth ->
|
||||||
let
|
let
|
||||||
@ -905,16 +906,16 @@ update mId key flags texts settings msg model =
|
|||||||
makeResult ( model_, cmd_, Sub.map PowerSearchMsg result.subs )
|
makeResult ( model_, cmd_, Sub.map PowerSearchMsg result.subs )
|
||||||
|
|
||||||
Comp.PowerSearchInput.SubmitSearch ->
|
Comp.PowerSearchInput.SubmitSearch ->
|
||||||
update mId key flags texts settings (DoSearch model_.searchTypeDropdownValue) model_
|
update bookmarkId mId key flags texts settings (DoSearch model_.searchTypeDropdownValue) model_
|
||||||
|
|
||||||
KeyUpPowerSearchbarMsg (Just Enter) ->
|
KeyUpPowerSearchbarMsg (Just Enter) ->
|
||||||
update mId key flags texts settings (DoSearch model.searchTypeDropdownValue) model
|
update bookmarkId mId key flags texts settings (DoSearch model.searchTypeDropdownValue) model
|
||||||
|
|
||||||
KeyUpPowerSearchbarMsg _ ->
|
KeyUpPowerSearchbarMsg _ ->
|
||||||
withSub ( model, Cmd.none )
|
withSub ( model, Cmd.none )
|
||||||
|
|
||||||
RemoveItem id ->
|
RemoveItem id ->
|
||||||
update mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.RemoveItem id)) model
|
update bookmarkId mId key flags texts settings (ItemCardListMsg (Comp.ItemCardList.RemoveItem id)) model
|
||||||
|
|
||||||
TogglePublishCurrentQueryView ->
|
TogglePublishCurrentQueryView ->
|
||||||
case createQuery model of
|
case createQuery model of
|
||||||
@ -1146,18 +1147,14 @@ doSearch param model =
|
|||||||
|
|
||||||
searchCmd =
|
searchCmd =
|
||||||
doSearchCmd param_ model
|
doSearchCmd param_ model
|
||||||
|
|
||||||
( newThrottle, cmd ) =
|
|
||||||
Throttle.try searchCmd model.throttle
|
|
||||||
in
|
in
|
||||||
withSub
|
withSub
|
||||||
( { model
|
( { model
|
||||||
| searchInProgress = cmd /= Cmd.none
|
| searchInProgress = True
|
||||||
, searchOffset = 0
|
, searchOffset = 0
|
||||||
, throttle = newThrottle
|
|
||||||
, lastSearchType = param.searchType
|
, lastSearchType = param.searchType
|
||||||
}
|
}
|
||||||
, cmd
|
, searchCmd
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -1190,9 +1187,7 @@ withSub ( m, c ) =
|
|||||||
makeResult
|
makeResult
|
||||||
( m
|
( m
|
||||||
, c
|
, c
|
||||||
, Throttle.ifNeeded
|
, Sub.none
|
||||||
(Time.every 500 (\_ -> UpdateThrottle))
|
|
||||||
m.throttle
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Page.Home.View2 exposing (viewContent, viewSidebar)
|
module Page.Search.View2 exposing (viewContent, viewSidebar)
|
||||||
|
|
||||||
import Api
|
import Api
|
||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
@ -27,10 +27,10 @@ import Data.UiSettings exposing (UiSettings)
|
|||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick, onInput)
|
import Html.Events exposing (onClick, onInput)
|
||||||
import Messages.Page.Home exposing (Texts)
|
import Messages.Page.Search exposing (Texts)
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Page.Home.Data exposing (..)
|
import Page.Search.Data exposing (..)
|
||||||
import Page.Home.SideMenu
|
import Page.Search.SideMenu
|
||||||
import Set
|
import Set
|
||||||
import Styles as S
|
import Styles as S
|
||||||
import Util.Html
|
import Util.Html
|
||||||
@ -44,7 +44,7 @@ viewSidebar texts visible flags settings model =
|
|||||||
, class S.sidebarBg
|
, class S.sidebarBg
|
||||||
, classList [ ( "hidden", not visible ) ]
|
, classList [ ( "hidden", not visible ) ]
|
||||||
]
|
]
|
||||||
[ Page.Home.SideMenu.view texts.sideMenu flags settings model
|
[ Page.Search.SideMenu.view texts.sideMenu flags settings model
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -563,7 +563,7 @@ editMenuBar texts model svm =
|
|||||||
searchStats : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
searchStats : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
||||||
searchStats texts _ settings model =
|
searchStats texts _ settings model =
|
||||||
if settings.searchStatsVisible then
|
if settings.searchStatsVisible then
|
||||||
[ Comp.SearchStatsView.view2 texts.searchStatsView "my-2" model.searchStats
|
[ Comp.SearchStatsView.view texts.searchStatsView "my-2" model.searchStats
|
||||||
]
|
]
|
||||||
|
|
||||||
else
|
else
|
@ -19,7 +19,7 @@ import Comp.SharePasswordForm
|
|||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.ItemArrange exposing (ItemArrange)
|
import Data.ItemArrange exposing (ItemArrange)
|
||||||
import Http
|
import Http
|
||||||
import Page.Home.Data exposing (Msg(..))
|
import Page.Search.Data exposing (Msg(..))
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
import Util.Html exposing (KeyCode)
|
import Util.Html exposing (KeyCode)
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ itemData texts flags model shareId itemId =
|
|||||||
]
|
]
|
||||||
, div [ class boxStyle ]
|
, div [ class boxStyle ]
|
||||||
[ div [ class headerStyle ]
|
[ div [ class headerStyle ]
|
||||||
[ Icons.tagsIcon2 "mr-2 ml-2"
|
[ Icons.tagsIcon "mr-2 ml-2"
|
||||||
, text texts.tagsAndFields
|
, text texts.tagsAndFields
|
||||||
]
|
]
|
||||||
, div [ class "flex flex-row items-center flex-wrap font-medium my-1" ]
|
, div [ class "flex flex-row items-center flex-wrap font-medium my-1" ]
|
||||||
|
@ -9,106 +9,27 @@ module Page.Upload.Data exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg(..)
|
, Msg(..)
|
||||||
, emptyModel
|
, emptyModel
|
||||||
, hasErrors
|
, reset
|
||||||
, isCompleted
|
|
||||||
, isDone
|
|
||||||
, isError
|
|
||||||
, isIdle
|
|
||||||
, isLoading
|
|
||||||
, isSuccessAll
|
|
||||||
, uploadAllTracker
|
|
||||||
)
|
)
|
||||||
|
|
||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Comp.UploadForm
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ incoming : Bool
|
{ uploadForm : Comp.UploadForm.Model
|
||||||
, 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emptyModel : Model
|
emptyModel : Model
|
||||||
emptyModel =
|
emptyModel =
|
||||||
{ incoming = True
|
{ uploadForm = Comp.UploadForm.init
|
||||||
, 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= SubmitUpload
|
= UploadMsg Comp.UploadForm.Msg
|
||||||
| SingleUploadResp String (Result Http.Error BasicResult)
|
|
||||||
| GotProgress String Http.Progress
|
|
||||||
| ToggleIncoming
|
|
||||||
| ToggleSingleItem
|
|
||||||
| Clear
|
|
||||||
| DropzoneMsg Comp.Dropzone.Msg
|
|
||||||
| ToggleSkipDuplicates
|
|
||||||
| LanguageMsg (Comp.FixedDropdown.Msg Language)
|
|
||||||
|
|
||||||
|
|
||||||
isLoading : Model -> File -> Bool
|
reset : Msg
|
||||||
isLoading model file =
|
reset =
|
||||||
Dict.member (makeFileId file) model.loading
|
UploadMsg Comp.UploadForm.reset
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user