Compare commits
2 Commits
ef057eca66
...
b3f88a49aa
Author | SHA1 | Date |
---|---|---|
Savanni D'Gerinel | b3f88a49aa | |
Savanni D'Gerinel | 3f1316b3dd |
|
@ -9,6 +9,8 @@ use warp::{filters::multipart::FormData, http::Response, multipart::Part};
|
||||||
|
|
||||||
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
|
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
|
||||||
|
|
||||||
|
const CSS: &str = include_str!("../templates/style.css");
|
||||||
|
|
||||||
pub async fn handle_index(
|
pub async fn handle_index(
|
||||||
app: App,
|
app: App,
|
||||||
token: Option<SessionToken>,
|
token: Option<SessionToken>,
|
||||||
|
@ -22,6 +24,13 @@ pub async fn handle_index(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_css() -> Result<Response<String>, Error> {
|
||||||
|
Response::builder()
|
||||||
|
.header("content-type", "text/css")
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.body(CSS.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render_auth_page(message: Option<String>) -> Result<Response<String>, Error> {
|
pub fn render_auth_page(message: Option<String>) -> Result<Response<String>, Error> {
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(StatusCode::OK)
|
.status(StatusCode::OK)
|
||||||
|
|
|
@ -2,6 +2,7 @@ use build_html::{self, Html, HtmlContainer};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Form {
|
pub struct Form {
|
||||||
|
classes: Option<String>,
|
||||||
path: String,
|
path: String,
|
||||||
method: String,
|
method: String,
|
||||||
encoding: Option<String>,
|
encoding: Option<String>,
|
||||||
|
@ -11,6 +12,7 @@ pub struct Form {
|
||||||
impl Form {
|
impl Form {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
classes: None,
|
||||||
path: "/".to_owned(),
|
path: "/".to_owned(),
|
||||||
method: "get".to_owned(),
|
method: "get".to_owned(),
|
||||||
encoding: None,
|
encoding: None,
|
||||||
|
@ -36,16 +38,21 @@ impl Form {
|
||||||
|
|
||||||
impl Html for Form {
|
impl Html for Form {
|
||||||
fn to_html_string(&self) -> String {
|
fn to_html_string(&self) -> String {
|
||||||
|
let classes = match self.classes {
|
||||||
|
Some(ref classes) => format!("class=\"{}\"", classes),
|
||||||
|
None => "".to_owned(),
|
||||||
|
};
|
||||||
let encoding = match self.encoding {
|
let encoding = match self.encoding {
|
||||||
Some(ref encoding) => format!("enctype=\"{encoding}\"", encoding = encoding),
|
Some(ref encoding) => format!("enctype=\"{encoding}\"", encoding = encoding),
|
||||||
None => "".to_owned(),
|
None => "".to_owned(),
|
||||||
};
|
};
|
||||||
format!(
|
format!(
|
||||||
"<form action=\"{path}\" method=\"{method}\" {encoding}>\n{elements}\n</form>\n",
|
"<form action=\"{path}\" method=\"{method}\" {encoding} {classes}>\n{elements}\n</form>\n",
|
||||||
path = self.path,
|
path = self.path,
|
||||||
method = self.method,
|
method = self.method,
|
||||||
encoding = encoding,
|
encoding = encoding,
|
||||||
elements = self.elements.to_html_string()
|
elements = self.elements.to_html_string(),
|
||||||
|
classes = classes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +69,7 @@ pub struct Input {
|
||||||
name: String,
|
name: String,
|
||||||
id: Option<String>,
|
id: Option<String>,
|
||||||
value: Option<String>,
|
value: Option<String>,
|
||||||
content: Option<String>,
|
attributes: Vec<(String, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Html for Input {
|
impl Html for Input {
|
||||||
|
@ -75,14 +82,20 @@ impl Html for Input {
|
||||||
Some(ref value) => format!("value=\"{}\"", value),
|
Some(ref value) => format!("value=\"{}\"", value),
|
||||||
None => "".to_owned(),
|
None => "".to_owned(),
|
||||||
};
|
};
|
||||||
|
let attrs = self
|
||||||
|
.attributes
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| format!("{}=\"{}\"", key, value))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"<input type=\"{ty}\" name=\"{name}\" {id} {value}>{content}</input>\n",
|
"<input type=\"{ty}\" name=\"{name}\" {id} {value} {attrs} />\n",
|
||||||
ty = self.ty,
|
ty = self.ty,
|
||||||
name = self.name,
|
name = self.name,
|
||||||
id = id,
|
id = id,
|
||||||
value = value,
|
value = value,
|
||||||
content = self.content.clone().unwrap_or("".to_owned()),
|
attrs = attrs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +107,7 @@ impl Input {
|
||||||
name: name.to_owned(),
|
name: name.to_owned(),
|
||||||
id: None,
|
id: None,
|
||||||
value: None,
|
value: None,
|
||||||
content: None,
|
attributes: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,12 +121,16 @@ impl Input {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pub fn with_attributes<'a>(
|
||||||
pub fn with_content(mut self, val: &str) -> Self {
|
mut self,
|
||||||
self.content = Some(val.to_owned());
|
values: impl IntoIterator<Item = (&'a str, &'a str)>,
|
||||||
|
) -> Self {
|
||||||
|
self.attributes = values
|
||||||
|
.into_iter()
|
||||||
|
.map(|(a, b)| (a.to_owned(), b.to_owned()))
|
||||||
|
.collect::<Vec<(String, String)>>();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
use handlers::{file, handle_auth, handle_upload, thumbnail};
|
use handlers::{file, handle_auth, handle_css, handle_upload, thumbnail};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
|
@ -119,6 +119,8 @@ pub async fn main() {
|
||||||
.and(maybe_with_session())
|
.and(maybe_with_session())
|
||||||
.then(handle_index);
|
.then(handle_index);
|
||||||
|
|
||||||
|
let styles = warp::path!("css").and(warp::get()).then(handle_css);
|
||||||
|
|
||||||
let auth = warp::path!("auth")
|
let auth = warp::path!("auth")
|
||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
.and(with_app(app.clone()))
|
.and(with_app(app.clone()))
|
||||||
|
@ -145,7 +147,8 @@ pub async fn main() {
|
||||||
.then(move |id, old_etags, app: App| file(app, id, old_etags));
|
.then(move |id, old_etags, app: App| file(app, id, old_etags));
|
||||||
|
|
||||||
let server = warp::serve(
|
let server = warp::serve(
|
||||||
root.or(auth)
|
root.or(styles)
|
||||||
|
.or(auth)
|
||||||
.or(upload_via_form)
|
.or(upload_via_form)
|
||||||
.or(thumbnail)
|
.or(thumbnail)
|
||||||
.or(file)
|
.or(file)
|
||||||
|
|
|
@ -5,14 +5,32 @@ use file_service::{FileHandle, FileId, ReadFileError};
|
||||||
pub fn auth(_message: Option<String>) -> build_html::HtmlPage {
|
pub fn auth(_message: Option<String>) -> build_html::HtmlPage {
|
||||||
build_html::HtmlPage::new()
|
build_html::HtmlPage::new()
|
||||||
.with_title("Authentication")
|
.with_title("Authentication")
|
||||||
|
.with_stylesheet("/css")
|
||||||
|
.with_container(
|
||||||
|
Container::new(ContainerType::Div)
|
||||||
|
.with_attributes([("class", "authentication-page")])
|
||||||
|
.with_container(
|
||||||
|
Container::new(ContainerType::Div)
|
||||||
|
.with_attributes([("class", "authentication-form")])
|
||||||
.with_html(
|
.with_html(
|
||||||
Form::new()
|
Form::new()
|
||||||
.with_path("/auth")
|
.with_path("/auth")
|
||||||
.with_method("post")
|
.with_method("post")
|
||||||
.with_container(
|
.with_container(
|
||||||
Container::new(ContainerType::Div)
|
Container::new(ContainerType::Div)
|
||||||
.with_html(Input::new("token", "token").with_id("for-token-input"))
|
.with_attributes([("class", "authentication-form__label")])
|
||||||
.with_html(Label::new("for-token-input", "Authentication Token")),
|
.with_html(Label::new("for-token-input", "Authentication")),
|
||||||
|
)
|
||||||
|
.with_container(
|
||||||
|
Container::new(ContainerType::Div)
|
||||||
|
.with_attributes([("class", "authentication-form__input")])
|
||||||
|
.with_html(
|
||||||
|
Input::new("token", "token")
|
||||||
|
.with_id("for-token-input")
|
||||||
|
.with_attributes([("size", "50")]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +38,7 @@ pub fn auth(_message: Option<String>) -> build_html::HtmlPage {
|
||||||
pub fn gallery(handles: Vec<Result<FileHandle, ReadFileError>>) -> build_html::HtmlPage {
|
pub fn gallery(handles: Vec<Result<FileHandle, ReadFileError>>) -> build_html::HtmlPage {
|
||||||
let mut page = build_html::HtmlPage::new()
|
let mut page = build_html::HtmlPage::new()
|
||||||
.with_title("Admin list of files")
|
.with_title("Admin list of files")
|
||||||
|
.with_stylesheet("/css")
|
||||||
.with_header(1, "Admin list of files")
|
.with_header(1, "Admin list of files")
|
||||||
.with_html(
|
.with_html(
|
||||||
Form::new()
|
Form::new()
|
||||||
|
|
|
@ -1,5 +1,39 @@
|
||||||
|
:root {
|
||||||
|
--main-bg-color: #e5f0fc;
|
||||||
|
--fg-color: #449dfc;
|
||||||
|
|
||||||
|
--px-4: 4px;
|
||||||
|
--px-8: 8px;
|
||||||
|
--px-12: 12px;
|
||||||
|
|
||||||
|
--hover-low: 4px 4px 4px gray;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Ariel', sans-serif;
|
font-family: 'Ariel', sans-serif;
|
||||||
|
background-color: var(--main-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.authentication-page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.authentication-form {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-shadow: var(--hover-low);
|
||||||
|
padding: var(--px-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.authentication-form__label {
|
||||||
|
margin: var(--px-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.authentication-form__input {
|
||||||
|
margin: var(--px-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.files {
|
.files {
|
||||||
|
@ -33,9 +67,6 @@ img {
|
||||||
.uploadform {
|
.uploadform {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
background-color: #e5f0fc;
|
|
||||||
border: 1px solid #449dfc;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +103,8 @@ img {
|
||||||
outline: -webkit-focus-ring-color auto 5px;
|
outline: -webkit-focus-ring-color auto 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 980px) { /* This is the screen width of a OnePlus 5t */
|
/*
|
||||||
|
@media screen and (max-width: 980px) { /* This is the screen width of a OnePlus 5t
|
||||||
body {
|
body {
|
||||||
font-size: xx-large;
|
font-size: xx-large;
|
||||||
}
|
}
|
||||||
|
@ -101,3 +133,4 @@ img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue