More styling, test results

main
~erin 2023-07-26 01:13:49 -04:00
parent b6d9d117f6
commit ac4682e20a
Signed by: erin
GPG Key ID: 0FEDEAFF1C14847E
6 changed files with 194 additions and 18 deletions

1
Cargo.lock generated
View File

@ -756,6 +756,7 @@ dependencies = [
"config",
"dirs",
"ramhorns",
"serde",
"tokio",
"tracing",
"tracing-subscriber",

View File

@ -16,3 +16,4 @@ url.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
ramhorns = "0.14.0"
serde = "1.0.175"

View File

@ -1,3 +1,4 @@
use axum::Form;
use axum::{
body::Bytes,
extract::State,
@ -8,6 +9,7 @@ use axum::{
};
use chrono::{DateTime, NaiveDateTime, Utc};
use ramhorns::{Content, Template};
use serde::Deserialize;
use std::fs::File;
use std::io::prelude::*;
use std::net::SocketAddr;
@ -26,6 +28,7 @@ async fn main() {
tracing_subscriber::fmt::init();
let app = Router::new()
.route("/", get(root))
.route("/search", post(search))
.route("/style.css", get(stylesheet));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
@ -62,3 +65,56 @@ async fn root() -> Html<String> {
});
Html(rendered)
}
#[derive(Deserialize)]
struct SearchForm {
query: String,
}
#[derive(Content)]
struct SearchResult {
url: String,
size: i64,
title: String,
summary: String,
last_updated: String,
}
#[derive(Content)]
struct SearchResults {
title: String,
description: String,
query: String,
results: Vec<SearchResult>,
}
async fn search(Form(search): Form<SearchForm>) -> Html<String> {
let mut source = File::open("static/results.html").unwrap();
let mut contents = String::new();
source.read_to_string(&mut contents).unwrap();
let tpl = Template::new(contents).unwrap();
let rendered = tpl.render(&SearchResults {
title: "Ferret".to_string(),
description: "A small independent search engine".to_string(),
query: search.query,
results: vec![
SearchResult {
url: "https://example.com/".to_string(),
size: 0,
title: "Example Domain".to_string(),
summary: "This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.".to_string(),
last_updated: "one week ago".to_string(),
},
SearchResult {
url: "https://example.com/".to_string(),
size: 0,
title: "Example Domain".to_string(),
summary: "This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.".to_string(),
last_updated: "one week ago".to_string(),
}
],
});
Html(rendered)
}

View File

@ -15,10 +15,10 @@
</head>
<body>
<div class="container">
<h1>{{title}}</h1>
<h1 class="home">{{title}}</h1>
<form action="" method="post">
<input type="text" name="search" id="search" required>
<form class="home" action="/search" method="post">
<input class="big-search" type="text" name="query" id="query" required>
<input class="button" type="submit" value="Search!">
</form>

41
static/results.html Normal file
View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/style.css">
<!-- preview metadata -->
<meta property="og:site_name" content="{{title}}"/>
<meta property="og:title" content="{{title}}x"/>
<meta name="description" content="{{description}}"/>
<meta property="og:description" content="{{description}}">
<title>{{title}}</title>
</head>
<body class="results">
<div class="results-container">
<header>
<h1 class="results" >{{title}}</h1>
<form action="/search" method="post" class="results">
<input class="results-search" type="text" name="query" id="query" required value="{{query}}">
<input class="results-button" type="submit" value="Search!">
</form>
</header>
<div class="results">
{{#results}}
<article>
<h2>{{title}}</h2>
<a class="result" href="{{url}}">{{url}}</a>
<p class="result">{{summary}}</a>
</article>
<hr>
{{/results}}
{{^results}}
<p>No results found! :c</p>
{{/results}}
</div>
</div>
</body>
</html>

View File

@ -1,18 +1,78 @@
body{
body {
margin:40px auto;
max-width:650px;
line-height:1.6;
max-width: 650px;
font-size:18px;
color:#444;
color: #444;
padding: 0 10px;
font-family: "Atkinson Hyperlegible";
}
body.results {
margin-top: 0;
max-width: 100%;
margin: 0;
padding: 0;
background-color: #d2d2d2;
}
h1,h2,h3{line-height:1.2}
h1 {
h2 {
font-size: 1em;
margin-bottom: 0;
}
hr {
color: white;
height: 1px;
width: 100%;
}
p.result {
font-size: .9em;
margin-top: .5em;
}
a.result {
font-size: .9em;
color: #ce8500;
font-style: italic;
}
h1.home {
font-size: 3em;
}
div.results {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
margin: auto;
margin-left: 25px;
}
h1.results {
margin-top: 0;
font-size: 1.5em;
padding-left: 20px;
}
header {
width: 100%;
border-radius: 2px;
background-color: white;
padding: 0px;
padding-top: 20px;
padding-bottom: 20px;
}
.results-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
.container {
display: flex;
flex-direction: column;
@ -20,16 +80,7 @@ h1 {
align-items: center;
}
footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 25em;
}
form {
flex-grow: 1;
form.home {
display: flex;
flex-direction: column;
justify-content: center;
@ -38,13 +89,39 @@ form {
gap: .5em;
}
input#search {
form.results {
display: flex;
flex-direction: row;
align-items: center;
gap: .5em;
padding-left: 20px;
}
.big-search {
width: 100%;
font-size: 1.5em;
}
.results-search {
font-size: 1em;
}
.button {
font-size: 1.2em;
border-radius: 2px;
}
.results-button {
font-size: 1em;
border-radius: 2px;
}
footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 25em;
}
footer p {