Completely overhaul frontend styling for clearer usage. Add support for entering either the full link or just link key for viewing secrets without opening links anew.

This commit is contained in:
James Eversole 2022-12-26 21:49:21 -06:00
parent 785a797b7c
commit 117d8793dd
10 changed files with 205 additions and 112 deletions

View File

@ -1,3 +1,6 @@
# Changelog for Purr
0.3.0:
- Complete overhaul of frontend styling
- Properly support entering either the full link or link key only in the "get secret" input field
## Unreleased changes

View File

@ -14,7 +14,7 @@ license: ISC
license-file: LICENSE
build-type: Simple
extra-source-files:
README.md
README
ChangeLog.md
library
@ -60,6 +60,7 @@ library
, random >=1.2
, scotty ==0.12
, shakespeare >=2.0.20
, split >=0.2.3.4
, sqlite-simple >=0.4.18.0
, text >=1.2.5.0
, time >=1.9
@ -97,6 +98,7 @@ executable Purr-exe
, random >=1.2
, scotty ==0.12
, shakespeare >=2.0.20
, split >=0.2.3.4
, sqlite-simple >=0.4.18.0
, text >=1.2.5.0
, time >=1.9
@ -135,6 +137,7 @@ test-suite Purr-test
, random >=1.2
, scotty ==0.12
, shakespeare >=2.0.20
, split >=0.2.3.4
, sqlite-simple >=0.4.18.0
, text >=1.2.5.0
, time >=1.9

View File

@ -1,12 +1,12 @@
name: Purr
version: 0.1.0.0
version: 0.3.0
license: ISC
author: "James Eversole"
maintainer: "james@eversole.co"
copyright: "2022 James Eversole"
extra-source-files:
- README.md
- README
- ChangeLog.md
default-extensions:
@ -42,6 +42,7 @@ dependencies:
- scotty == 0.12
- shakespeare >= 2.0.20
- sqlite-simple >= 0.4.18.0
- split >= 0.2.3.4
- time >= 1.9
- text >= 1.2.5.0
- wai-extra >= 3.1.12.1

View File

@ -9,13 +9,15 @@ import Feature.Sharing.SQLite (findByLink, insertNewSecret)
import Feature.Sharing.Templates (renderPw)
import Feature.Sharing.Types
import Control.Monad.Reader (ask, lift, liftIO)
import Data.Maybe (listToMaybe)
import Data.List.Split (splitOn)
import Web.Scotty.Trans
import Prelude
import qualified Data.Text as T
import qualified Data.Text.Lazy as LT
import Control.Monad.Reader (ask, lift, liftIO)
import Data.Maybe (listToMaybe)
import Web.Scotty.Trans
import Prelude
routes :: PurrApp ()
routes = do
@ -28,7 +30,7 @@ routes = do
post "/pw" $ do
reqId <- param "userLink"
res <- findByLink reqId
html $ renderPw reqId res
html $ renderPw (last $ splitOn "/" reqId) res
post "/new" $ do
reqSecret <- param "newSec"

View File

@ -9,6 +9,7 @@ import Control.Monad.Reader (ask, lift, liftIO)
import Crypto.Simple.CBC (encrypt, decrypt)
import Data.Maybe (listToMaybe)
import Data.Time.Clock.POSIX (getPOSIXTime)
import Data.List.Split (splitOn)
import Database.SQLite.Simple
import qualified Data.ByteString.Base64 as B64
@ -22,7 +23,7 @@ findByLink link = do
db <- dbPath
key <- encKey
conn <- liftIO $ open db
res <- liftIO $ query conn "SELECT * from pws WHERE link = ?" (Only link)
res <- liftIO $ query conn "SELECT * from pws WHERE link = ?" (Only (last $ splitOn "/" link))
liftIO $ close conn
readEncryptedSecret key res

View File

@ -38,8 +38,7 @@ packages:
extra-deps:
- crypto-simple-0.1.0.0@sha256:5c0e1e04a814d903743d7543245951a91a46817230fdf478fadca57116805fc1,1502
ghc-options:
'$everything': -haddock
#ghc-options:
# Override default flag values for local packages and extra-deps
# flags: {}

View File

