First version of new ui based on tailwind

This drops fomantic-ui as css toolkit and introduces tailwindcss. With
tailwind there are no predefined components, but it's very easy to
create those. So customizing the look&feel is much simpler, most of
the time no additional css is needed.

This requires a complete rewrite of the markup + styles. Luckily all
logic can be kept as is. The now old ui is not removed, it is still
available by using a request header `Docspell-Ui` with a value of `1`
for the old ui and `2` for the new ui.

Another addition is "dev mode", where docspell serves assets with a
no-cache header, to disable browser caching. This makes developing a
lot easier.
This commit is contained in:
Eike Kettner
2021-01-29 20:48:27 +01:00
parent 442b76c5af
commit dd935454c9
140 changed files with 15077 additions and 214 deletions

View File

@ -4,6 +4,8 @@ module Data.Color exposing
, allString
, fromString
, toString
, toString2
, toStringFg2
)
@ -133,3 +135,114 @@ toString color =
Black ->
"black"
toString2 : Color -> String
toString2 color =
case color of
Red ->
"border "
++ "bg-red-700 border-red-700 text-white "
++ "dark:bg-red-500 dark:bg-opacity-30 dark:text-red-400 dark:border-red-400"
Orange ->
"border "
++ "bg-orange-600 border-orange-600 text-white "
++ "dark:bg-orange-600 dark:bg-opacity-30 dark:text-orange-400 dark:border-orange-400"
Yellow ->
"border "
++ "bg-yellow-500 border-yellow-500 text-white "
++ "dark:bg-yellow-500 dark:bg-opacity-30 dark:text-yellow-500 dark:border-yellow-500"
Olive ->
"border "
++ "bg-lime-600 border-lime-600 text-white "
++ "dark:bg-lime-600 dark:bg-opacity-30 dark:text-lime-400 dark:border-lime-400"
Green ->
"border "
++ "bg-green-400 border-green-400 text-white "
++ "dark:bg-green-600 dark:bg-opacity-30 dark:text-green-400 dark:border-green-400"
Teal ->
"border "
++ "bg-teal-600 border-teal-600 text-white "
++ "dark:bg-teal-600 dark:bg-opacity-30 dark:text-teal-400 dark:border-teal-400"
Blue ->
"border "
++ "bg-blue-600 border-blue-600 text-white "
++ "dark:bg-blue-600 dark:bg-opacity-30 dark:text-blue-400 dark:border-blue-400"
Violet ->
"border "
++ "bg-indigo-600 border-indigo-600 text-white "
++ "dark:bg-indigo-600 dark:bg-opacity-30 dark:text-indigo-400 dark:border-indigo-400"
Purple ->
"border "
++ "bg-purple-600 border-purple-600 text-white "
++ "dark:bg-purple-600 dark:bg-opacity-30 dark:text-purple-400 dark:border-purple-400"
Pink ->
"border "
++ "bg-pink-600 border-pink-600 text-white "
++ "dark:bg-pink-600 dark:bg-opacity-30 dark:text-pink-400 dark:border-pink-400"
Brown ->
"border "
++ "bg-amber-700 border-amber-700 text-white "
++ "dark:bg-amber-900 dark:bg-opacity-30 dark:text-amber-700 dark:border-amber-700"
Grey ->
"border "
++ "bg-gray-500 border-gray-500 text-white "
++ "dark:bg-gray-500 dark:bg-opacity-30 dark:text-gray-400 dark:border-gray-400"
Black ->
"border "
++ "bg-black border-black text-white dark:bg-opacity-90 "
toStringFg2 : Color -> String
toStringFg2 color =
case color of
Red ->
"text-red-700 dark:text-red-400"
Orange ->
"text-orange-600 dark:text-orange-400"
Yellow ->
"text-yellow-500 dark:text-yellow-500"
Olive ->
"text-lime-600 dark:text-lime-400"
Green ->
"text-green-400 dark:text-green-400"
Teal ->
"text-teal-600 dark:text-teal-400"
Blue ->
"text-blue-600 dark:text-blue-400 "
Violet ->
"text-indigo-600 dark:text-indigo-400 "
Purple ->
"text-purple-600 dark:text-purple-400"
Pink ->
"text-pink-600 text:text-pink-400"
Brown ->
"text-amber-700 dark:text-amber-700"
Grey ->
"text-gray-500 dark:text-gray-400"
Black ->
"text-black "

