ezidam: added admin/apps listing

This commit is contained in:
Philippe Loctaux 2023-03-30 00:55:45 +02:00
parent e2a7d7625e
commit 574ee62092
7 changed files with 166 additions and 0 deletions

View file

@ -2,3 +2,4 @@
pub const HOME: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-home" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 12l-2 0l9 -9l9 9l-2 0"></path><path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7"></path><path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6"></path></svg>"#;
pub const LOGOUT: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-logout" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M14 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2"></path><path d="M7 12h14l-3 -3m0 6l3 -3"></path></svg>"#;
pub const SETTINGS: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-settings" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"></path><path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0"></path></svg>"#;
pub const APPS: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-apps" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 4m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path><path d="M4 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path><path d="M14 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path><path d="M14 7l6 0"></path><path d="M17 4l0 6"></path>svg>"#;

View file

@ -5,6 +5,7 @@ use rocket::uri;
pub enum AdminMenu {
Exit,
Dashboard,
Apps,
Settings,
}
@ -13,6 +14,7 @@ impl AdminMenu {
match self {
AdminMenu::Exit => "exit",
AdminMenu::Dashboard => "dashboard",
AdminMenu::Apps => "apps",
AdminMenu::Settings => "settings",
}
}
@ -32,6 +34,13 @@ impl AdminMenu {
icon: icons::HOME,
sub: None,
},
MainItem {
id: AdminMenu::Apps.id(),
label: "Applications",
link: uri!(routes::admin::apps::admin_apps).to_string(),
icon: icons::APPS,
sub: None,
},
MainItem {
id: AdminMenu::Settings.id(),
label: "Server settings",

View file

@ -17,6 +17,7 @@ pub enum Page {
AdminDashboard(AdminDashboard),
AdminSettingsBranding(AdminSettingsBranding),
AdminSettingsSecurity(AdminSettingsSecurity),
AdminApps(AdminApps),
}
impl Page {
@ -31,6 +32,7 @@ impl Page {
Page::AdminDashboard(_) => "pages/admin/dashboard",
Page::AdminSettingsBranding(_) => "pages/admin/settings/branding",
Page::AdminSettingsSecurity(_) => "pages/admin/settings/security",
Page::AdminApps(_) => "pages/admin/apps/list",
}
}
@ -45,6 +47,7 @@ impl Page {
Page::AdminDashboard(_) => "Admin dashboard",
Page::AdminSettingsBranding(_) => "Server branding",
Page::AdminSettingsSecurity(_) => "Server security",
Page::AdminApps(_) => "Applications",
}
}
@ -61,6 +64,7 @@ impl Page {
Page::AdminDashboard(_) => Some(AdminMenu::Dashboard.into()),
Page::AdminSettingsBranding(_) => Some(AdminMenu::Settings.into()),
Page::AdminSettingsSecurity(_) => Some(AdminMenu::Settings.into()),
Page::AdminApps(_) => Some(AdminMenu::Apps.into()),
}
}
@ -75,6 +79,7 @@ impl Page {
Page::AdminDashboard(dashboard) => Box::new(dashboard),
Page::AdminSettingsBranding(branding) => Box::new(branding),
Page::AdminSettingsSecurity(security) => Box::new(security),
Page::AdminApps(apps) => Box::new(apps),
}
}
}

View file

@ -1,7 +1,9 @@
use self::apps::*;
use self::settings::*;
use dashboard::*;
use rocket::{routes, Route};
pub mod apps;
pub mod dashboard;
pub mod settings;
@ -12,10 +14,12 @@ pub fn routes() -> Vec<Route> {
settings_update_branding,
settings_security,
settings_security_form,
admin_apps,
]
}
pub mod content {
use apps::App;
use jwt::JwtClaims;
use rocket::serde::Serialize;
@ -40,4 +44,12 @@ pub mod content {
pub struct AdminSettingsSecurity {
pub user: JwtClaims,
}
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
#[derive(Clone)]
pub struct AdminApps {
pub user: JwtClaims,
pub apps: Vec<App>,
}
}

View file

@ -0,0 +1,13 @@
use crate::routes::prelude::*;
use apps::App;
use rocket::get;
#[get("/admin/apps")]
pub async fn admin_apps(mut db: Connection<Database>, admin: JwtAdmin) -> Result<Page> {
let list = App::get_all(&mut *db, None).await?;
Ok(Page::AdminApps(super::content::AdminApps {
user: admin.0,
apps: list,
}))
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,124 @@
{% extends "shell" %}
{% block content %}
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row align-items-center">
<div class="col">
<div class="page-pretitle">
Admin dashboard
</div>
<h2 class="page-title">
Applications
</h2>
</div>
<div class="col-auto ms-auto">
<div class="btn-list">
{% set primary_action = "New application" %}
<a href="#" class="btn btn-primary d-none d-sm-inline-block" data-bs-toggle="modal"
data-bs-target="#modal-report">
<!-- Download SVG icon from http://tabler-icons.io/i/plus -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24"
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 5l0 14"/>
<path d="M5 12l14 0"/>
</svg>
{{ primary_action }}
</a>
<a href="#" class="btn btn-primary d-sm-none btn-icon" data-bs-toggle="modal"
data-bs-target="#modal-report" aria-label="{{ primary_action }}">
<!-- Download SVG icon from http://tabler-icons.io/i/plus -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24"
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 5l0 14"/>
<path d="M5 12l14 0"/>
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Page body -->
<div class="page-body">
<div class="container-xl">
<div class="card">
<div id="table-default" class="table-responsive">
<table class="table table-hover">
<!-- Table header -->
<thead>
<tr>
<th>
<button class="table-sort" data-sort="sort-name">Name</button>
</th>
<th>
<button class="table-sort" data-sort="sort-status">Status</button>
</th>
<th>
<button class="table-sort" data-sort="sort-creation-date">Creation Date</button>
</th>
<th>
<button class="table-sort" data-sort="sort-id">ID</button>
</th>
<th>
<button class="table-sort" data-sort="sort-redirect-uri">Redirect URI</button>
</th>
<th class="w-1">
Actions
</th>
</tr>
</thead>
<tbody class="table-tbody">
<!-- Table content -->
{% for app in apps %}
<tr>
<td class="sort-name">{{ app.label }}</td>
<td class="sort-status">
{% if app.is_archived == true %}
<span class="badge bg-danger me-1"></span> Archived
{% else %}
<span class="badge bg-success me-1"></span> Active
{% endif %}
</td>
<td class="sort-creation-date" data-date="{{ app.created_at | date(timestamp=true) }}">
{{ app.created_at | date() }}
</td>
<td class="sort-id">{{ app.id }}</td>
<td class="sort-redirect-uri">{{ app.redirect_uri }}</td>
<td>
<a class="btn btn-sm btn-outline-secondary" href="#">Details</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block libs_js %}
<script src="/libs/list.js/list.min.js" defer></script>
{% endblock lib_js %}
{% block additional_js %}
<script>
document.addEventListener("DOMContentLoaded", function () {
const list = new List('table-default', {
sortClass: 'table-sort',
listClass: 'table-tbody',
valueNames: ['sort-name', 'sort-status',
{attr: 'data-date', name: 'sort-date'},
'sort-id', 'sort-redirect-uri',
]
});
})
</script>
{% endblock additional_js %}