From c6e4cccfa51f7c9fdebad97cb8e466c029cbd8d5 Mon Sep 17 00:00:00 2001 From: Vladimir Krutkin Date: Fri, 14 Jun 2024 11:52:12 +0300 Subject: [PATCH] Git dashboard HTML / CSS refactoring * Inline SVG icons * Page layout refactoring * Dark theme works * Minor improvements --- .../HBS2/Git/Web/Assets.hs | 167 +++++++- .../assets/css/custom.css | 365 ++++------------- .../assets/icon/blob-filled.svg | 8 - .../assets/icon/blob.svg | 16 - .../assets/icon/gear.svg | 8 - .../assets/icon/git-branch.svg | 9 - .../assets/icon/git-commit.svg | 6 - .../assets/icon/git-fork.svg | 8 - .../assets/icon/git-tag.svg | 5 - .../assets/icon/haskell.svg | 3 - .../assets/icon/javascript.svg | 8 - .../assets/icon/license.svg | 6 - .../assets/icon/lock-closed.svg | 7 - .../assets/icon/logo-small.svg | 108 ----- .../assets/icon/logo_black.svg | 66 ---- .../assets/icon/markdown.svg | 7 - .../assets/icon/nixos.svg | 8 - .../assets/icon/pinned-light.svg | 6 - .../assets/icon/python.svg | 4 - .../assets/icon/refresh.svg | 13 - .../assets/icon/sql.svg | 10 - .../assets/icon/terminal.svg | 9 - .../assets/icon/tree-up.svg | 15 - .../assets/icon/tree.svg | 5 - .../assets/icon/xclip.svg | 6 - .../assets/icon/xclipdone.svg | 6 - .../assets/icon/yaml.svg | 7 - .../src/HBS2/Git/Web/Html/Root.hs | 372 +++++++++--------- hbs2-git/hbs2-git.cabal | 2 +- 29 files changed, 440 insertions(+), 820 deletions(-) delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob-filled.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/gear.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-branch.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-commit.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-fork.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-tag.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/haskell.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/javascript.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/license.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/lock-closed.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo-small.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo_black.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/markdown.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/nixos.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/pinned-light.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/python.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/refresh.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/sql.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/terminal.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree-up.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclip.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclipdone.svg delete mode 100644 hbs2-git/hbs2-git-dashboard-assets/assets/icon/yaml.svg diff --git a/hbs2-git/hbs2-git-dashboard-assets/HBS2/Git/Web/Assets.hs b/hbs2-git/hbs2-git-dashboard-assets/HBS2/Git/Web/Assets.hs index 993f30f2..d1b51804 100644 --- a/hbs2-git/hbs2-git-dashboard-assets/HBS2/Git/Web/Assets.hs +++ b/hbs2-git/hbs2-git-dashboard-assets/HBS2/Git/Web/Assets.hs @@ -2,8 +2,10 @@ module HBS2.Git.Web.Assets where import Data.FileEmbed - import Data.ByteString +import Data.Text (Text) +import Text.InterpolatedString.Perl6 (qc) +import Lucid.Base version :: Int version = 3 @@ -11,4 +13,167 @@ version = 3 assetsDir :: [(FilePath, ByteString)] assetsDir = $(embedDir "hbs2-git-dashboard-assets/assets") +data IconType + = IconCopy + | IconCopyDone + | IconLockClosed + | IconGitCommit + | IconGitFork + | IconGitBranch + | IconTag + | IconFolderFilled + | IconHaskell + | IconMarkdown + | IconNix + | IconBash + | IconPython + | IconJavaScript + | IconSql + | IconSettingsFilled + | IconFileFilled + | IconRefresh + | IconArrowUturnLeft + | IconLicense + | IconPinned +svgIcon :: Monad m => IconType -> HtmlT m () +svgIcon = toHtmlRaw . svgIconText + +svgIconText :: IconType -> Text + +svgIconText IconCopy = [qc| + + + +|] + +svgIconText IconCopyDone = [qc| + + + + +|] + +svgIconText IconLockClosed = [qc| + + + + +|] + +svgIconText IconGitCommit = [qc| + + + + +|] + +svgIconText IconGitFork = [qc| + + + + + + +|] + +svgIconText IconGitBranch = [qc| + + + + + + + +|] + +svgIconText IconTag = [qc| + + + +|] + +svgIconText IconFolderFilled = [qc| + + +|] + +svgIconText IconHaskell = [qc| + Haskell + + |] + +svgIconText IconMarkdown = [qc| + Markdown + + |] + +svgIconText IconNix = [qc| + Nix + + |] + +svgIconText IconBash = [qc| + + + + +|] + +svgIconText IconPython = [qc| + Python + +|] + +svgIconText IconJavaScript = [qc| + JavaScript + +|] + +svgIconText IconSql = [qc| + + + + + + + + +|] + +svgIconText IconSettingsFilled = [qc| + + +|] + +svgIconText IconFileFilled = [qc| + + + +|] + +svgIconText IconRefresh = [qc| + + + +|] + +svgIconText IconArrowUturnLeft = [qc| + + + +|] + +svgIconText IconLicense = [qc| + + + + +|] + +svgIconText IconPinned = [qc| + + + + +|] diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/css/custom.css b/hbs2-git/hbs2-git-dashboard-assets/assets/css/custom.css index fd827dab..049d23c4 100644 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/css/custom.css +++ b/hbs2-git/hbs2-git-dashboard-assets/assets/css/custom.css @@ -1,337 +1,146 @@ -input, button { - font-size: var(--form-element-font-size); - height: 2.5rem; - padding: 0.25rem 0.5rem; - border-radius: 0.25rem; - border: 1px solid #ccc; +/* fastpok CSS start */ + +:root { + --pico-form-element-spacing-vertical: .5rem; + --pico-form-element-spacing-horizontal: .625rem; } -input[type="search"] { - font-size: var(--form-element-font-size); - height: 2.5rem; - padding: 0.25rem 0.5rem; - border-radius: 0.25rem; - border: 1px solid #ccc; +[type=search] { + --pico-border-radius: inherit; } -button.search { - background: url('/icon/refresh.svg') no-repeat center center; - background-size: 24px 24px; - min-width: 32px; - height: 2.5rem; +[role=search] { + --pico-border-radius: inherit; } -button.search svg { +[role=search]>:first-child { + border-top-left-radius: var(--pico-border-radius); + border-bottom-left-radius: var(--pico-border-radius); } -body, html { - margin: 0; - height: 100%; - font-size: 18px; +[role=search]>:last-child { + border-top-right-radius: var(--pico-border-radius); + border-bottom-right-radius: var(--pico-border-radius); } +body>footer, body>header, body>main { + padding-block: 0; +} -header { - width: 100%; - - font-size: 20px; +header>nav { + border-bottom: var(--pico-border-width) solid var(--pico-muted-border-color); +} +.wrapper { display: flex; - align-items: center; - - padding: 8px; - - top: 0; - left: 0; - z-index: 100; - box-shadow: 0 2px 5px rgba(0,0,0,0.2); } -/* height: 64px; */ - -header h1 { - font-size: 20px; - margin: 0 0 0 2.21rem; - font-weight: 500; -} - -.header-title { -} - -.container { - width: 100%; -} - -.header-links { +.sidebar { + width: 20rem; + flex-shrink: 0; + padding-top: var(--pico-block-spacing-vertical); + padding-right: var(--pico-block-spacing-horizontal); + padding-bottom: var(--pico-block-spacing-vertical); + border-right: var(--pico-border-width) solid var(--pico-muted-border-color); display: flex; - margin-left: 10em; - gap: 2rem; - background: white; -} - -header a { - /* display: inline; */ - height: 1rem; - text-decoration: none; -} - -.header-actions { - margin-left: auto; -} - -nav.left { - flex: 0 0 20rem; - padding: 4rem 0rem 0 1rem; - font-size: 20px; flex-direction: column; - justify-content: normal; - background: #FAFAFA; } -nav.left .info-block { - margin-bottom: 1.5rem; - padding-left: 0.85rem; - padding-right: 0.85rem; +.content { + padding-top: var(--pico-block-spacing-vertical); + padding-bottom: var(--pico-block-spacing-vertical); + padding-left: var(--pico-block-spacing-horizontal); } -section#repo-data { - margin-top: 1.5rem; +article { + border: var(--pico-border-width) solid var(--pico-card-border-color); + box-shadow: none; } -section#repo-data> h1::after, -section#repo-data> h2::after, -section#repo-data> h3::after, -section#repo-data> h4::after -{ - content: ""; - display: block; - margin: 8px 0; - height: 1px; - background-color: #ccc; -} - -/* height: calc(100vh - 64px); */ - -section { - margin-top: 1rem; -} - - -main { - flex-grow: 1; - padding: 2rem 0 0 4rem; -} - - -.main { - display: flex; - padding: 4px 0 0 0; - margin: 0; - min-height: 100vh; -} - -main h1 { - font-size: 1.5rem; -} - -main h2 { - font-size: 1.45rem; - font-weight: 400; -} - -div .repo-list-item { +.repo-list-item { display: flex; justify-content: space-between; - align-items: flex-start; - - - background: #FAFAFA; - padding: 0.75rem; - margin-top: 1.75rem; - border-radius: 0.25rem; - border: 1px solid #BFC7D9; + gap: var(--pico-block-spacing-horizontal); } -.channel-list-item { - display: block; - - background: #FAFAFA; - padding: 1.45rem; - margin-top: 2rem; - border-radius: 0.25rem; - border: 1px solid #BFC7D9; - -} - -.repo-info, .repo-info-misc { - flex: 1; - padding: 1.25rem; -} - -.repo-info h2 a { - text-decoration: none; - color: inherit; -} - -.repo-info h2 { - font-size: 1.35rem; -} - -.repo-info h2 a:hover { - text-decoration: underline dotted; -} - - -.repo-info-misc { - text-align: right; - font-size: 0.85rem; -} - - -.attr { - display: flex; - flex-direction: row; - gap: 1rem; - margin-bottom: 0.5em; - padding-right: 1rem; - font-size: 0.85rem; -} - -.attrname, { - flex: 1; - margin-right: 0.5rem; -} - -div.attrname a img { - margin-right: 0.15rem; - display: inline; -} - -.attrval { - text-align: right; - flex-basis: 8rem; -} - -.onleft { - text-align: left; -} - -.icon { - flex-basis: 90%; - text-align: right; -} - -.info-block .attrname { - font-size: 0.85rem; - font-weight: bolder; -} - -.info-block .attrval { - font-size: 0.85rem; -} - -.info-block a { - font-size: inherit; - color: inherit; - text-decoration: none; -} - -.info-block a:hover { - text-decoration: underline dotted 2px black; - color: black; -} - - -form.search { +.repo-list-item-link-wrapper { display: flex; align-items: center; - align-items: flex-start; - gap: 0.5em; + margin-bottom: var(--pico-typography-spacing-vertical); } -form.search input[type="search"] { - align: center; - flex-grow: 1; - margin-right: 0.5em; +.copy-button { + margin-left: calc(var(--pico-spacing) * .5); + background-color: transparent; + border: none; + padding: 0; + border-radius: 0; + box-shadow: none; + color: var(--pico-secondary); + transition: color var(--pico-transition); } -form.search button { - align: center; - min-width: 4rem; +.copy-button:hover { + color: var(--pico-secondary-hover); } -.xclip::after { +.copy-button .icon { + width: 1.125rem; + height: 1.125rem; +} + +.inline-icon-wrapper { display: inline-block; - content: url('/icon/xclip.svg'); +} + +.inline-icon-wrapper .icon { + margin-right: calc(var(--pico-spacing) * .25); vertical-align: middle; - width: 24px; - height: 24px; - opacity: 0; - transition: opacity 0.2s; - left: 16px; - position: relative; } -.xclip:hover::after { - left: 16px; - position: relative; - content: url('/icon/xclip.svg'); - vertical-align: middle; - height: 24x; - width: 24x; - opacity: 1; +.info-block { + margin-bottom: var(--pico-block-spacing-vertical); } -.xclip { - /*position: relative;*/ - text-decoration: underline dotted; +.mb-0 { + margin-bottom: 0; } -.xclip:hover { - text-decoration: underline dotted; +.py-0 { + padding-top: 0; + padding-bottom: 0; } -.clicked:hover::after { - content: url('/icon/xclipdone.svg'); - vertical-align: middle; - right: 16px; - height: 24x; - width: 24x; - opacity: 1; +.text-nowrap { + text-wrap: nowrap; } -nav[role="tab-control"] { - min-height: 24px; - font-size: 18px; - /* border: 1px solid black; */ - display: block; - margin-bottom: 4rem; +.repo-menu { + --pico-nav-breadcrumb-divider: '|'; } -nav[role="tab-control"] li { - display: block; - padding: 0 0 0 0; - padding-right: 2rem; - margin-right: 2rem; - border-right: 2px solid gray; - font-weight: bolder; +.repo-menu li.active { + color: var(--pico-primary); } -nav[role="tab-control"] li a { - color: inherit; +aside li { + padding: 0; +} + +aside ul { + padding: 0; +} + +aside li :where(a,[role=link]):not(:hover) { text-decoration: none; } -nav[role="tab-control"] li.active { - display: block; - color: #0089D1; +.sidebar-title { + margin-bottom: calc(var(--pico-typography-spacing-vertical) * .25); } +/* fastpok CSS end */ -nav.secondary[role="tab-control"] li { - border-right: none; - font-weight: normal; -} ul.misc-menu { margin: 0 0 0 0; @@ -423,8 +232,6 @@ pre.numberSource code > span > a:first-child::before color: #aaaaaa; } pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } -div.sourceCode - { background-color: #f8f8f8; } @media screen { pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } } diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob-filled.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob-filled.svg deleted file mode 100644 index ee6095d6..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob-filled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob.svg deleted file mode 100644 index cfbcd398..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/blob.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/gear.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/gear.svg deleted file mode 100644 index 8c2174da..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/gear.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-branch.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-branch.svg deleted file mode 100644 index 8a97e6dc..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-branch.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-commit.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-commit.svg deleted file mode 100644 index 84a368d0..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-commit.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-fork.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-fork.svg deleted file mode 100644 index e08e98ab..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-fork.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-tag.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-tag.svg deleted file mode 100644 index 3d498598..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/git-tag.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/haskell.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/haskell.svg deleted file mode 100644 index c6a33c2f..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/haskell.svg +++ /dev/null @@ -1,3 +0,0 @@ - -Haskell - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/javascript.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/javascript.svg deleted file mode 100644 index 7b4c84f0..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/javascript.svg +++ /dev/null @@ -1,8 +0,0 @@ - -JavaScript - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/license.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/license.svg deleted file mode 100644 index 995ee894..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/license.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/lock-closed.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/lock-closed.svg deleted file mode 100644 index 5d7c4d6f..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/lock-closed.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo-small.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo-small.svg deleted file mode 100644 index d2f555c9..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo-small.svg +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo_black.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo_black.svg deleted file mode 100644 index 8ea5228f..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/logo_black.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/markdown.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/markdown.svg deleted file mode 100644 index fdeedea8..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/markdown.svg +++ /dev/null @@ -1,7 +0,0 @@ - -Markdown - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/nixos.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/nixos.svg deleted file mode 100644 index 2fd29281..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/nixos.svg +++ /dev/null @@ -1,8 +0,0 @@ - - NixOS - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/pinned-light.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/pinned-light.svg deleted file mode 100644 index 59c4e50d..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/pinned-light.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/python.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/python.svg deleted file mode 100644 index 3399c587..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/python.svg +++ /dev/null @@ -1,4 +0,0 @@ - -Python - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/refresh.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/refresh.svg deleted file mode 100644 index f736b8bd..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/refresh.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/sql.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/sql.svg deleted file mode 100644 index 63f4ae77..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/sql.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/terminal.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/terminal.svg deleted file mode 100644 index 85865a80..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/terminal.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree-up.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree-up.svg deleted file mode 100644 index b23bfa0f..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree-up.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree.svg deleted file mode 100644 index 0fb7a185..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/tree.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclip.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclip.svg deleted file mode 100644 index 49a76771..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclip.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclipdone.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclipdone.svg deleted file mode 100644 index 47e26372..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/xclipdone.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/yaml.svg b/hbs2-git/hbs2-git-dashboard-assets/assets/icon/yaml.svg deleted file mode 100644 index 8807a356..00000000 --- a/hbs2-git/hbs2-git-dashboard-assets/assets/icon/yaml.svg +++ /dev/null @@ -1,7 +0,0 @@ - -YAML - diff --git a/hbs2-git/hbs2-git-dashboard/src/HBS2/Git/Web/Html/Root.hs b/hbs2-git/hbs2-git-dashboard/src/HBS2/Git/Web/Html/Root.hs index afd529ff..c0cbe5c0 100644 --- a/hbs2-git/hbs2-git-dashboard/src/HBS2/Git/Web/Html/Root.hs +++ b/hbs2-git/hbs2-git-dashboard/src/HBS2/Git/Web/Html/Root.hs @@ -13,6 +13,7 @@ import HBS2.OrDie import HBS2.Git.Data.Tx.Git import HBS2.Git.Data.RepoHead +import HBS2.Git.Web.Assets -- import Data.Text.Fuzzy.Tokenize as Fuzz @@ -265,10 +266,18 @@ myCss = do hyper_ :: Text -> Attribute hyper_ = makeAttribute "_" +ariaLabel_ :: Text -> Attribute +ariaLabel_ = makeAttribute "aria-label" onClickCopy :: Text -> Attribute onClickCopy s = - hyper_ [qc|on click writeText('{s}') into the navigator's clipboard add .clicked to me wait 2s remove .clicked from me|] + hyper_ [qc|on click writeText('{s}') into the navigator's clipboard +set my innerHTML to '{svgIconText IconCopyDone}' +set @data-tooltip to 'Copied!' +wait 2s +set my innerHTML to '{svgIconText IconCopy}' +set @data-tooltip to 'Copy' +|] markdownToHtml :: Text -> Either PandocError String markdownToHtml markdown = runPure $ do @@ -318,10 +327,10 @@ rootPage content = do myCss body_ do - header_ do - div_ [class_ "header-title"] $ h1_ [] $ do - a_ [href_ (toURL RepoListPage)] "hbs2-peer dashboard" + header_ [class_ "container-fluid"] do + nav_ do + ul_ $ li_ $ a_ [href_ (toURL RepoListPage)] $ strong_ "hbs2-peer dashboard" content @@ -333,80 +342,73 @@ dashboardRootPage = rootPage do now <- liftIO getPOSIXTime <&> fromIntegral . round - div_ [class_ "container main"] $ do - nav_ [class_ "left"] $ do - div_ [class_ "info-block"] "Всякая разная рандомная информация хрен знает, что тут пока выводить" - div_ [class_ "info-block"] "Всякая разная рандомная информация хрен знает, что тут пока выводить" + main_ [class_ "container-fluid"] $ do + div_ [class_ "wrapper"] $ do + aside_ [class_ "sidebar"] $ do + div_ [class_ "info-block"] $ small_ "Всякая разная рандомная информация хрен знает, что тут пока выводить" + div_ [class_ "info-block"] $ small_ "Всякая разная рандомная информация хрен знает, что тут пока выводить" - main_ do + div_ [class_ "content"] do + + section_ do + h2_ "Git repositories" + form_ [role_ "search"] do + input_ [name_ "search", type_ "search"] + input_ [type_ "submit", value_ "Search"] + + section_ do - section_ do - h1_ "Git repositories" - form_ [class_ "search"] do - input_ [type_ "search", id_ "search"] - button_ [class_ "search"] mempty + for_ items $ \it@RepoListItem{..} -> do + let locked = isJust $ coerce @_ @(Maybe HashRef) rlRepoGK0 - section_ [id_ "repo-search-results"] do + let url = toURL (RepoPage (CommitsTab Nothing) (coerce @_ @(LWWRefKey 'HBS2Basic) rlRepoLww)) + -- path ["repo", Text.unpack $ view rlRepoLwwAsText it] + let t = fromIntegral $ coerce @_ @Word64 rlRepoSeq - for_ items $ \it@RepoListItem{..} -> do + let updated = agePure t now - let locked = isJust $ coerce @_ @(Maybe HashRef) rlRepoGK0 + article_ [class_ "repo-list-item"] do + div_ do - let url = toURL (RepoPage (CommitsTab Nothing) (coerce @_ @(LWWRefKey 'HBS2Basic) rlRepoLww)) - -- path ["repo", Text.unpack $ view rlRepoLwwAsText it] - let t = fromIntegral $ coerce @_ @Word64 rlRepoSeq + h5_ do + toHtml rlRepoName - let updated = agePure t now + div_ [class_ "repo-list-item-link-wrapper"] $ do + a_ [href_ url] (toHtml $ view rlRepoLwwAsText it) + button_ [class_ "copy-button", onClickCopy (view rlRepoLwwAsText it), data_ "tooltip" "Copy"] do + svgIcon IconCopy - div_ [class_ "repo-list-item"] do - div_ [class_ "repo-info", style_ "flex: 1; flex-basis: 70%;"] do + toHtml rlRepoBrief - h2_ [class_ "xclip", onClickCopy (view rlRepoLwwAsText it)] do - toHtml rlRepoName - -- when locked $ img_ [src_ "/icon/lock-closed.svg"] + div_ do - p_ $ a_ [href_ url] (toHtml $ view rlRepoLwwAsText it) + div_ [class_ "text-nowrap"] do + small_ $ "Updated " <> toHtml updated - toHtml rlRepoBrief + when locked do + div_ do + small_ do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconLockClosed + "Encrypted" - div_ [ ] do + div_ do + small_ do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconGitCommit + strong_ $ toHtml $ show rlRepoCommits + " commits" - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "" - div_ [ class_ "attrval"] (toHtml updated) - - when locked do - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "encrypted" - div_ [ class_ "attrval"] do - img_ [src_ "/icon/lock-closed.svg"] - - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "commits" - div_ [ class_ "attrval"] $ toHtml (show rlRepoCommits) - - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "forks" - div_ [ class_ "attrval"] $ toHtml (show rlRepoForks) + div_ do + small_ do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconGitFork + strong_ $ toHtml $ show rlRepoForks + " forks" tabClick :: Attribute tabClick = - hyper_ "on click take .active from .tab for event's target" - --- repoMenu :: Monad m => HtmlT m () -> HtmlT m () -repoMenu :: Term [Attribute] (t1 -> t2) => t1 -> t2 -repoMenu = ul_ [] - - -repoMenuItem0 :: Term [Attribute] (t1 -> t2) => [Attribute] -> t1 -> t2 -repoMenuItem0 misc name = li_ ([class_ "tab active"] <> misc <> [tabClick]) name - -repoMenuItem :: Term [Attribute] (t1 -> t2) => [Attribute] -> t1 -> t2 -repoMenuItem misc name = li_ ([class_ "tab"] <> misc <> [tabClick]) name - + hyper_ "on click take .contrast from .tab for event's target" parsedManifest :: (DashBoardPerks m, MonadReader DashBoardEnv m) => RepoListItem -> m ([Syntax C], Text) parsedManifest RepoListItem{..} = do @@ -459,9 +461,9 @@ repoRefs lww = do td_ do if | Text.isPrefixOf "refs/heads" r_ -> do - img_ [src_ "/icon/git-branch.svg"] + svgIcon IconGitBranch | Text.isPrefixOf "refs/tags" r_ -> do - img_ [src_ "/icon/git-tag.svg"] + svgIcon IconTag | otherwise -> mempty td_ (toHtml r_) @@ -564,7 +566,7 @@ repoTree_ embed lww co root = do for_ back' $ \r -> do let rootLink = toURL (RepoTree lww co (coerce @_ @GitHash r)) - td_ $ img_ [src_ "/icon/tree-up.svg"] + td_ $ svgIcon IconArrowUturnLeft td_ ".." td_ do a_ [ href_ "#" , hxGet_ rootLink @@ -578,25 +580,25 @@ repoTree_ embed lww co root = do tr_ mempty do td_ $ case tp of Commit -> mempty - Tree -> img_ [src_ "/icon/tree.svg"] + Tree -> svgIcon IconFolderFilled Blob -> do let syn = Sky.syntaxesByFilename syntaxMap (Text.unpack name) & headMay <&> Text.toLower . Sky.sName let icon = case syn of - Just "haskell" -> [src_ "/icon/haskell.svg"] - Just "markdown" -> [src_ "/icon/markdown.svg"] - Just "nix" -> [src_ "/icon/nixos.svg"] - Just "bash" -> [src_ "/icon/terminal.svg"] - Just "python" -> [src_ "/icon/python.svg"] - Just "javascript" -> [src_ "/icon/javascript.svg"] - Just "sql" -> [src_ "/icon/sql.svg"] + Just "haskell" -> IconHaskell + Just "markdown" -> IconMarkdown + Just "nix" -> IconNix + Just "bash" -> IconBash + Just "python" -> IconPython + Just "javascript" -> IconJavaScript + Just "sql" -> IconSql Just s | s `elem` ["cabal","makefile","toml","ini","yaml"] - -> [src_ "/icon/gear.svg"] - _ -> [src_ "/icon/blob-filled.svg"] + -> IconSettingsFilled + _ -> IconFileFilled - img_ ([alt_ (fromMaybe "blob" syn)] <> icon) + svgIcon icon -- debug $ red "PUSH URL" <+> pretty (path ["back", wtf]) @@ -719,7 +721,7 @@ repoForks lww = do for_ forks $ \it@RepoListItem{..} -> do let lwwTo = coerce @_ @(LWWRefKey 'HBS2Basic) rlRepoLww tr_ [class_ "commit-brief-title"] do - td_ $ img_ [src_ "/icon/git-fork.svg"] + td_ $ svgIcon IconGitFork td_ [class_ "mono"] $ a_ [ href_ (toURL (RepoPage (CommitsTab Nothing) lwwTo)) ] do @@ -754,7 +756,7 @@ repoCommits lww predicate' = do for_ co $ \case CommitListItemBrief{..} -> do tr_ [class_ "commit-brief-title"] do - td_ [class_ "commit-icon"] $ img_ [src_ "/icon/git-commit.svg"] + td_ [class_ "commit-icon"] $ svgIcon IconGitCommit td_ [class_ "commit-hash mono"] do let hash = coerce @_ @GitHash commitListHash @@ -937,137 +939,137 @@ repoPage tab lww params = rootPage do debug $ red "META" <+> pretty meta - div_ [class_ "container main"] $ do - nav_ [class_ "left"] $ do + main_ [class_ "container-fluid"] do + div_ [class_ "wrapper"] do + aside_ [class_ "sidebar"] do - div_ [class_ "info-block" ] do - div_ [ class_ "attr" ] do - a_ [href_ (toURL (RepoPage (CommitsTab Nothing) lww))] $ toHtml (ShortRef lww) + div_ [class_ "info-block" ] do + toHtml (ShortRef lww) - div_ [class_ "info-block" ] do - div_ [ class_ "attr" ] do - img_ [src_ "/icon/tree-up.svg"] - a_ [ href_ "/"] "back to projects" + -- div_ [class_ "info-block" ] do + -- a_ [ href_ "/"] do + -- span_ [class_ "inline-icon-wrapper"] $ svgIcon IconArrowUturnLeft + -- "back to projects" - div_ [class_ "info-block" ] do - for_ author $ \a -> do - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "author:" - div_ [ class_ "attrval"] $ toHtml a + div_ [class_ "info-block" ] do - for_ public $ \p -> do - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] "public:" - div_ [ class_ "attrval"] $ toHtml p + summary_ [class_ "sidebar-title"] $ small_ $ strong_ "About" + ul_ [class_ "mb-0"] do + for_ author $ \a -> do + li_ $ small_ do + "Author: " + toHtml a - div_ [class_ "info-block" ] do + for_ public $ \p -> do + li_ $ small_ do + "Public: " + toHtml p - when (Text.length manifest > 100) do - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] do - a_ [ href_ (toURL (RepoPage ManifestTab lww))] do - img_ [src_ "/icon/license.svg"] + when (Text.length manifest > 100) do + li_ $ small_ do + a_ [class_ "secondary", href_ (toURL (RepoPage ManifestTab lww))] do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconLicense "Manifest" - when (rlRepoForks > 0) do - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] do - a_ [ hxGet_ (toURL (RepoForksHtmx lww)) - , hxTarget_ "#repo-tab-data" - ] do - img_ [src_ "/icon/git-fork.svg"] - "Forks" + when (rlRepoForks > 0) do + li_ $ small_ do + a_ [class_ "secondary" + , href_ "#" + , hxGet_ (toURL (RepoForksHtmx lww)) + , hxTarget_ "#repo-tab-data" + ] do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconGitFork + toHtml $ show rlRepoForks + " forks" - div_ [ class_ "attrval"] $ toHtml (show $ rlRepoForks) + li_ $ small_ do + a_ [class_ "secondary" + , href_ (toURL (RepoPage (CommitsTab Nothing) lww)) + ] do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconGitCommit + toHtml $ show rlRepoCommits + " commits" - div_ [ class_ "attr" ] do - div_ [ class_ "attrname"] do - a_ [ href_ (toURL (RepoPage (CommitsTab Nothing) lww))] do - img_ [src_ "/icon/git-commit.svg"] - "Commits" - - div_ [ class_ "attrval"] $ toHtml (show $ rlRepoCommits) - - for_ pinned $ \(_,ref) -> do - div_ [ class_ "attr" ] do + for_ pinned $ \(_,ref) -> do case ref of - PinnedRefBlob s n hash -> do - div_ [ class_ "attrname"] $ do - a_ [ href_ "#" - , hxGet_ (toURL (RepoSomeBlob lww s hash)) - , hxTarget_ "#repo-tab-data" - ] do - img_ [src_ "/icon/pinned-light.svg"] - toHtml (Text.take 12 n) - - div_ [ class_ "attrval"] $ toHtml $ ShortRef hash - - for_ mbHead $ \rh -> do - - let theHead = headMay [ v | (GitRef "HEAD", v) <- view repoHeadRefs rh ] - - let checkHead v what | v == theHead = strong_ what - | otherwise = what - - div_ [class_ "info-block" ] do - strong_ [] "heads" - for_ (view repoHeadHeads rh) $ \(branch,v) -> do - div_ [ class_ "attrval onleft"] do - a_ [ href_ (toURL (RepoPage (CommitsTab (Just v)) lww )) - ] do checkHead (Just v) - $ toHtml branch - - div_ [class_ "info-block" ] do - strong_ [] "tags" - for_ (view repoHeadTags rh) $ \(tag,v) -> do - div_ [ class_ "attrval onleft"] do - a_ [href_ (toURL (RepoPage (CommitsTab (Just v)) lww ))] - do checkHead (Just v) $ - toHtml tag - - main_ do - - nav_ [ role_ "tab-control" ] do - repoMenu do - - let menu t = if isActiveTab tab t then repoMenuItem0 else repoMenuItem - - menu (CommitsTab Nothing) - [ hxGet_ (toURL (RepoCommits lww)) - , hxTarget_ "#repo-tab-data" - ] "commits" - - - menu (TreeTab Nothing) - [ hxGet_ (toURL (RepoRefs lww)) + PinnedRefBlob s n hash -> small_ do + li_ $ a_ [class_ "secondary" + , href_ "#" + , hxGet_ (toURL (RepoSomeBlob lww s hash)) , hxTarget_ "#repo-tab-data" - ] "tree" + ] do + span_ [class_ "inline-icon-wrapper"] $ svgIcon IconPinned + toHtml (Text.take 12 n) + " " + toHtml $ ShortRef hash - section_ [id_ "repo-data"] do - strong_ (toHtml $ rlRepoName) + for_ mbHead $ \rh -> do - div_ [id_ "repo-tab-data"] do + let theHead = headMay [ v | (GitRef "HEAD", v) <- view repoHeadRefs rh ] - case tab of + let checkHead v what | v == theHead = strong_ what + | otherwise = what - TreeTab{} -> do + div_ [class_ "info-block" ] do + summary_ [class_ "sidebar-title"] $ small_ $ strong_ "Heads" + ul_ [class_ "mb-0"] $ do + for_ (view repoHeadHeads rh) $ \(branch,v) -> do + li_ $ small_ do + a_ [class_ "secondary", href_ (toURL (RepoPage (CommitsTab (Just v)) lww ))] do + checkHead (Just v) $ toHtml branch - let tree = [ fromStringMay @GitHash (Text.unpack v) - | ("tree", v) <- params - ] & catMaybes & headMay + div_ [class_ "info-block" ] do + summary_ [class_ "sidebar-title"] $ small_ $ strong_ "Tags" + ul_ [class_ "mb-0"] $ do + for_ (view repoHeadTags rh) $ \(tag,v) -> do + li_ $ small_ do + a_ [class_ "secondary", href_ (toURL (RepoPage (CommitsTab (Just v)) lww ))] do + checkHead (Just v) $ toHtml tag - maybe (repoRefs lww) (\t -> repoTree lww t t) tree + div_ [class_ "content"] $ do - ManifestTab -> do - thisRepoManifest it + article_ [class_ "py-0"] $ nav_ [ariaLabel_ "breadcrumb", class_ "repo-menu"] $ ul_ do - CommitsTab{} -> do - let predicate = Right (fromQueryParams params) - repoCommits lww predicate + let menuTabClasses isActive = if isActive then "tab contrast" else "tab" + menuTab t misc name = li_ do + a_ ([class_ $ menuTabClasses $ isActiveTab tab t] <> misc <> [tabClick]) do + name - ForksTab -> do - repoForks lww + menuTab (CommitsTab Nothing) + [ href_ "#" + , hxGet_ (toURL (RepoCommits lww)) + , hxTarget_ "#repo-tab-data" + ] "commits" - div_ [id_ "repo-tab-data-embedded"] mempty + menuTab (TreeTab Nothing) + [ href_ "#" + , hxGet_ (toURL (RepoRefs lww)) + , hxTarget_ "#repo-tab-data" + ] "tree" + section_ do + strong_ $ toHtml rlRepoName + div_ [id_ "repo-tab-data"] do + + case tab of + + TreeTab{} -> do + + let tree = [ fromStringMay @GitHash (Text.unpack v) + | ("tree", v) <- params + ] & catMaybes & headMay + + maybe (repoRefs lww) (\t -> repoTree lww t t) tree + + ManifestTab -> do + thisRepoManifest it + + CommitsTab{} -> do + let predicate = Right (fromQueryParams params) + repoCommits lww predicate + + ForksTab -> do + repoForks lww + + div_ [id_ "repo-tab-data-embedded"] mempty diff --git a/hbs2-git/hbs2-git.cabal b/hbs2-git/hbs2-git.cabal index 968667b5..7b052e7a 100644 --- a/hbs2-git/hbs2-git.cabal +++ b/hbs2-git/hbs2-git.cabal @@ -129,7 +129,7 @@ library hbs2-git-dashboard-assets import: shared-properties build-depends: - base, file-embed + base, file-embed, lucid, text exposed-modules: HBS2.Git.Web.Assets