View File

@ -3,8 +3,11 @@ module Data.Direction exposing
, all
, fromString
, icon
, icon2
, iconFromMaybe
, iconFromMaybe2
, iconFromString
, iconFromString2
, labelFromMaybe
, toString
)
@ -55,11 +58,26 @@ icon dir =
"level up alternate icon"
icon2 : Direction -> String
icon2 dir =
case dir of
Incoming ->
"fa fa-level-down-alt"
Outgoing ->
"fa fa-level-up-alt"
unknownIcon : String
unknownIcon =
"question circle outline icon"
unknownIcon2 : String
unknownIcon2 =
"fa fa-question-circle font-thin"
iconFromString : String -> String
iconFromString dir =
fromString dir
@ -67,12 +85,25 @@ iconFromString dir =
|> Maybe.withDefault unknownIcon
iconFromString2 : String -> String
iconFromString2 dir =
fromString dir
|> Maybe.map icon2
|> Maybe.withDefault unknownIcon2
iconFromMaybe : Maybe String -> String
iconFromMaybe ms =
Maybe.map iconFromString ms
|> Maybe.withDefault unknownIcon
iconFromMaybe2 : Maybe String -> String
iconFromMaybe2 ms =
Maybe.map iconFromString2 ms
|> Maybe.withDefault unknownIcon2
labelFromMaybe : Maybe String -> String
labelFromMaybe ms =
Maybe.andThen fromString ms

View File

@ -0,0 +1,105 @@
module Data.DropdownStyle exposing
( DropdownStyle
, mainStyle
, mainStyleWith
, sidebarStyle
)
import Styles as S
type alias DropdownStyle =
{ root : String
, link : String
, menu : String
, item : String
, itemActive : String
, input : String
}
mainStyle : DropdownStyle
mainStyle =
{ root = ""
, link = dropdownLinkStyle ++ mainLink
, menu = dropdownMenuStyle ++ mainMenu
, item = dropdownItemStyle ++ mainItem
, itemActive = "bg-gray-200 dark:bg-bluegray-700"
, input = mainInputStyle
}
mainStyleWith : String -> DropdownStyle
mainStyleWith rootClass =
let
ds =
mainStyle
in
{ ds | root = rootClass }
sidebarStyle : DropdownStyle
sidebarStyle =
{ root = ""
, link = dropdownLinkStyle ++ sidebarLink
, menu = dropdownMenuStyle ++ sidebarMenu
, item = dropdownItemStyle ++ sidebarItem
, itemActive = "bg-gray-300 dark:bg-bluegray-600"
, input = sidebarInputStyle
}
dropdownLinkStyle : String
dropdownLinkStyle =
"py-2 px-4 w-full inline-flex items-center border rounded "
++ S.formFocusRing
mainLink : String
mainLink =
" bg-white border-gray-500 hover:border-gray-500 dark:bg-bluegray-800 dark:border-bluegray-500 dark:hover:border-bluegray-500"
sidebarLink : String
sidebarLink =
" bg-blue-50 border-gray-500 hover:border-gray-500 dark:bg-bluegray-700 dark:border-bluegray-400 dark:hover:border-bluegray-400"
dropdownMenuStyle : String
dropdownMenuStyle =
"absolute left-0 max-h-44 w-full overflow-y-auto z-50 border shadow-lg transition duration-200 "
mainMenu : String
mainMenu =
"bg-white dark:bg-bluegray-800 dark:border-bluegray-700 dark:text-bluegray-300"
sidebarMenu : String
sidebarMenu =
"bg-blue-50 dark:bg-bluegray-700 dark:border-bluegray-600 dark:text-bluegray-200"
dropdownItemStyle : String
dropdownItemStyle =
"transition-colors duration-200 items-center block px-4 py-2 text-normal "
mainItem : String
mainItem =
" hover:bg-gray-200 dark:hover:bg-bluegray-700 dark:hover:text-bluegray-100"
sidebarItem : String
sidebarItem =
" hover:bg-gray-300 dark:hover:bg-bluegray-600 dark:hover:text-bluegray-50"
mainInputStyle : String
mainInputStyle =
"dark:text-bluegray-200 dark:bg-bluegray-800 dark:border-bluegray-500"
sidebarInputStyle : String
sidebarInputStyle =
"bg-blue-50 dark:text-bluegray-200 dark:bg-bluegray-700 dark:border-bluegray-400"

