~saiko/modsite

18244534210ceb0b200b3a4a6317999c72693baf — 2xsaiko 6 months ago cd733e9
Properly do inter page links
M Cargo.lock => Cargo.lock +2 -0
@@ 1330,6 1330,7 @@ dependencies = [
 "sqlx",
 "tokio",
 "toml",
 "url",
 "uuid",
 "zip",
]


@@ 2349,6 2350,7 @@ dependencies = [
 "idna",
 "matches",
 "percent-encoding",
 "serde",
]

[[package]]

M site/Cargo.toml => site/Cargo.toml +1 -0
@@ 28,6 28,7 @@ cmdparser = { git = "https://git.dblsaiko.net/cmdparser.git", default-features =
log = "0.4.8"
simplelog = "0.8.0"
itertools = "0.9.0"
url = { version = "*", features = ["serde"] }

[build-dependencies]
cmdparser = { git = "https://git.dblsaiko.net/cmdparser.git", default-features = false }

M site/src/site/main_page.rs => site/src/site/main_page.rs +11 -25
@@ 8,12 8,15 @@ use crate::db::types::Environment;
use crate::site::db_access::{Db, map_db_err};
use crate::site::geninfo::GenInfo;

pub async fn main_page(req: HttpRequest, page_state: web::Query<PageState>, hb: web::Data<Handlebars<'_>>, db: Db) -> Result<impl Responder, actix_web::Error> {
use super::pagestates::{MainPage as PageState, self};
use url::Url;

pub async fn main_page(req: HttpRequest, page_state: web::Query<PageState<'_>>, hb: web::Data<Handlebars<'_>>, db: Db) -> Result<impl Responder, actix_web::Error> {
    let sorting = SortLinks::from(&page_state, &req);

    let body = hb.render("index", &Data {
        current_query: page_state.query.as_deref(),
        mods: ModData::get_all(&db).await.map_err(map_db_err)?,
        mods: ModData::get_all(&db, &req).await.map_err(map_db_err)?,
        geninfo: GenInfo::current(),
        sorting,
    }).unwrap();


@@ 21,27 24,8 @@ pub async fn main_page(req: HttpRequest, page_state: web::Query<PageState>, hb: 
    Ok(HttpResponse::Ok().body(body))
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PageState {
    query: Option<String>,
    sort: Option<SortType>,
    order: Option<SortOrder>,
}

impl PageState {
    fn link(&self, req: &HttpRequest) -> String {
        let mut url = req.url_for_static("main_page").unwrap();
        url.set_query(Some(&serde_urlencoded::to_string(self).unwrap()));
        url.to_string()
    }

    fn sort(&self) -> SortType { self.sort.unwrap_or_default() }

    fn order(&self) -> SortOrder { self.order.unwrap_or_default() }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
enum SortType {
pub enum SortType {
    #[serde(rename = "name")]
    Name,
    #[serde(rename = "created")]


@@ 55,7 39,7 @@ impl Default for SortType {
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
enum SortOrder {
pub enum SortOrder {
    #[serde(rename = "asc")]
    Asc,
    #[serde(rename = "desc")]


@@ 85,6 69,7 @@ struct Data<'a> {

#[derive(Serialize)]
struct ModData {
    link: Url,
    display_name: String,
    from_db: FromDb,
}


@@ 104,7 89,7 @@ struct FromDb {
}

impl ModData {
    async fn get_all(db: &Pool<PgConnection>) -> sqlx::Result<Vec<ModData>> {
    async fn get_all(db: &Pool<PgConnection>, req: &HttpRequest) -> sqlx::Result<Vec<ModData>> {
        let from_db: Vec<FromDb> = sqlx::query_as_unchecked!(FromDb,
                "SELECT b.id, v.id as modid, v.name, v.description, v.homepage, v.issues, v.source, v.license, v.download_link, v.environment \
                 FROM mod_base b \


@@ 114,6 99,7 @@ impl ModData {

        Ok(from_db.into_iter()
            .map(|data| ModData {
                link: pagestates::ModPage::from_id(&data.id).link(req),
                display_name: data.name.clone().unwrap_or_else(|| data.id.clone()),
                from_db: data,
            }).collect())


@@ 129,7 115,7 @@ struct SortLinks {

#[derive(Serialize)]
struct SortLink {
    link: String,
    link: Url,
    prefix: &'static str,
}


M site/src/site/mod.rs => site/src/site/mod.rs +2 -0
@@ 13,6 13,8 @@ mod geninfo;
mod main_page;
mod mod_page;

mod pagestates;

mod db_access;

pub async fn start_site(config: &LaunchConfig, db_pool: Pool<PgConnection>) -> io::Result<()> {

M site/src/site/mod_page.rs => site/src/site/mod_page.rs +19 -18
@@ 1,23 1,26 @@
use actix_web::{HttpRequest, HttpResponse, Responder, web};
use futures_util::TryStreamExt;
use handlebars::Handlebars;
use serde::{Deserialize, Serialize};
use serde::Serialize;
use sqlx::{FromRow, PgConnection, Pool};
use url::Url;

use crate::db::types::Environment;
use crate::site::db_access::{Db, map_db_err};
use crate::site::geninfo::GenInfo;

pub async fn mod_page(_req: HttpRequest, web::Query(PageState { id, v: version }): web::Query<PageState>, hb: web::Data<Handlebars<'_>>, db: Db) -> Result<impl Responder, actix_web::Error> {
use super::pagestates::ModPage as PageState;

pub async fn mod_page(req: HttpRequest, web::Query(PageState { id, v: version }): web::Query<PageState<'_>>, hb: web::Data<Handlebars<'_>>, db: Db) -> Result<impl Responder, actix_web::Error> {
    let from_db = if let Some(version) = version {
        FromDb::load_ver(&id, &version, &db).await.map_err(map_db_err)?
    } else {
        FromDb::load(&id, &db).await.map_err(map_db_err)?
    };
    let all_versions = ModVersion::load_all(&id, &from_db.file_version, &db).await.map_err(map_db_err)?;
    let all_versions = ModVersion::load_all(&id, &from_db.file_version, &db, &req).await.map_err(map_db_err)?;

    let body = hb.render("mod", &Data {
        id,
        id: &id,
        name: from_db.name.clone().unwrap_or_else(|| from_db.modid.clone()),
        from_db,
        mcversions: vec![],


@@ 28,15 31,9 @@ pub async fn mod_page(_req: HttpRequest, web::Query(PageState { id, v: version }
    Ok(HttpResponse::Ok().body(body))
}

#[derive(Deserialize)]
pub struct PageState {
    id: String,
    v: Option<String>,
}

#[derive(Serialize)]
struct Data {
    id: String,
struct Data<'a> {
    id: &'a str,
    name: String,
    from_db: FromDb,
    mcversions: Vec<ByMcVersion>,


@@ 52,6 49,7 @@ struct ByMcVersion {

#[derive(Serialize)]
struct ModVersion {
    link: Url,
    current: bool,
    dl_link: String,
    file_version: String,


@@ 59,7 57,7 @@ struct ModVersion {
}

impl ModVersion {
    async fn load_all(id: &str, current: &str, db: &Pool<PgConnection>) -> sqlx::Result<Vec<ModVersion>> {
    async fn load_all(id: &str, current: &str, db: &Pool<PgConnection>, req: &HttpRequest) -> sqlx::Result<Vec<ModVersion>> {
        let db: Vec<_> = sqlx::query!(
                "SELECT v.download_link, v.file_version FROM mod_version v \
                 JOIN mod_base b ON b.uuid = v.mod_base \


@@ 67,11 65,14 @@ impl ModVersion {
            .fetch(db)
            .try_collect().await?;

        Ok(db.into_iter().map(|db| ModVersion {
            current: db.file_version == current,
            dl_link: db.download_link,
            file_version: db.file_version,
            id: id.to_string(),
        Ok(db.into_iter().map(|db| {
            ModVersion {
                link: PageState { id: id.into(), v: Some((&db.file_version).into()) }.link(req),
                current: db.file_version == current,
                dl_link: db.download_link,
                file_version: db.file_version,
                id: id.to_string(),
            }
        }).collect())
    }
}

A site/src/site/pagestates.rs => site/src/site/pagestates.rs +47 -0
@@ 0,0 1,47 @@
use std::borrow::Cow;

use actix_web::HttpRequest;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::site::main_page::{SortOrder, SortType};

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct MainPage<'a> {
    pub query: Option<Cow<'a, str>>,
    pub sort: Option<SortType>,
    pub order: Option<SortOrder>,
}

impl MainPage<'_> {
    pub fn link(&self, req: &HttpRequest) -> Url {
        let mut url = req.url_for_static("main_page").unwrap();
        url.set_query(Some(&serde_urlencoded::to_string(self).unwrap()));
        url
    }

    pub fn sort(&self) -> SortType { self.sort.unwrap_or_default() }

    pub fn order(&self) -> SortOrder { self.order.unwrap_or_default() }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ModPage<'a> {
    pub id: Cow<'a, str>,
    pub v: Option<Cow<'a, str>>,
}

impl<'a> ModPage<'a> {
    pub fn from_id(id: impl Into<Cow<'a, str>>) -> Self {
        ModPage {
            id: id.into(),
            v: None,
        }
    }

    pub fn link(&self, req: &HttpRequest) -> Url {
        let mut url = req.url_for_static("mod_page").unwrap();
        url.set_query(Some(&serde_urlencoded::to_string(self).unwrap()));
        url
    }
}
\ No newline at end of file

M templates/index.html.hbs => templates/index.html.hbs +1 -1
@@ 27,7 27,7 @@
            </td>
            <td class="mod-body">
              <div>
                <a href="/mod?id={{from_db/id}}" title="{{from_db/id}}">{{display_name}}</a>
                <a href="{{link}}" title="{{from_db/id}}">{{display_name}}</a>
                <!--by {{#each m/authors}}{{this}}{{#if @last}}{{else}}, {{/if}}{{/each}}-->
              </div>
              <div>

M templates/mod.html.hbs => templates/mod.html.hbs +1 -1
@@ 6,7 6,7 @@
    <title>{{name}} {{from_db/file_version}}</title>
  </head>
  <body>
    <h1 class="page-title">Fabric Mod Links</h1>
    <h1 id="page-title">Fabric Mod Links</h1>
    <hr>
    <div>
      <img id="mod-icon" src="/static/icon.png">

M templates/mod_in_vlist.html.hbs => templates/mod_in_vlist.html.hbs +1 -1
@@ 2,7 2,7 @@
  {{#if current}}
    <span class="current" title="current">{{file_version}}</span>
  {{else}}
    <a href="/mod?id={{id}}&v={{file_version}}">{{file_version}}</a>
    <a href="{{link}}">{{file_version}}</a>
  {{/if}}
  [<a href="{{dl_link}}">download</a>]
</li>
\ No newline at end of file