v0.33.7
This commit is contained in:
1 parent
162e986d37
commit
f462ca7194
26 files changed
+980
-710
No files matched your search
@@ -0,0 +1,103 @@
|
||||
const DASHBOARD_PRESET_MAX: usize = 20;
|
||||
const DASHBOARD_PRESET_NAME_MAX: usize = 64;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct DashboardPreset {
|
||||
name: String,
|
||||
dashboard_density: String,
|
||||
dashboard_widgets: Vec<String>,
|
||||
dashboard_hidden_widgets: Vec<String>,
|
||||
#[serde(default)]
|
||||
dashboard_widget_sizes: Option<std::collections::BTreeMap<String, u8>>,
|
||||
}
|
||||
|
||||
fn reconcile_dashboard_layout(
|
||||
order: &mut Vec<String>,
|
||||
hidden: &mut Vec<String>,
|
||||
sizes: &mut Option<std::collections::BTreeMap<String, u8>>,
|
||||
) {
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
order.retain(|id| {
|
||||
DASHBOARD_WIDGETS.iter().any(|widget| widget.id == *id) && seen.insert(id.clone())
|
||||
});
|
||||
let mut seen_hidden = std::collections::HashSet::new();
|
||||
hidden.retain(|id| {
|
||||
DASHBOARD_WIDGETS.iter().any(|widget| widget.id == *id) && seen_hidden.insert(id.clone())
|
||||
});
|
||||
if let Some(sizes) = sizes.as_mut() {
|
||||
sizes.retain(|id, span| {
|
||||
DASHBOARD_WIDGETS
|
||||
.iter()
|
||||
.any(|widget| widget.id == *id && valid_dashboard_span(&widget.display_type, *span))
|
||||
});
|
||||
}
|
||||
for widget in DASHBOARD_WIDGETS.iter() {
|
||||
if !seen.contains(&widget.id) {
|
||||
order.push(widget.id.clone());
|
||||
if widget.default_hidden && seen_hidden.insert(widget.id.clone()) {
|
||||
hidden.push(widget.id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reconcile_dashboard_presets(presets: &mut [DashboardPreset]) {
|
||||
for preset in presets {
|
||||
reconcile_dashboard_layout(
|
||||
&mut preset.dashboard_widgets,
|
||||
&mut preset.dashboard_hidden_widgets,
|
||||
&mut preset.dashboard_widget_sizes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn valid_dashboard_preset_name(name: &str) -> bool {
|
||||
!name.is_empty()
|
||||
&& name.chars().count() <= DASHBOARD_PRESET_NAME_MAX
|
||||
&& name.trim() == name
|
||||
&& !name.chars().any(char::is_control)
|
||||
}
|
||||
|
||||
fn valid_dashboard_preset(preset: &DashboardPreset) -> bool {
|
||||
if !valid_dashboard_preset_name(&preset.name)
|
||||
|| !matches!(preset.dashboard_density.as_str(), "normal" | "compact" | "ultra")
|
||||
|| preset.dashboard_widgets.is_empty()
|
||||
|| preset.dashboard_widgets.len() > DASHBOARD_WIDGETS.len()
|
||||
|| preset.dashboard_hidden_widgets.len() > DASHBOARD_WIDGETS.len()
|
||||
|| !valid_dashboard_sizes(&preset.dashboard_widget_sizes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let mut order = std::collections::HashSet::new();
|
||||
if preset.dashboard_widgets.iter().any(|id| {
|
||||
!DASHBOARD_WIDGETS.iter().any(|widget| widget.id == *id) || !order.insert(id.as_str())
|
||||
}) {
|
||||
return false;
|
||||
}
|
||||
let mut hidden = std::collections::HashSet::new();
|
||||
!preset.dashboard_hidden_widgets.iter().any(|id| {
|
||||
!order.contains(id.as_str()) || !hidden.insert(id.as_str())
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_dashboard_presets(presets: &[DashboardPreset]) -> Result<(), ApiError> {
|
||||
if presets.len() > DASHBOARD_PRESET_MAX {
|
||||
return Err(ApiError(
|
||||
StatusCode::UNPROCESSABLE_ENTITY,
|
||||
"too many dashboard presets".into(),
|
||||
));
|
||||
}
|
||||
let mut names = std::collections::HashSet::new();
|
||||
for preset in presets {
|
||||
if !valid_dashboard_preset(preset)
|
||||
|| !names.insert(preset.name.to_lowercase())
|
||||
{
|
||||
return Err(ApiError(
|
||||
StatusCode::UNPROCESSABLE_ENTITY,
|
||||
"invalid dashboard preset".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user