PR with too many features #58

Merged
BobdaFett merged 56 commits from feat/admin-page into main 2026-02-10 14:31:49 +00:00
8 changed files with 198 additions and 90 deletions
Showing only changes of commit a95e9a1034 - Show all commits

No files matched your search

+57 -14
View File
@@ -1,26 +1,69 @@
use leptos::logging::log;
use leptos::prelude::*;
use crate::common::ValueType;
use crate::components::{NavListInfo, SelectableNavList};
use crate::pages::api::get_all_providers;
#[component]
pub fn AdminProviderPage() -> impl IntoView {
let selected_items = RwSignal::new(Vec::new());
let provider_list = RwSignal::new(vec![
NavListInfo {
text: vec!["Testing 1".to_string(), 3.to_string(), 500.to_string()],
id: "1".to_string(),
slug: "1".to_string(),
},
NavListInfo {
text: vec!["Testing 2".to_string(), 2.to_string(), 1000.to_string()],
id: "2".to_string(),
slug: "2".to_string(),
let provider_list = RwSignal::new(Vec::new());
let provider_trigger = Trigger::new();
let provider_resource = Resource::new(
move || provider_trigger.track(),
async move |_| {
get_all_providers().await
}
]);
);
Effect::new(move || {
if let Some(Err(err)) = provider_resource.get() {
log!("Found error: {}", err.to_string());
}
let Some(Ok(list)) = provider_resource.get() else {
return;
};
let members_list = vec![
"contact_email".to_string(),
"first_name".to_string(),
"last_name".to_string(),
];
// Convert the list into a series of NavListInfo
let converted = list
.into_iter()
.map(|info| {
let mut text_list = vec![];
members_list.iter().for_each(|member| {
let val = info.get(member)
.unwrap_or(&ValueType::String(None))
.as_string()
.ok().flatten()
.unwrap_or_default();
text_list.push(val);
});
let subject = info.get("subject")
.unwrap_or(&ValueType::String(None))
.to_string();
NavListInfo {
text: text_list,
id: subject.clone(),
slug: subject,
}
})
.collect();
provider_list.set(converted);
});
let headers = vec![
"Scholarship Name",
"Number of Awards",
"Amount of Awards"
"Email",
"First Name",
"Last Name"
]
.iter()
.map(|s| s.to_string())
+44
View File
@@ -0,0 +1,44 @@
use leptos::prelude::*;
use std::collections::HashMap;
use crate::common::ValueType;
use leptos::logging::log;
#[cfg(feature = "ssr")]
mod server_logic {
pub use crate::utils::server::create_dynamo_client;
pub use super::super::PROVIDER_CONTACT_TABLE;
}
#[server]
pub async fn get_all_providers() -> Result<Vec<HashMap<String, ValueType>>, ServerFnError> {
use server_logic::*;
// We want to get all provider information from the contacts table.
// This will be migrated to the new table structure when it happens.
let client = create_dynamo_client().await;
log!("Scanning all provider information from {}", PROVIDER_CONTACT_TABLE);
client
.scan()
.table_name(PROVIDER_CONTACT_TABLE)
.send()
.await
.map(|output| {
if let Some(items) = output.items {
items
.into_iter()
.map(|item| {
item.into_iter().map(|(key, attr)| {
let val = ValueType::from(&attr);
(key, val)
}).collect()
})
.collect::<Vec<HashMap<String, ValueType>>>()
} else {
Vec::new()
}
})
.map_err(ServerFnError::from)
}
+3 -2
View File
@@ -7,6 +7,9 @@ use aws_sdk_dynamodb::error::ProvideErrorMetadata;
#[cfg(feature = "ssr")]
use leptos::logging::log;
#[cfg(feature = "ssr")]
use super::COMPARISONS_TABLE;
use crate::common::{
ComparisonData, ComparisonType, MapListComparison, NumberComparison, NumberListComparison,
TextComparison, TextListComparison, ValueType,
@@ -15,8 +18,6 @@ use std::collections::HashMap;
use leptos::prelude::ServerFnError;
use leptos::server;
#[cfg(feature = "ssr")]
static COMPARISONS_TABLE: &str = "leptos-comparisons";
/// Helper function to create all sports comparisons. Only used to create initial
/// comparison data, and should be removed upon completion of a comparison editor page.
+1 -1
View File
@@ -4,7 +4,7 @@ use leptos::prelude::*;
use crate::common::DateInfo;
#[cfg(feature = "ssr")]
static DATES_TABLE: &str = "leptos-dates";
use super::DATES_TABLE;
#[cfg(feature = "ssr")]
use aws_sdk_dynamodb::{
+19 -3
View File
@@ -1,7 +1,23 @@
mod comparisons;
pub use comparisons::*;
mod scholarships;
pub use scholarships::*;
mod dates;
pub use dates::*;
mod admin;
mod providers;
pub use comparisons::*;
pub use scholarships::*;
pub use dates::*;
pub use admin::*;
pub use providers::*;
#[cfg(feature = "ssr")]
pub static COMPARISONS_TABLE: &str = "leptos-comparisons";
#[cfg(feature = "ssr")]
pub static DATES_TABLE: &str = "leptos-dates";
#[cfg(feature = "ssr")]
pub static SCHOLARSHIPS_TABLE: &str = "leptos-scholarships";
#[cfg(feature = "ssr")]
pub static PROVIDER_CONTACT_TABLE: &str = "leptos-provider-contacts";
+70
View File
@@ -0,0 +1,70 @@
use leptos::prelude::*;
use leptos::logging::log;
use std::collections::HashMap;
use crate::common::ValueType;
#[cfg(feature = "ssr")]
use crate::utils::server::{create_dynamo_client, into_attr_map};
#[cfg(feature = "ssr")]
static PROVIDER_CONTACT_TABLE: &str = "leptos-provider-contacts";
#[server]
pub async fn get_provider_contact(id: String) -> Result<HashMap<String, ValueType>, ServerFnError> {
use aws_sdk_dynamodb::types::AttributeValue;
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
let client = create_dynamo_client().await;
log!("Getting contact info for provider {}", id);
match client
.get_item()
.table_name(PROVIDER_CONTACT_TABLE)
.key("subject", AttributeValue::S(id))
.send()
.await
{
Ok(output) => {
let Some(item) = output.item else {
return Ok(HashMap::new());
};
let map = item.iter().map(|(key, val)| {
let val_type = ValueType::from(val);
(key.clone(), val_type)
}).collect::<HashMap<String, ValueType>>();
Ok(map)
}
Err(err) => {
let msg = err.message().unwrap_or("An unknown error occurred.");
Err(ServerFnError::new(msg))
}
}
}
#[server]
pub async fn put_provider_contact(id: String, contact_info: HashMap<String, ValueType>) -> Result<(), ServerFnError> {
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
let client = create_dynamo_client().await;
let mut item = into_attr_map(contact_info);
item.insert("subject".to_owned(), aws_sdk_dynamodb::types::AttributeValue::S(id));
match client
.put_item()
.table_name(PROVIDER_CONTACT_TABLE)
.set_item(Some(item))
.send()
.await
{
Ok(_) => Ok(()),
Err(err) => {
let msg = err.message().unwrap_or("An unknown error occurred.");
Err(ServerFnError::new(msg))
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ use leptos::prelude::ServerFnError;
use leptos::server;
#[cfg(feature = "ssr")]
static SCHOLARSHIPS_TABLE: &str = "leptos-scholarships";
use super::SCHOLARSHIPS_TABLE;
#[server(GetScholarshipInfo)]
pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFnError> {
+3 -69
View File
@@ -1,77 +1,11 @@
#[cfg(feature = "ssr")]
use crate::utils::server::{create_dynamo_client, into_attr_map};
use std::collections::HashMap;
use std::collections::HashMap;
use leptos::logging::log;
use leptos::prelude::*;
use leptos_oidc::{AuthLoaded, Authenticated};
use crate::common::ValueType;
use crate::components::{Banner, Loading, OutlinedTextField, Panel, Row, TextFieldType, Toast, ToastContext, ToastList, ValidatedForm};
use crate::components::{Banner, Loading, OutlinedTextField, Panel, Row, TextFieldType, Toast, ToastContext, ValidatedForm};
use crate::pages::UnauthenticatedPage;
use crate::utils::get_user_claims;
#[cfg(feature = "ssr")]
static PROVIDER_CONTACT_TABLE: &str = "leptos-provider-contacts";
#[server]
async fn get_provider_contact(id: String) -> Result<HashMap<String, ValueType>, ServerFnError> {
use aws_sdk_dynamodb::types::AttributeValue;
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
let client = create_dynamo_client().await;
log!("Getting contact info for provider {}", id);
match client
.get_item()
.table_name(PROVIDER_CONTACT_TABLE)
.key("subject", AttributeValue::S(id))
.send()
.await
{
Ok(output) => {
let Some(item) = output.item else {
return Ok(HashMap::new());
};
let map = item.iter().map(|(key, val)| {
let val_type = ValueType::from(val);
(key.clone(), val_type)
}).collect::<HashMap<String, ValueType>>();
Ok(map)
}
Err(err) => {
let msg = err.message().unwrap_or("An unknown error occurred.");
Err(ServerFnError::new(msg))
}
}
}
#[server]
async fn put_provider_contact(id: String, contact_info: HashMap<String, ValueType>) -> Result<(), ServerFnError> {
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
let client = create_dynamo_client().await;
let mut item = into_attr_map(contact_info);
item.insert("subject".to_owned(), aws_sdk_dynamodb::types::AttributeValue::S(id));
match client
.put_item()
.table_name(PROVIDER_CONTACT_TABLE)
.set_item(Some(item))
.send()
.await
{
Ok(_) => Ok(()),
Err(err) => {
let msg = err.message().unwrap_or("An unknown error occurred.");
Err(ServerFnError::new(msg))
}
}
}
use super::api::{get_provider_contact, PutProviderContact};
#[component]
pub fn ProviderContactPage() -> impl IntoView {