Skip to content
This repository has been archived by the owner on Jun 27, 2020. It is now read-only.

Commit

Permalink
New UI
Browse files Browse the repository at this point in the history
  • Loading branch information
pgaskin committed Jul 24, 2017
1 parent 072520c commit ece000c
Show file tree
Hide file tree
Showing 7 changed files with 1,140 additions and 213 deletions.
141 changes: 72 additions & 69 deletions html.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,92 +6,100 @@ import (
"strings"
)

func pageHTML(title string, content string) string {
func pageHTML(title string, content string, containsview bool, showsearch bool) string {
var html bytes.Buffer
html.WriteString(`<!DOCTYPE html>
<html>
<html lang="en">
<head>
<title>`)
html.WriteString(title)
html.WriteString(`</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,600,700" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<title>`)
html.WriteString(title)
html.WriteString(`</title>
<link rel="stylesheet" href="/static/style.css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/books/">BookBrowser</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/books/">Books</a></li>
<li><a href="/authors/">Authors</a></li>
<li><a href="/series/">Series</a></li>
<li><a href="/static/list.html">List</a></li>
<li><a href="/random/">Random</a></li>
</ul>
<ul class="nav navbar-nav navbar-right" style="padding-right:20px">
<form class="navbar-form" role="search" method="GET" action="/search/">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q" id="q">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form>
</ul>
</div>
</div>
</nav>
<body class="light `)
if containsview {
html.WriteString("contains-view")
} else {
html.WriteString("no-contains-view")
}
html.WriteString(`">
<div class="container">
<div class="page-header">
<h1>`)
<div class="nav">
<div class="left">
<div class="title">
<a href="/books/" class="item">BookBrowser</a>
</div>
</div>
<div class="right">
<a href="/books/" class="item">Books</a>
<a href="/authors/" class="item">Authors</a>
<a href="/series/" class="item">Series</a>
<a href="/static/list.html" class="item">List</a>
<a href="/random/" class="item">Random</a>
<a href="/search/" class="item">Search</a>
</div>
</div>
<div class="section">
<div class="title">`)
html.WriteString(title)
html.WriteString(`</h1>
html.WriteString(`</div>
<div class="body">
<div class="bar">`)
if showsearch {
html.WriteString(`<div class="search">
<form action="/search/" method="GET">
<input class="q" name="q" type="search" placeholder="Search books..." />
<button class="s" type="submit">
<i class="fa fa-search"></i>
</button>
</form>
</div>`)
} else {
html.WriteString(`<div style="flex:1"></div>`)
}
html.WriteString(`<div class="view-buttons">
<a href="javascript:void(0);" class="cards view-button" title="Cards">
<i class="fa fa-th"></i>
</a>
<a href="javascript:void(0);" class="list view-button" title="List">
<i class="fa fa-bars"></i>
</a>
</div>
</div>`)
html.WriteString(content)
html.WriteString(`</div>
<footer class="footer">
<div class="container">
<p class="text-muted"><a href="https://geek1011.github.io/BookBrowser">BookBrowser</a> ` + curversion + `</p>
<p class="text-muted">Copyright 2017 <a href="https://geek1011.github.io">Patrick G</a></p>
</div>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</div>
<div class="footer section">
<div>BookBrowser ` + curversion + `</div>
<div>Copyright 2017 <a href="https://geek1011.github.io">Patrick G</a></div>
</div>
<script src="/static/view.js"></script>
<script>
BookBrowserVersion = "` + curversion + `";
</script>
<script src="/static/picomodal.js"></script>
<script src="/static/updater.js"></script>
</body>
</html>`)
return html.String()
}

func bookHTML(b *Book, isCard bool) string {
func bookHTML(b *Book, isInfo bool) string {
var html bytes.Buffer
if isCard {
html.WriteString(`<div class="book card">`)
} else {
if isInfo {
html.WriteString(`<div class="book info">`)
} else {
html.WriteString(`<div class="book">`)
}

html.WriteString(`<a class="cover" href="/books/` + b.ID + `">`)
if b.HasCover {
if isCard {
if !isInfo {
html.WriteString(`<img alt="cover" src="/covers/` + b.ID + `_thumb.jpg" />`)
} else {
html.WriteString(`<img alt="cover" src="/covers/` + b.ID + `.jpg" />`)
Expand Down Expand Up @@ -119,7 +127,7 @@ func bookHTML(b *Book, isCard bool) string {
html.WriteString(`</span>`)
html.WriteString(`</div>`)
}
if !isCard && b.Description != "" {
if isInfo && b.Description != "" {
html.WriteString(`<div class="description">`)
html.WriteString(b.Description)
html.WriteString(`</div>`)
Expand All @@ -141,30 +149,25 @@ func bookHTML(b *Book, isCard bool) string {
return html.String()
}

func bookListPageHTML(books []Book, title string, notfoundtext string) (html string, notfound bool) {
func bookListPageHTML(books []Book, title string, notfoundtext string, showsearch bool) (html string, notfound bool) {
if len(books) == 0 {
return pageHTML("Not Found", notfoundtext), true
return pageHTML("Not Found", notfoundtext, false, false), true
}

var booksHTML bytes.Buffer
booksHTML.WriteString(`<div class="books cards">`)
booksHTML.WriteString(`<div class="books view cards">`)
for _, b := range books {
booksHTML.WriteString(bookHTML(&b, true))
booksHTML.WriteString(bookHTML(&b, false))
}
booksHTML.WriteString(`</div>`)

return pageHTML(title, booksHTML.String()), false
return pageHTML(title, booksHTML.String(), true, showsearch), false
}

func itemCardHTML(title string, description string, link string) string {
func itemCardHTML(title string, link string) string {
var html bytes.Buffer
html.WriteString(`<a class="item card" href="` + link + `">`)
html.WriteString(`<div class="title">`)
html.WriteString(`<a class="item" href="` + link + `">`)
html.WriteString(title)
html.WriteString(`</div>`)
html.WriteString(`<div class="description">`)
html.WriteString(description)
html.WriteString(`</div>`)
html.WriteString(`</a>`)
return html.String()
}
50 changes: 18 additions & 32 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ html, body {
}

w.WriteHeader(http.StatusNotFound)
io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid))
io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid, false, false))
}

// AuthorsHandler handles the authors page
Expand All @@ -170,13 +170,13 @@ func AuthorsHandler(w http.ResponseWriter, r *http.Request) {
}, func(a nameID, b nameID) bool {
return a.Name < b.Name
})
listHTML.WriteString(`<div style="text-align:center;">`)
listHTML.WriteString(`<div class="items view cards">`)
for _, ni := range authors {
listHTML.WriteString(itemCardHTML(ni.Name, "", "/authors/"+ni.ID))
listHTML.WriteString(itemCardHTML(ni.Name, "/authors/"+ni.ID))
}
listHTML.WriteString(`</div>`)

io.WriteString(w, pageHTML("Authors", listHTML.String()))
io.WriteString(w, pageHTML("Authors", listHTML.String(), true, false))
return
}

Expand All @@ -193,7 +193,7 @@ func AuthorsHandler(w http.ResponseWriter, r *http.Request) {
aname = matched[0].Author
}

html, notfound := bookListPageHTML(matched, aname, "Author not found")
html, notfound := bookListPageHTML(matched, aname, "Author not found", false)

if notfound {
w.WriteHeader(http.StatusNotFound)
Expand All @@ -220,17 +220,17 @@ func SeriesHandler(w http.ResponseWriter, r *http.Request) {
}, func(a nameID, b nameID) bool {
return a.Name < b.Name
})
listHTML.WriteString(`<div style="text-align:center;">`)
listHTML.WriteString(`<div class="items view cards">`)
for _, ni := range series {
listHTML.WriteString(itemCardHTML(ni.Name, "", "/series/"+ni.ID))
listHTML.WriteString(itemCardHTML(ni.Name, "/series/"+ni.ID))
}
listHTML.WriteString(`</div>`)
if len(series) == 0 {
io.WriteString(w, pageHTML("Series", "No series have been found."))
io.WriteString(w, pageHTML("Series", "No series have been found.", false, false))
return
}

io.WriteString(w, pageHTML("Series", listHTML.String()))
io.WriteString(w, pageHTML("Series", listHTML.String(), true, false))
return
}

Expand All @@ -247,7 +247,7 @@ func SeriesHandler(w http.ResponseWriter, r *http.Request) {
sname = matched[0].Series.Name
}

html, notfound := bookListPageHTML(matched, sname, "Series not found")
html, notfound := bookListPageHTML(matched, sname, "Series not found", false)

if notfound {
w.WriteHeader(http.StatusNotFound)
Expand All @@ -269,7 +269,7 @@ func BooksHandler(w http.ResponseWriter, r *http.Request) {
return a.ModTime.Unix() > b.ModTime.Unix()
})

html, notfound := bookListPageHTML(matched, "Books", "There are no books in your library.")
html, notfound := bookListPageHTML(matched, "Books", "There are no books in your library.", true)

if notfound {
w.WriteHeader(http.StatusNotFound)
Expand All @@ -282,13 +282,13 @@ func BooksHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
for _, b := range books {
if b.ID == bid {
io.WriteString(w, pageHTML(b.Title, bookHTML(&b, false)))
io.WriteString(w, pageHTML(b.Title, bookHTML(&b, true), false, false))
return
}
}

w.WriteHeader(http.StatusNotFound)
io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid))
io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid, false, false))
}

