feat: homepage
This commit is contained in:
parent
0586f2e670
commit
428cb600a6
8 changed files with 245 additions and 0 deletions
131
src/pages/chart/home.rs
Normal file
131
src/pages/chart/home.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
use actix_web::http::{self, header::ContentType};
|
||||||
|
use actix_web::{HttpResponse, Responder};
|
||||||
|
use actix_web_codegen_const_routes::{get, post};
|
||||||
|
use log::info;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use tera::Context;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use db_core::prelude::*;
|
||||||
|
|
||||||
|
use crate::errors::ServiceResult;
|
||||||
|
use crate::pages::errors::*;
|
||||||
|
use crate::settings::Settings;
|
||||||
|
use crate::verify::TXTChallenge;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub use crate::pages::*;
|
||||||
|
|
||||||
|
pub const TITLE: &str = "Explore";
|
||||||
|
pub const HOME: TemplateFile = TemplateFile::new("home_page", "pages/chart/index.html");
|
||||||
|
pub const REPO_INFO: TemplateFile =
|
||||||
|
TemplateFile::new("repo_info", "pages/chart/components/repo_info.html");
|
||||||
|
|
||||||
|
pub struct HomePage {
|
||||||
|
ctx: RefCell<Context>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CtxError for HomePage {
|
||||||
|
fn with_error(&self, e: &ReadableError) -> String {
|
||||||
|
self.ctx.borrow_mut().insert(ERROR_KEY, e);
|
||||||
|
self.render()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize)]
|
||||||
|
pub struct HomePagePayload {
|
||||||
|
pub repos: Vec<Repository>,
|
||||||
|
pub next_page: String,
|
||||||
|
pub prev_page: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HomePage {
|
||||||
|
fn new(settings: &Settings, payload: &HomePagePayload) -> Self {
|
||||||
|
let ctx = RefCell::new(ctx(settings));
|
||||||
|
ctx.borrow_mut().insert(TITLE_KEY, TITLE);
|
||||||
|
ctx.borrow_mut().insert(PAYLOAD_KEY, payload);
|
||||||
|
Self { ctx }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self) -> String {
|
||||||
|
TEMPLATES.render(HOME.name, &self.ctx.borrow()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn page(s: &Settings, payload: &HomePagePayload) -> String {
|
||||||
|
let p = Self::new(s, payload);
|
||||||
|
p.render()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
|
cfg.service(home);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Page {
|
||||||
|
pub page: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct OptionalPage {
|
||||||
|
pub page: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OptionalPage> for Page {
|
||||||
|
fn from(o: OptionalPage) -> Self {
|
||||||
|
match o.page {
|
||||||
|
Some(page) => Self { page },
|
||||||
|
None => Page { page: 2 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get(path = "PAGES.home")]
|
||||||
|
pub async fn home(
|
||||||
|
q: web::Query<OptionalPage>,
|
||||||
|
ctx: WebCtx,
|
||||||
|
db: WebDB,
|
||||||
|
) -> PageResult<impl Responder, HomePage> {
|
||||||
|
let q = q.into_inner();
|
||||||
|
async fn _home(ctx: &ArcCtx, db: &BoxDB, p: &Page) -> ServiceResult<Vec<db_core::Repository>> {
|
||||||
|
const LIMIT: u32 = 10;
|
||||||
|
let responses = db.get_all_repositories(p.page, LIMIT).await?;
|
||||||
|
Ok(responses)
|
||||||
|
}
|
||||||
|
let q: Page = q.into();
|
||||||
|
|
||||||
|
let repos = _home(&ctx, &db, &q).await.map_err(|e| {
|
||||||
|
let x = HomePagePayload::default();
|
||||||
|
PageError::new(HomePage::new(&ctx.settings, &x), e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let prev = if q.page == 2 { 1 } else { q.page - 1 };
|
||||||
|
|
||||||
|
let payload = HomePagePayload {
|
||||||
|
repos,
|
||||||
|
next_page: PAGES.home_next(q.page + 1),
|
||||||
|
prev_page: PAGES.home_next(prev),
|
||||||
|
};
|
||||||
|
let page = HomePage::page(&ctx.settings, &payload);
|
||||||
|
|
||||||
|
let html = ContentType::html();
|
||||||
|
Ok(HttpResponse::Ok().content_type(html).body(page))
|
||||||
|
}
|
32
src/pages/chart/mod.rs
Normal file
32
src/pages/chart/mod.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub mod home;
|
||||||
|
pub use home::HOME;
|
||||||
|
pub use home::REPO_INFO;
|
||||||
|
|
||||||
|
pub use super::{ctx, TemplateFile, ERROR_KEY, PAGES, PAYLOAD_KEY, TITLE_KEY};
|
||||||
|
|
||||||
|
pub fn register_templates(t: &mut tera::Tera) {
|
||||||
|
HOME.register(t).expect(HOME.name);
|
||||||
|
REPO_INFO.register(t).expect(REPO_INFO.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
|
||||||
|
home::services(cfg);
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ use crate::static_assets::ASSETS;
|
||||||
use crate::{GIT_COMMIT_HASH, VERSION};
|
use crate::{GIT_COMMIT_HASH, VERSION};
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod chart;
|
||||||
mod errors;
|
mod errors;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
errors::register_templates(&mut tera);
|
errors::register_templates(&mut tera);
|
||||||
auth::register_templates(&mut tera);
|
auth::register_templates(&mut tera);
|
||||||
|
chart::register_templates(&mut tera);
|
||||||
tera.autoescape_on(vec![".html", ".sql"]);
|
tera.autoescape_on(vec![".html", ".sql"]);
|
||||||
//auth::register_templates(&mut tera);
|
//auth::register_templates(&mut tera);
|
||||||
//gists::register_templates(&mut tera);
|
//gists::register_templates(&mut tera);
|
||||||
|
@ -122,6 +124,7 @@ impl<'a> Footer<'a> {
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
auth::services(cfg);
|
auth::services(cfg);
|
||||||
|
chart::services(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -140,6 +143,7 @@ mod tests {
|
||||||
PUB_NAV,
|
PUB_NAV,
|
||||||
auth::AUTH_CHALLENGE,
|
auth::AUTH_CHALLENGE,
|
||||||
auth::AUTH_ADD,
|
auth::AUTH_ADD,
|
||||||
|
chart::HOME,
|
||||||
// auth::AUTH_BASE,
|
// auth::AUTH_BASE,
|
||||||
// auth::login::LOGIN,
|
// auth::login::LOGIN,
|
||||||
// auth::register::REGISTER,
|
// auth::register::REGISTER,
|
||||||
|
|
|
@ -36,6 +36,10 @@ impl Pages {
|
||||||
let auth = Auth::new();
|
let auth = Auth::new();
|
||||||
Pages { home, auth }
|
Pages { home, auth }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn home_next(&self, page: u32) -> String {
|
||||||
|
format!("{}?page={page}", self.home)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|
29
static/cache/css/main.css
vendored
29
static/cache/css/main.css
vendored
|
@ -253,3 +253,32 @@ button {
|
||||||
border-radius: none;
|
border-radius: none;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Inline #1 | http://localhost:7000/ */
|
||||||
|
|
||||||
|
.repository__container {
|
||||||
|
width: 100%;
|
||||||
|
margin: 20px auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
border-bottom: 1px grey dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository__tags {
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository_tags > a {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository__tags > a {
|
||||||
|
background: lightgreen;
|
||||||
|
margin: 15px 2px;
|
||||||
|
padding: 1px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
<div class="nav__spacer"></div>
|
<div class="nav__spacer"></div>
|
||||||
|
|
||||||
<div class="nav__link-group">
|
<div class="nav__link-group">
|
||||||
|
<div class="nav__link-container">
|
||||||
|
<a class="nav__link" rel="noreferrer" href="/federate/">Download Data</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="nav__link-container">
|
<div class="nav__link-container">
|
||||||
<a class="nav__link" rel="noreferrer" href="{{ page.auth.add }}">Spider Forge</a>
|
<a class="nav__link" rel="noreferrer" href="{{ page.auth.add }}">Spider Forge</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
22
templates/pages/chart/components/repo_info.html
Normal file
22
templates/pages/chart/components/repo_info.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{% set name = repository.hostname ~ "/" ~ repository.username ~ "/" ~ repository.name %}
|
||||||
|
<div class="repository__container">
|
||||||
|
|
||||||
|
<h3><a href="/{{ name }}">{{ name }}</a></h3>
|
||||||
|
|
||||||
|
{% if repository.description %}
|
||||||
|
<p>{{ repository.description }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="repository__tags">
|
||||||
|
{% if repository.tags %}
|
||||||
|
{% for tag in repository.tags %}
|
||||||
|
<a class="repository__tag" href="/tag/{{ tag }}" >{{ tag }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="" href="{{ repository.html_url }}" target="_blank">On {{ repository.hostname }}</a>
|
||||||
|
{% if repository.website %}
|
||||||
|
<a href="{{ repository.website }}" target="_blank">Homeage</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
19
templates/pages/chart/index.html
Normal file
19
templates/pages/chart/index.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
{% extends 'base' %}
|
||||||
|
{% block title %} {{ title }} {% endblock %}
|
||||||
|
{% block nav %} {% include "pub_nav" %} {% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<section class="main">
|
||||||
|
{% for repository in payload.repos %}
|
||||||
|
{% include "repo_info" %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="next_page">
|
||||||
|
<a href="{{ payload.prev_page }}">Back</a>
|
||||||
|
<a href="{{ payload.next_page }}">Next</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue