feat: tile mode (#39)

Experimental mode for displaying links as tiles.
For consistency, I made the globe the default icon.
This commit is contained in:
Ivan R. 2024-04-01 22:38:23 +05:00
parent 101202b128
commit 9a9a1af63e
No known key found for this signature in database
GPG key ID: 56C7BAAE859B302C
5 changed files with 130 additions and 30 deletions

View file

@ -9,8 +9,29 @@
margin-top: 3em; margin-top: 3em;
} }
.group { @media screen and (min-width: 600px) {
width: 100%; .page {
padding: 2em 10em
}
.row {
gap: 4em;
}
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
.controls a {
display: flex;
gap: 8px;
align-items: center;
}
.controls a img {
filter: invert(100%);
} }
h2 { h2 {
@ -18,23 +39,6 @@ h2 {
margin-bottom: 6px; margin-bottom: 6px;
} }
div > a { img {
display: flex;
padding-top: 6px;
padding-bottom: 6px;
align-items: center;
gap: 8px;
}
div > a > img {
filter: invert(100%); filter: invert(100%);
} }
@media screen and (min-width: 600px) {
.page {
padding: 2em 10em
}
.group {
max-width: 230px;
}
}

12
assets/css/index-list.css Normal file
View file

@ -0,0 +1,12 @@
.group {
width: 100%;
max-width: max-content;
}
.links > a {
display: flex;
padding-top: 6px;
padding-bottom: 6px;
align-items: center;
gap: 8px;
}

View file

@ -0,0 +1,37 @@
.group {
width: 100%;
max-width: max-content;
}
.links {
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.links > a {
display: flex;
flex-direction: column;
justify-content: center;
width: 130px;
height: 130px;
padding-top: 6px;
padding-bottom: 6px;
align-items: center;
gap: 8px;
border: 2px solid #444;
border-radius: 5px;
text-align: center;
}
.links > a:hover {
border-color: #812abd;
text-decoration: none;
}
.links img {
flex-grow: 1;
width: 30px;
height: 30px;
}

View file

@ -2,32 +2,54 @@
<html lang="en"> <html lang="en">
<head> <head>
{{template "head" .}} {{template "head" .}}
<link rel="stylesheet" href="assets/css/index.css" /> <link rel="stylesheet" href="/assets/css/index-common.css" />
<link rel="stylesheet" href="/assets/css/index-{{ .style }}.css" />
</head> </head>
<body> <body>
<div class="page"> <div class="page">
<h1>{{ .title }}</h1> <h1>{{ .title }}</h1>
{{if not .groups}}
<p> <div class="controls">
You don't have any links. {{if not .groups}}
Go to <a href="/settings" style="text-decoration: underline">settings</a> and create one. <p>
</p> You don't have any links.
{{else}} Go to <a href="/settings" style="text-decoration: underline">settings</a> and create one.
<a href="/settings">Settings</a> </p>
{{end}} {{else}}
<a href="/settings">
<img src="/assets/icons/solid/gear.svg" width="20" height="20" /> Settings
</a>
{{end}}
{{ if ne .style "list" }}
<a href="/?style=list">
<img src="/assets/icons/solid/list.svg" width="20" height="20" /> List
</a>
{{ end }}
{{ if ne .style "tiles" }}
<a href="/?style=tiles">
<img src="/assets/icons/solid/table-cells-large.svg" width="20" height="20" /> Tiles
</a>
{{ end }}
</div>
<div class="row"> <div class="row">
{{range .groups}} {{range .groups}}
<div class="group"> <div class="group">
<h2>{{.Name}}</h2> <h2>{{.Name}}</h2>
<div class="links">
{{range .Links}} {{range .Links}}
<a href="{{.Href}}" target="_blank" rel="noreferrer"> <a href="{{.Href}}" target="_blank" rel="noreferrer">
{{ if .Icon }} {{ if .Icon }}
<img src="/assets/icons/{{.Icon}}.svg" width="20" height="20" /> <img src="/assets/icons/{{.Icon}}.svg" width="20" height="20" />
{{ else }}
<img src="/assets/icons/solid/globe.svg" width="20" height="20" />
{{ end }} {{ end }}
{{.Name}} {{.Name}}
</a> </a>
{{end}} {{end}}
</div>
</div> </div>
{{end}} {{end}}
</div> </div>

View file

@ -2,21 +2,46 @@ package pages
import ( import (
"net/http" "net/http"
"time"
"github.com/ordinary-dev/phoenix/database" "github.com/ordinary-dev/phoenix/database"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func ShowMainPage(w http.ResponseWriter, _ *http.Request) { func ShowMainPage(w http.ResponseWriter, r *http.Request) {
groups, err := database.GetGroupsWithLinks() groups, err := database.GetGroupsWithLinks()
if err != nil { if err != nil {
ShowError(w, http.StatusInternalServerError, err) ShowError(w, http.StatusInternalServerError, err)
return return
} }
// Get desired style.
style := r.FormValue("style")
if style == "tiles" || style == "list" {
// If a valid style is specified in the url -
// save the value in a cookie.
http.SetCookie(w, &http.Cookie{
Name: "phoenix-style",
Value: style,
Expires: time.Now().Add(time.Hour * 24 * 30 * 12 * 10),
})
} else {
// The style is not specified or has an incorrect type, check the cookies.
styleCookie, err := r.Cookie("phoenix-style")
if err == nil {
style = styleCookie.Value
}
}
if style != "tiles" && style != "list" {
style = "list"
}
err = Render("index.html.tmpl", w, map[string]any{ err = Render("index.html.tmpl", w, map[string]any{
"description": "Self-hosted start page.", "description": "Self-hosted start page.",
"groups": groups, "groups": groups,
"style": style,
}) })
if err != nil { if err != nil {
log.Error(err) log.Error(err)