View File

@ -20,6 +20,7 @@ type alias Config =
, maxPageSize : Int
, maxNoteLength : Int
, showClassificationSettings : Bool
, uiVersion : Int
}

View File

@ -1,40 +1,70 @@
module Data.Icons exposing
( addFiles
, addFiles2
, addFilesIcon
, addFilesIcon2
, concerned
, concerned2
, concernedIcon
, concernedIcon2
, correspondent
, correspondent2
, correspondentIcon
, correspondentIcon2
, customField
, customField2
, customFieldIcon
, customFieldIcon2
, customFieldType
, customFieldType2
, customFieldTypeIcon
, customFieldTypeIconString
, customFieldTypeIconString2
, date
, date2
, dateIcon
, dateIcon2
, direction
, direction2
, directionIcon
, directionIcon2
, dueDate
, dueDate2
, dueDateIcon
, dueDateIcon2
, editNotes
, editNotesIcon
, equipment
, equipment2
, equipmentIcon
, equipmentIcon2
, folder
, folder2
, folderIcon
, folderIcon2
, itemDatesIcon
, organization
, organization2
, organizationIcon
, organizationIcon2
, person
, person2
, personIcon
, personIcon2
, search
, searchIcon
, source
, source2
, sourceIcon
, sourceIcon2
, tag
, tag2
, tagIcon
, tagIcon2
, tags
, tags2
, tagsIcon
, tagsIcon2
)
import Data.CustomFieldType exposing (CustomFieldType)
@ -47,11 +77,21 @@ source =
"upload icon"
source2 : String
source2 =
"fa fa-upload"
sourceIcon : String -> Html msg
sourceIcon classes =
i [ class (source ++ " " ++ classes) ] []
sourceIcon2 : String -> Html msg
sourceIcon2 classes =
i [ class (source2 ++ " " ++ classes) ] []
customFieldType : CustomFieldType -> String
customFieldType ftype =
case ftype of
@ -71,12 +111,37 @@ customFieldType ftype =
"money bill icon"
customFieldType2 : CustomFieldType -> String
customFieldType2 ftype =
case ftype of
Data.CustomFieldType.Text ->
"fa fa-stream"
Data.CustomFieldType.Numeric ->
"fa fa-hashtag"
Data.CustomFieldType.Date ->
"fa fa-calendar"
Data.CustomFieldType.Boolean ->
"fa fa-marker"
Data.CustomFieldType.Money ->
"fa fa-money-bill"
customFieldTypeIcon : String -> CustomFieldType -> Html msg
customFieldTypeIcon classes ftype =
i [ class (customFieldType ftype ++ " " ++ classes) ]
[]
customFieldTypeIcon2 : String -> CustomFieldType -> Html msg
customFieldTypeIcon2 classes ftype =
i [ class (customFieldType2 ftype ++ " " ++ classes) ]
[]
customFieldTypeIconString : String -> String -> Html msg
customFieldTypeIconString classes ftype =
Data.CustomFieldType.fromString ftype
@ -84,16 +149,33 @@ customFieldTypeIconString classes ftype =
|> Maybe.withDefault (i [ class "question circle outline icon" ] [])
customFieldTypeIconString2 : String -> String -> Html msg
customFieldTypeIconString2 classes ftype =
Data.CustomFieldType.fromString ftype
|> Maybe.map (customFieldTypeIcon2 classes)
|> Maybe.withDefault (i [ class "question circle outline icon" ] [])
customField : String
customField =
"highlighter icon"
customField2 : String
customField2 =
"fa fa-highlighter"
customFieldIcon : String -> Html msg
customFieldIcon classes =
i [ class (customField ++ " " ++ classes) ] []
customFieldIcon2 : String -> Html msg
customFieldIcon2 classes =
i [ class (customField2 ++ " " ++ classes) ] []
search : String
search =
"search icon"
@ -109,11 +191,21 @@ folder =
"folder outline icon"
folder2 : String
folder2 =
"fa fa-folder font-thin "
folderIcon : String -> Html msg
folderIcon classes =
i [ class (folder ++ " " ++ classes) ] []
folderIcon2 : String -> Html msg
folderIcon2 classes =
i [ class (folder2 ++ " " ++ classes) ] []
concerned : String
concerned =
"crosshairs icon"
@ -124,6 +216,20 @@ concernedIcon =
i [ class concerned ] []
concerned2 : String
concerned2 =
"fa fa-crosshairs"
concernedIcon2 : String -> Html msg
concernedIcon2 classes =
i
[ class concerned2
, class classes
]
[]
correspondent : String
correspondent =
"address card outline icon"
@ -134,6 +240,16 @@ correspondentIcon classes =
i [ class (correspondent ++ " " ++ classes) ] []
correspondent2 : String
correspondent2 =
"fa fa-address-card font-thin"
correspondentIcon2 : String -> Html msg
correspondentIcon2 classes =
i [ class (correspondent2 ++ " " ++ classes) ] []
itemDates : String
itemDates =
"calendar alternate outline icon"
@ -158,6 +274,16 @@ dateIcon classes =
i [ class (date ++ " " ++ classes) ] []
date2 : String
date2 =
"fa fa-calendar font-thin"
dateIcon2 : String -> Html msg
dateIcon2 classes =
i [ class (date2 ++ " " ++ classes) ] []
dueDate : String
dueDate =
"bell icon"
@ -168,6 +294,16 @@ dueDateIcon classes =
i [ class (dueDate ++ " " ++ classes) ] []
dueDate2 : String
dueDate2 =
"fa fa-bell"
dueDateIcon2 : String -> Html msg
dueDateIcon2 classes =
i [ class (dueDate2 ++ " " ++ classes) ] []
editNotes : String
editNotes =
"comment alternate outline icon"
@ -183,21 +319,41 @@ addFiles =
"file plus icon"
addFiles2 : String
addFiles2 =
"fa fa-file-upload"
addFilesIcon : Html msg
addFilesIcon =
i [ class addFiles ] []
addFilesIcon2 : String -> Html msg
addFilesIcon2 classes =
i [ class addFiles2, class classes ] []
tag : String
tag =
"tag icon"
tag2 : String
tag2 =
"fa fa-tag"
tagIcon : String -> Html msg
tagIcon classes =
i [ class (tag ++ " " ++ classes) ] []
tagIcon2 : String -> Html msg
tagIcon2 classes =
i [ class (tag2 ++ " " ++ classes) ] []
tags : String
tags =
"tags icon"
@ -208,6 +364,16 @@ tagsIcon classes =
i [ class (tags ++ " " ++ classes) ] []
tags2 : String
tags2 =
"fa fa-tags"
tagsIcon2 : String -> Html msg
tagsIcon2 classes =
i [ class (tags2 ++ " " ++ classes) ] []
direction : String
direction =
"exchange icon"
@ -218,31 +384,71 @@ directionIcon classes =
i [ class (direction ++ " " ++ classes) ] []
direction2 : String
direction2 =
"fa fa-exchange-alt"
directionIcon2 : String -> Html msg
directionIcon2 classes =
i [ class (direction2 ++ " " ++ classes) ] []
person : String
person =
"user icon"
person2 : String
person2 =
"fa fa-user"
personIcon : String -> Html msg
personIcon classes =
i [ class (person ++ " " ++ classes) ] []
personIcon2 : String -> Html msg
personIcon2 classes =
i [ class (person2 ++ " " ++ classes) ] []
organization : String
organization =
"factory icon"
organization2 : String
organization2 =
"fa fa-industry"
organizationIcon : String -> Html msg
organizationIcon classes =
i [ class (organization ++ " " ++ classes) ] []
organizationIcon2 : String -> Html msg
organizationIcon2 classes =
i [ class (organization2 ++ " " ++ classes) ] []
equipment : String
equipment =
"box icon"
equipment2 : String
equipment2 =
"fa fa-box"
equipmentIcon : String -> Html msg
equipmentIcon classes =
i [ class (equipment ++ " " ++ classes) ] []
equipmentIcon2 : String -> Html msg
equipmentIcon2 classes =
i [ class (equipment2 ++ " " ++ classes) ] []