@ -4,18 +4,23 @@
@colorFour: #435F5D
html
font-family: Courier
font-family: Monospace
background-color: #{colorTwo}
color: #{colorOne}
body
margin: 3% 10% 0 10%
font-size: 20px
text-align: left
margin: 1% auto
font-size: 20px
font-weight: 150
text-align: left
header
margin: 0 8% 0 0
text-align: right
a
text-decoration: none
h2
font-family: monaco, Consolas, monospace
text-transform: uppercase
@ -29,14 +34,20 @@ p
a
color: #{colorThree}
.main
margin: 1em auto
max-width: 50%
.title
margin: 0 auto 0 auto
font-size: 2em
color: #{colorThree}
text-align: center
font-size: 2em
margin: 0 auto 0 auto
color: #{colorThree}
.titleLink
all: unset
cursor: pointer
font-size: unset
cursor: pointer
font-weight: 100
.title h1
margin: 0.1em 0 0.1em 0
@ -49,19 +60,22 @@ a
opacity: 1
.generators
margin: 0 0 0.5em 0
padding: 1em 0.5em 0.5em 1.5em
background-color: #{colorTwo}
box-shadow: 8px 8px 12px #ccc
.generators .numberInput
background-color: #{colorTwo}
.generatorRadio
margin: 0
.logo
margin: 4% 3% 0 0
font-size: 1.2vw
color: #{colorFour}
text-align: center
.content
display: flex
.column
flex: 50%
margin: 4% 3% 0 0
font-size: 1.2vw
color: #{colorFour}
text-align: center
.emptyReq
height: 1%
@ -103,7 +117,7 @@ a
transition: all 0.1s ease-in-out
.mainInput:focus
border-bottom: 0.2em solid #{colorThree};
border-bottom: 0.2em solid #{colorThree}
.mainInput:focus::placeholder
color: #{colorThree}
@ -130,7 +144,7 @@ a
transition: all 0.1s ease-in-out
.numberInput:focus
border-bottom: 0.2em solid #{colorThree};
border-bottom: 0.2em solid #{colorThree}
.numberInput:focus::placeholder
color: #{colorThree}
@ -142,33 +156,108 @@ a
.genResult
color: #{colorFour}
.requestedPw
text-align: center
background-color: #333
color: #f0f6f0
margin: 1.5em 0 2em 0
padding: 0.5em 0.5em 0.5em 1.5em
box-shadow: 8px 8px 12px #ccc
.pwResult
margin: 0 0 1em 0
font-size: 1.5em
color: #{colorFour}
color: #f0f6f0
.shareNew
margin-bottom: 2em
padding: 0.5em 0.5em 0.5em 1.5em
background-color: #{colorTwo}
box-shadow: 8px 8px 12px #ccc
margin: 1em 0 2em 0
.shareNew .mainInput
background-color: #{colorTwo}
.shareNew .numberInput
background-color: #{colorTwo}
.requestNew
margin-top: 1em
padding: 0.5em 0.5em 0.5em 1.5em
background-color: #{colorTwo}
box-shadow: 8px 8px 12px #ccc
margin-bottom: 2em
margin-top: 1em
.requestedPw
max-width: 85%
.requestNew .mainInput
background-color: #{colorTwo}
.resLink
font-size: 0.75em
font-size: 0.8em
.validForm
margin: 0.5em 0 0 0
margin: 0
.radioLabel
display: flex
align-items: center
border-radius: 100px
margin: 0.3em 0
padding: 0.3em 0.5em
cursor: pointer
transition: .3s
.radioLabel:hover, .radioLabel:focus-within
background: hsla(0, 0%, 80%, .14)
.radioInput
position: fixed
left: 0
top: 0
width: 1px
height: 1px
opacity: 0
z-index: -1
.radioDesign
width: 22px
height: 22px
border-radius: 100px
background: linear-gradient(to right bottom, #fff, #{colorThree})
position: relative
.radioDesign::before
content: ''
display: inline-block
width: inherit
height: inherit
border-radius: inherit
background: hsl(0, 0%, 90%)
transform: scale(1.1)
transition: .3s
.radioInput:checked+.radioDesign::before
transform: scale(0)
.radioText
margin-left: 14px
letter-spacing: 3px
transition: .3s
.radioInput:checked~.radioText
color: hsl(0, 0%, 40%)
.hidden
display: none
@media only screen and (max-width : 768px)
body
text-align: center
font-size: 16px
.content
display: block
.header
margin: 0 2% 0 0
.main
max-width: 90%
.mainButton
width: 80%
@ -176,9 +265,6 @@ a
.genButton
width: 80%
.generators
text-align: left
.mainInput
width: 95%
max-width: 100%
@ -188,14 +274,17 @@ a
width: 25%
.title
margin: 4% auto 2% auto
font-size: 3em
margin: 4% auto 2% auto
.title h1
font-size: 2.5em
margin-bottom: 0
.requestedPw
max-width: 100%
.pwResult
font-size: 1.75em
.shareUtils
width: 100%

View File

@ -1,28 +1,20 @@
<div #generators .column>
<h2>Generators
<h3>Random, Classic, XKCD
<div #generators .generators>
<form id="genForm">
<div .generators">
<input type="radio" id="gibberish" name="newSec" value="#{show genGibberish}">
<label for="gibberish" .genResult>#{show genGibberish}
<br />
<input type="radio" id="oldschool" name="newSec" value="#{show genOldschool}">
<label for="oldschool" .genResult>#{show genOldschool}
<br />
<input type="radio" id="xkcd" name="newSec" value="#{show genXkcd}">
<label for="xkcd" .genResult>#{show genXkcd}
<button .genButton
hx-get="/gen"
hx-target="#generators"
hx-swap="outerHTML"
/>
Generate New
<br />
<div .generatorRadio">
<label .radioLabel for="gibberish" .genResult>
<input .radioInput type="radio" id="gibberish" name="newSec" value="#{show genGibberish}">
<div .radioDesign>
<div .radioText>#{show genGibberish}
<label .radioLabel for="oldschool" .genResult>
<input .radioInput type="radio" id="oldschool" name="newSec" value="#{show genOldschool}">
<div .radioDesign>
<div .radioText>#{show genOldschool}
<label .radioLabel for="xkcd" .genResult>
<input .radioInput type="radio" id="xkcd" name="newSec" value="#{show genXkcd}">
<div .radioDesign>
<div .radioText>#{show genXkcd}
<div .validForm>
<h3>Share Generated Password
Valid for:
<br />
<input .numberInput
name="newSecDuration"
type="number"
@ -39,12 +31,19 @@
value="20"
onkeyup="if (value < 1 || value > 60) { value = 0 }"
/> views
<button .genButton
<button .mainButton
hx-post="/new"
hx-target="#requestedPw"
hx-swap="outerHTML"
hx-include="[name='newSec']"
/>
Share Password
share selected secret
<img class="htmx-indicator" src="/loading.svg" />
<button .mainButton
hx-get="/gen"
hx-target="#generators"
hx-swap="outerHTML"
/>
regenerate
<br />

View File

@ -11,19 +11,20 @@ $doctype 5
<header>
<a href="https://git.eversole.co/purr">
Made with &#9829;
| <a href="mailto:#{email}">Contact
made with &#9829;
|
<a href="mailto:#{email}">contact
<div #title .title>
<h1>
<a #titleLink .titleLink href="/">purr
<div #main .main>
<div #content .content>
<div #title .title>
<h1>
<a #titleLink .titleLink href="/">purr
<div #shareUtils .column>
<h2>Sharing Tools
<div #shareUtils>
$if (link == "/")
<div #requestedPw .requestedPw>
<div #requestedPw .hidden>
<p .emptyReq>
$else
<div #requestedPw .requestedPw
@ -35,16 +36,31 @@ $doctype 5
>
Loading... <img class="htmx-indicator" src="/loading.svg" />
<div #requestNew .requestNew>
<p>
<input .mainInput
name="userLink"
type="text"
placeholder="enter a link to view secret"
/>
<button .mainButton
hx-post="/pw"
hx-target="#requestedPw"
hx-swap="outerHTML"
hx-include="[name='userLink']"
/>
get secret
<img class="htmx-indicator" src="/loading.svg" />
<div #shareNew .shareNew>
<h3>Share New Secret
<p>
<input .mainInput
name="newSec"
type="text"
placeholder="Enter a Secret to Share"
placeholder="enter a secret to share"
/>
<div .validForm>
Valid for:
valid for:
<br />
<input .numberInput
name="newSecDuration"
@ -68,31 +84,12 @@ $doctype 5
hx-swap="outerHTML"
hx-include="[id='shareNew']"
/>
Share Secret
share secret
<img class="htmx-indicator" src="/loading.svg" />
<div #requestNew .requestNew>
<h3>Lookup
<p>
<input .mainInput
name="userLink"
type="text"
placeholder="Enter a Link to View Secret"
/>
<button .mainButton
hx-post="/pw"
hx-target="#requestedPw"
<div #generators
hx-trigger="load"
hx-get="/gen"
hx-target="#generators"
hx-swap="outerHTML"
hx-include="[name='userLink']"
/>
Get Secret
<img class="htmx-indicator" src="/loading.svg" />
<div #generators .column>
<h2>Generators
<button .mainButton
hx-get="/gen"
hx-target="#generators"
hx-swap="outerHTML"
/>
Load Generators
>

View File

@ -1,7 +1,6 @@
<div #requestedPw .requestedPw>
$maybe pw <- password
<p .resLink>Here's the secret found at <a href="/pw/#{link}">/pw/#{link}</a>:
<p .resLink>secret found at <a href="/pw/#{link}">/pw/#{link}</a>:
<h3 .pwResult>#{pw}
<hr />
$nothing
<h3 .pwResult>No secret found at <a href="/pw/#{link}">/pw/#{link}</a>
<h3 .pwResult>no secret found at <a href="/pw/#{link}">/pw/#{link}</a>