pib-viewer 0.8.0

A viewer for public governmental data served over OParl
// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

use oparl_types::{
    AgendaItemUrl, BodyUrl, DataListPage, MeetingListUrl, MeetingUrl, MembershipUrl,
    OrganizationListUrl, OrganizationUrl, PersonListUrl, PersonUrl, SystemUrl,
};
use url::Url;

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct SystemReference {
    pub name: String,
    pub url: SystemUrl,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct BodyReference {
    pub name: String,
    pub url: BodyUrl,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(tag = "mode", rename_all = "snake_case")]
pub enum Contents {
    SingleSystem { system: SystemReference },
    SingleBody { body: BodyReference },
    ConnectDialog,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Config {
    pub banner: Option<Vec<Banner>>,
    pub contents: Contents,
    pub footer: Option<Footer>,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BannerStyle {
    Warning,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Banner {
    pub style: BannerStyle,
    pub message: String,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Footer {
    pub links: Option<Vec<FooterLink>>,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct FooterLink {
    pub label: String,
    pub target: String,
}

pub async fn get_page_config(base_url: Url) -> Result<Option<Config>, String> {
    let url = base_url
        .join("/config.json")
        .map_err(|e| format!("Error joining to URL {base_url}: {e}"))?;
    let response = reqwest::get(url).await.map_err(|e| format!("{e}"))?;
    if response.status().as_u16() == 404 {
        return Ok(None);
    }
    Some(response.json::<Config>().await.map_err(|e| format!("{e}"))).transpose()
}

pub async fn get_body(body_url: &BodyUrl) -> Result<oparl_types::Body, String> {
    let response = reqwest::get(format!("{body_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::Body>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_persons(
    persons_url: &PersonListUrl,
) -> Result<DataListPage<oparl_types::Person>, String> {
    let response = reqwest::get(format!("{persons_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::DataListPage<oparl_types::Person>>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_person(person_url: &PersonUrl) -> Result<oparl_types::Person, String> {
    let response = reqwest::get(format!("{person_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::Person>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_organizations(
    organizations_url: &OrganizationListUrl,
) -> Result<DataListPage<oparl_types::Organization>, String> {
    let response = reqwest::get(format!("{organizations_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::DataListPage<oparl_types::Organization>>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_organization(
    organization_url: &OrganizationUrl,
) -> Result<oparl_types::Organization, String> {
    let response = reqwest::get(format!("{organization_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::Organization>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_membership(
    membership_url: &MembershipUrl,
) -> Result<oparl_types::Membership, String> {
    let response = reqwest::get(format!("{membership_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::Membership>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_meetings(
    meetings_url: &MeetingListUrl,
) -> Result<DataListPage<oparl_types::Meeting>, String> {
    let response = reqwest::get(format!("{meetings_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::DataListPage<oparl_types::Meeting>>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_meeting(meeting_url: &MeetingUrl) -> Result<oparl_types::Meeting, String> {
    let response = reqwest::get(format!("{meeting_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::Meeting>()
        .await
        .map_err(|e| format!("{e}"))
}

pub async fn get_agenda_item(
    agenda_item_url: &AgendaItemUrl,
) -> Result<oparl_types::AgendaItem, String> {
    let response = reqwest::get(format!("{agenda_item_url}"))
        .await
        .map_err(|e| format!("{e}"))?;
    response
        .json::<oparl_types::AgendaItem>()
        .await
        .map_err(|e| format!("{e}"))
}