View File

@ -4,8 +4,11 @@ module Data.UiSettings exposing
, StoredUiSettings
, UiSettings
, cardPreviewSize
, cardPreviewSize2
, catColor
, catColorFg2
, catColorString
, catColorString2
, defaults
, fieldHidden
, fieldVisible
@ -14,7 +17,9 @@ module Data.UiSettings exposing
, posFromString
, posToString
, tagColor
, tagColorFg2
, tagColorString
, tagColorString2
, toStoredUiSettings
)
@ -23,6 +28,7 @@ import Data.BasicSize exposing (BasicSize)
import Data.Color exposing (Color)
import Data.Fields exposing (Field)
import Data.ItemTemplate exposing (ItemTemplate)
import Data.UiTheme exposing (UiTheme)
import Dict exposing (Dict)
import Html exposing (Attribute)
import Html.Attributes as HA
@ -53,6 +59,9 @@ type alias StoredUiSettings =
, cardTitleTemplate : Maybe String
, cardSubtitleTemplate : Maybe String
, searchStatsVisible : Bool
, cardPreviewFullWidth : Bool
, uiTheme : Maybe String
, sideMenuVisible : Bool
}
@ -80,6 +89,9 @@ type alias UiSettings =
, cardTitleTemplate : ItemPattern
, cardSubtitleTemplate : ItemPattern
, searchStatsVisible : Bool
, cardPreviewFullWidth : Bool
, uiTheme : UiTheme
, sideMenuVisible : Bool
}
@ -147,6 +159,9 @@ defaults =
, pattern = "{{dateLong}}"
}
, searchStatsVisible = True
, cardPreviewFullWidth = False
, uiTheme = Data.UiTheme.Light
, sideMenuVisible = True
}
@ -193,6 +208,11 @@ merge given fallback =
Maybe.andThen readPattern given.cardSubtitleTemplate
|> Maybe.withDefault fallback.cardSubtitleTemplate
, searchStatsVisible = given.searchStatsVisible
, cardPreviewFullWidth = given.cardPreviewFullWidth
, uiTheme =
Maybe.andThen Data.UiTheme.fromString given.uiTheme
|> Maybe.withDefault fallback.uiTheme
, sideMenuVisible = given.sideMenuVisible
}
@ -226,6 +246,9 @@ toStoredUiSettings settings =
, cardTitleTemplate = settings.cardTitleTemplate.pattern |> Just
, cardSubtitleTemplate = settings.cardSubtitleTemplate.pattern |> Just
, searchStatsVisible = settings.searchStatsVisible
, cardPreviewFullWidth = settings.cardPreviewFullWidth
, uiTheme = Just (Data.UiTheme.toString settings.uiTheme)
, sideMenuVisible = settings.sideMenuVisible
}
@ -246,6 +269,20 @@ catColorString settings name =
|> Maybe.withDefault ""
catColorString2 : UiSettings -> String -> String
catColorString2 settings name =
catColor settings name
|> Maybe.map Data.Color.toString2
|> Maybe.withDefault ""
catColorFg2 : UiSettings -> String -> String
catColorFg2 settings name =
catColor settings name
|> Maybe.map Data.Color.toStringFg2
|> Maybe.withDefault ""
tagColorString : Tag -> UiSettings -> String
tagColorString tag settings =
tagColor tag settings
@ -253,6 +290,20 @@ tagColorString tag settings =
|> Maybe.withDefault ""
tagColorString2 : Tag -> UiSettings -> String
tagColorString2 tag settings =
tagColor tag settings
|> Maybe.map Data.Color.toString2
|> Maybe.withDefault "border-black dark:border-bluegray-200"
tagColorFg2 : Tag -> UiSettings -> String
tagColorFg2 tag settings =
tagColor tag settings
|> Maybe.map Data.Color.toStringFg2
|> Maybe.withDefault ""
fieldVisible : UiSettings -> Field -> Bool
fieldVisible settings field =
List.member field settings.formFields
@ -269,6 +320,19 @@ cardPreviewSize settings =
|> HA.class
cardPreviewSize2 : UiSettings -> String
cardPreviewSize2 settings =
case settings.cardPreviewSize of
Data.BasicSize.Small ->
"max-h-16"
Data.BasicSize.Medium ->
"max-h-52"
Data.BasicSize.Large ->
"max-h-80"
--- Helpers

View File

@ -0,0 +1,44 @@
module Data.UiTheme exposing
( UiTheme(..)
, cycle
, fromString
, toString
)
type UiTheme
= Light
| Dark
cycle : UiTheme -> UiTheme
cycle current =
case current of
Light ->
Dark
Dark ->
Light
fromString : String -> Maybe UiTheme
fromString str =
case String.toLower str of
"light" ->
Just Light
"dark" ->
Just Dark
_ ->
Nothing
toString : UiTheme -> String
toString theme =
case theme of
Light ->
"Light"
Dark ->
"Dark"