Updates
This commit is contained in:
parent
7591e5fc05
commit
89a85e9a0c
22 changed files with 1006 additions and 899 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,7 @@ pub fn parse_field_indices(
|
|||
return Ok(Some(vec![]));
|
||||
}
|
||||
let mut indices = Vec::new();
|
||||
for name in fields_str.split(',') {
|
||||
for name in fields_str.split(";;") {
|
||||
let name = name.trim();
|
||||
if name.is_empty() {
|
||||
continue;
|
||||
|
|
@ -38,7 +38,7 @@ pub fn parse_field_set(fields: Option<&str>) -> (bool, HashSet<String>) {
|
|||
let field_set: HashSet<String> = fields
|
||||
.map(|fields_str| {
|
||||
fields_str
|
||||
.split(',')
|
||||
.split(";;")
|
||||
.map(|field| field.trim().to_string())
|
||||
.filter(|field| !field.is_empty())
|
||||
.collect()
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,7 @@ pub async fn post_ai_filters(
|
|||
"No properties match these filters. Try relaxing some constraints.".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"{}. No properties match — try relaxing some constraints.",
|
||||
"{}. No properties match. Try relaxing some constraints.",
|
||||
notes
|
||||
)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use serde::Serialize;
|
|||
use tracing::info;
|
||||
|
||||
use crate::data::{Histogram, PropertyData};
|
||||
use crate::features::{ENUM_FEATURE_GROUPS, FEATURE_GROUPS};
|
||||
use crate::features::{Feature, FEATURE_GROUPS};
|
||||
use crate::state::SharedState;
|
||||
|
||||
fn is_empty(val: &str) -> bool {
|
||||
|
|
@ -69,74 +69,53 @@ pub struct FeaturesResponse {
|
|||
}
|
||||
|
||||
/// Build the features response at startup. Called once and cached in AppState.
|
||||
/// Feature order in each group follows the array order in FEATURE_GROUPS.
|
||||
pub fn build_features_response(data: &PropertyData) -> FeaturesResponse {
|
||||
// Collect all group names in order, merging numeric and enum groups with the same name
|
||||
let mut group_names: Vec<&str> = Vec::new();
|
||||
for feature_group in FEATURE_GROUPS {
|
||||
if !group_names.contains(&feature_group.name) {
|
||||
group_names.push(feature_group.name);
|
||||
}
|
||||
}
|
||||
for enum_group in ENUM_FEATURE_GROUPS {
|
||||
if !group_names.contains(&enum_group.name) {
|
||||
group_names.push(enum_group.name);
|
||||
}
|
||||
}
|
||||
|
||||
let mut groups: Vec<FeatureGroupResponse> = Vec::new();
|
||||
|
||||
for &group_name in &group_names {
|
||||
for feature_group in FEATURE_GROUPS {
|
||||
let mut features: Vec<FeatureInfo> = Vec::new();
|
||||
|
||||
// Add numeric features for this group
|
||||
for feature_group in FEATURE_GROUPS {
|
||||
if feature_group.name == group_name {
|
||||
for feature_config in feature_group.features {
|
||||
for feature in feature_group.features {
|
||||
match feature {
|
||||
Feature::Numeric(config) => {
|
||||
if let Some(feat_idx) = data
|
||||
.feature_names
|
||||
.iter()
|
||||
.position(|feat_name| feat_name == feature_config.name)
|
||||
.position(|name| name == config.name)
|
||||
{
|
||||
let stats = &data.feature_stats[feat_idx];
|
||||
features.push(FeatureInfo::Numeric {
|
||||
name: feature_config.name.to_string(),
|
||||
name: config.name.to_string(),
|
||||
min: stats.slider_min,
|
||||
max: stats.slider_max,
|
||||
step: feature_config.step,
|
||||
step: config.step,
|
||||
histogram: stats.histogram.clone(),
|
||||
description: feature_config.description,
|
||||
detail: feature_config.detail,
|
||||
source: feature_config.source,
|
||||
prefix: feature_config.prefix,
|
||||
suffix: feature_config.suffix,
|
||||
raw: feature_config.raw,
|
||||
absolute: feature_config.absolute,
|
||||
modes: feature_config.modes,
|
||||
linked: feature_config.linked,
|
||||
description: config.description,
|
||||
detail: config.detail,
|
||||
source: config.source,
|
||||
prefix: config.prefix,
|
||||
suffix: config.suffix,
|
||||
raw: config.raw,
|
||||
absolute: config.absolute,
|
||||
modes: config.modes,
|
||||
linked: config.linked,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add enum features for this group
|
||||
for enum_group in ENUM_FEATURE_GROUPS {
|
||||
if enum_group.name == group_name {
|
||||
for enum_config in enum_group.features {
|
||||
// Find the feature index by name
|
||||
Feature::Enum(config) => {
|
||||
if let Some(feat_idx) = data
|
||||
.feature_names
|
||||
.iter()
|
||||
.position(|name| name == enum_config.name)
|
||||
.position(|name| name == config.name)
|
||||
{
|
||||
// Check if this feature has enum values
|
||||
if let Some(values) = data.enum_values.get(&feat_idx) {
|
||||
features.push(FeatureInfo::Enum {
|
||||
name: enum_config.name.to_string(),
|
||||
name: config.name.to_string(),
|
||||
values: values.clone(),
|
||||
description: enum_config.description,
|
||||
detail: enum_config.detail,
|
||||
source: enum_config.source,
|
||||
description: config.description,
|
||||
detail: config.detail,
|
||||
source: config.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +125,7 @@ pub fn build_features_response(data: &PropertyData) -> FeaturesResponse {
|
|||
|
||||
if !features.is_empty() {
|
||||
groups.push(FeatureGroupResponse {
|
||||
name: group_name.to_string(),
|
||||
name: feature_group.name.to_string(),
|
||||
features,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ pub async fn get_short_url(
|
|||
let redirect_url = format!("/dashboard?{params}");
|
||||
let og_image_url = format!("{}/api/screenshot?og=1&{params}", state.public_url);
|
||||
let og_url = format!("{}/s/{code}", state.public_url);
|
||||
let og_title = "Perfect Postcode \u{2014} Every neighbourhood in England";
|
||||
let og_title = "Perfect Postcode | Every neighbourhood in England";
|
||||
let og_description = "Explore property prices, energy ratings, crime stats, school ratings, and more across England on one interactive map.";
|
||||
|
||||
let html = format!(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue