Tabulka na novinky

Tento commit je obsažen v:
sneedmaster 2023-12-18 18:00:25 +01:00
rodič 3e12aeffb9
revize 599c6ed804
13 změnil soubory, kde provedl 113 přidání a 31 odebrání

7
Cargo.lock vygenerováno
Zobrazit soubor

@ -1141,6 +1141,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures-channel"
version = "0.3.28"
@ -1810,6 +1816,7 @@ dependencies = [
"enumflags2",
"env_logger",
"fancy-regex",
"fs_extra",
"glob",
"html-minifier",
"image",

Zobrazit soubor

@ -43,6 +43,7 @@ toml = "0.8.6"
[build-dependencies]
anyhow = "1.0.74"
fs_extra = "1.3.0"
glob = "0.3.1"
html-minifier = "5.0.0"

Zobrazit soubor

@ -1,10 +1,10 @@
use anyhow::Error;
use fs_extra::dir::{copy, remove, CopyOptions};
use glob::glob;
use html_minifier::minify;
use std::{
fs::{read_to_string, File},
io::Write,
process::Command,
};
fn main() -> Result<(), Error> {
@ -12,11 +12,13 @@ fn main() -> Result<(), Error> {
println!("cargo:rerun-if-changed=migrations");
println!("cargo:rerun-if-changed=templates");
Command::new("rm").args(["-rf", "templates_min"]).output()?;
remove("templates_min")?;
Command::new("cp")
.args(["-r", "templates", "templates_min"])
.output()?;
copy(
"templates",
"templates_min",
&CopyOptions::new().copy_inside(true),
)?;
let templates = glob("templates_min/**/*.html")?;

Zobrazit soubor

@ -0,0 +1,7 @@
CREATE TABLE news (
id SERIAL NOT NULL PRIMARY KEY,
title VARCHAR(256) NOT NULL,
content TEXT NOT NULL,
author VARCHAR(32) NOT NULL REFERENCES users(username),
created TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Zobrazit soubor

@ -14,14 +14,12 @@ impl Board {
name: String,
description: String,
) -> Result<Self, NekrochanError> {
let banners = Json(Vec::<File>::new());
let config = Json(ctx.cfg.board_defaults.clone());
let board: Board = query_as("INSERT INTO boards (id, name, description, banners, config) VALUES ($1, $2, $3, $4, $5) RETURNING *")
let board: Board = query_as("INSERT INTO boards (id, name, description, config) VALUES ($1, $2, $3, $4) RETURNING *")
.bind(id)
.bind(name)
.bind(description)
.bind(banners)
.bind(config)
.fetch_one(ctx.db())
.await?;

Zobrazit soubor

@ -5,4 +5,5 @@ mod account;
mod ban;
mod banner;
mod board;
mod newspost;
mod post;

Zobrazit soubor

@ -78,6 +78,21 @@ pub struct Post {
pub created: DateTime<Utc>,
}
#[derive(FromRow, Serialize, Deserialize)]
pub struct Banner {
pub id: i32,
pub banner: Json<File>,
}
#[derive(FromRow)]
pub struct NewsPost {
pub id: i32,
pub title: String,
pub content: String,
pub author: String,
pub created: DateTime<Utc>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct File {
pub original_name: String,
@ -89,9 +104,3 @@ pub struct File {
pub timestamp: i64,
pub size: usize,
}
#[derive(FromRow, Serialize, Deserialize)]
pub struct Banner {
pub id: i32,
pub banner: Json<File>,
}

62
src/db/newspost.rs Normální soubor
Zobrazit soubor

@ -0,0 +1,62 @@
use sqlx::{query, query_as};
use super::models::NewsPost;
use crate::{ctx::Ctx, error::NekrochanError};
impl NewsPost {
pub async fn create(
ctx: &Ctx,
title: String,
content: String,
author: String,
) -> Result<Self, NekrochanError> {
let newspost = query_as("INSERT INTO news (title, content, author) VALUES ($1, $2, $3)")
.bind(title)
.bind(content)
.bind(author)
.fetch_one(ctx.db())
.await?;
Ok(newspost)
}
pub async fn read(ctx: &Ctx, id: i32) -> Result<Option<Self>, NekrochanError> {
let newspost = query_as("SELECT * FROM news WHERE id = $1")
.bind(id)
.fetch_optional(ctx.db())
.await?;
Ok(newspost)
}
pub async fn read_all(ctx: &Ctx) -> Result<Vec<Self>, NekrochanError> {
let newsposts = query_as("SELECT * FROM news").fetch_all(ctx.db()).await?;
Ok(newsposts)
}
pub async fn update(
&self,
ctx: &Ctx,
title: String,
content: String,
) -> Result<(), NekrochanError> {
query("UPDATE news SET title = $1, content = $2 WHERE id = $3")
.bind(title)
.bind(content)
.bind(self.id)
.execute(ctx.db())
.await?;
Ok(())
}
pub async fn delete(&self, ctx: &Ctx) -> Result<(), NekrochanError> {
query("DELETE FROM news WHERE id = $1")
.bind(self.id)
.execute(ctx.db())
.await?;
Ok(())
}
}

Zobrazit soubor

@ -28,7 +28,12 @@ pub async fn index(ctx: Data<Ctx>, req: HttpRequest) -> Result<HttpResponse, Nek
let posts = Post::read_latest(&ctx).await.unwrap_or_else(|_| Vec::new());
let files = Post::read_files(&ctx).await.unwrap_or_else(|_| Vec::new());
let template = IndexTemplate { tcx, boards, posts, files };
let template = IndexTemplate {
tcx,
boards,
posts,
files,
};
template_response(&template)
}

Zobrazit soubor

@ -283,10 +283,6 @@ summary {
margin: 0;
}
.catalog {
text-align: center;
}
.catalog-entry {
display: inline-block;
width: 200px;

Zobrazit soubor

@ -16,7 +16,7 @@
</div>
<hr>
<form method="post">
<div class="catalog">
<div class="center">
{% for thread in threads %}
{% call catalog_entry::catalog_entry(thread, loop.index, board.config.0.page_size.into()) %}
{% endfor %}

Zobrazit soubor

@ -10,9 +10,7 @@
</div>
{% if !boards.is_empty() %}
<div class="infobox">
<div class="infobox-head">
Nástěnky
</div>
<div class="infobox-head">Nástěnky</div>
<div class="infobox-content">
<ul class="infobox-list">
{% for board in boards %}
@ -24,9 +22,7 @@
{% endif %}
{% if !posts.is_empty() %}
<div class="infobox">
<div class="infobox-head">
Nejnovější příspěvky
</div>
<div class="infobox-head">Nejnovější příspěvky</div>
<div class="infobox-content">
<ul class="infobox-list">
{% for post in posts %}
@ -38,9 +34,7 @@
{% endif %}
{% if !files.is_empty() %}
<div class="infobox">
<div class="infobox-head">
Nejnovější soubory
</div>
<div class="infobox-head">Nejnovější soubory</div>
<div class="infobox-content">
<div class="post-files multi-files">
{% for post in files %}

Zobrazit soubor

@ -3,7 +3,7 @@
{% extends "base.html" %}
{% block title %}Katalog nadnístěnky{% endblock %}
{% block title %}Katalog nadnástěnky{% endblock %}
{% block content %}
<div class="container">
@ -16,7 +16,7 @@
</div>
<hr>
<form method="post">
<div class="catalog">
<div class="center">
{% for thread in threads %}
{% call catalog_entry::catalog_entry(thread, loop.index, 15) %}
{% endfor %}