// SearchHandler handles the search page
Expand All @@ -299,15 +299,8 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) {
if len(q) != 0 {
w.Header().Set("Content-Type", "text/html")
var booksHTML bytes.Buffer
booksHTML.WriteString(`<form role="search" method="GET" action="/search/">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q" id="q" value="` + strings.Replace(q, `"`, "&quot;", -1) + `">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form><br>`)
booksHTML.WriteString(`<div class="books cards">`)
booksHTML.WriteString(`<script>document.querySelector(".q").value="` + strings.Replace(q, `"`, `\"`, -1) + `";</script>`)
booksHTML.WriteString(`<div class="books view cards">`)
matched := false
for _, b := range books {
matches := false
Expand All @@ -316,25 +309,18 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) {
matches = matches || strings.Contains(strings.ToLower(b.Series.Name), ql)

if matches {
booksHTML.WriteString(bookHTML(&b, true))
booksHTML.WriteString(bookHTML(&b, false))
matched = true
}
}
booksHTML.WriteString(`</div>`)
if !matched {
booksHTML.WriteString("No books matching your query have been found.")
}
io.WriteString(w, pageHTML("Search Results", booksHTML.String()))
io.WriteString(w, pageHTML("Search Results", booksHTML.String(), true, true))
} else {
w.Header().Set("Content-Type", "text/html")
io.WriteString(w, pageHTML("Search", `<form role="search" method="GET" action="/search/">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q" id="q">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form><br><center><a href="/static/list.html">Advanced Search</a></center>`))
io.WriteString(w, pageHTML("Search", `<center><a href="/static/list.html">Advanced Search</a></center>`, false, true))
}
}

Expand Down
Loading

0 comments on commit ece000c

Please sign in to comment.