Couple the household & user
This commit is contained in:
parent
eacd89119f
commit
b52443f833
5 changed files with 84 additions and 83 deletions
|
|
@ -12,11 +12,14 @@ use serde::{Deserialize, Serialize};
|
||||||
use tower_sessions::Session;
|
use tower_sessions::Session;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::entity::{household, household_members, prelude::*};
|
use crate::entity::{household, household_members, prelude::*, user};
|
||||||
|
|
||||||
use super::{base_page_with_head, AppState, AuthenticatedUser, RedirectOrError, RouteError};
|
use super::{base_page_with_head, AppState, AuthenticatedUser, RedirectOrError, RouteError};
|
||||||
|
|
||||||
pub(super) struct CurrentHousehold(pub household::Model);
|
pub(super) struct CurrentHousehold {
|
||||||
|
pub(super) user: user::Model,
|
||||||
|
pub(super) household: household::Model,
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn routes() -> Router<AppState> {
|
pub(super) fn routes() -> Router<AppState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
|
|
@ -44,19 +47,30 @@ where
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RouteError::SessionExtract)?;
|
.map_err(|_| RouteError::SessionExtract)?;
|
||||||
|
|
||||||
let id: Uuid = session
|
let user_id: Uuid = session
|
||||||
|
.get("id")
|
||||||
|
.await
|
||||||
|
.map_err(RouteError::from)?
|
||||||
|
.ok_or_else(|| Redirect::to("/login"))?;
|
||||||
|
|
||||||
|
let household_id: Uuid = session
|
||||||
.get("household")
|
.get("household")
|
||||||
.await
|
.await
|
||||||
.map_err(RouteError::from)?
|
.map_err(RouteError::from)?
|
||||||
.ok_or_else(|| Redirect::to("/household/select"))?;
|
.ok_or_else(|| Redirect::to("/household/select"))?;
|
||||||
|
|
||||||
Ok(Self(
|
let (household, user) = Household::find_by_id(household_id)
|
||||||
Household::find_by_id(id)
|
.find_also_related(user::Entity)
|
||||||
.one(&app_state.db)
|
.filter(user::Column::Id.eq(user_id))
|
||||||
.await
|
.one(&app_state.db)
|
||||||
.map_err(RouteError::from)?
|
.await
|
||||||
.unwrap(),
|
.map_err(RouteError::from)?
|
||||||
))
|
.ok_or_else(|| RouteError::RessourceNotFound)?;
|
||||||
|
|
||||||
|
Ok(CurrentHousehold {
|
||||||
|
household,
|
||||||
|
user: user.ok_or_else(|| RouteError::RessourceNotFound)?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,11 +161,11 @@ struct HouseholdName {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn rename(
|
async fn rename(
|
||||||
household: CurrentHousehold,
|
current: CurrentHousehold,
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
Form(form): Form<HouseholdName>,
|
Form(form): Form<HouseholdName>,
|
||||||
) -> Result<Redirect, RouteError> {
|
) -> Result<Redirect, RouteError> {
|
||||||
let mut household: household::ActiveModel = household.0.into();
|
let mut household: household::ActiveModel = current.household.into();
|
||||||
|
|
||||||
household.name = ActiveValue::Set(form.name);
|
household.name = ActiveValue::Set(form.name);
|
||||||
|
|
||||||
|
|
@ -218,8 +232,7 @@ async fn delete_household(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn leave(
|
async fn leave(
|
||||||
household: CurrentHousehold,
|
current: CurrentHousehold,
|
||||||
user: AuthenticatedUser,
|
|
||||||
session: Session,
|
session: Session,
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
) -> Result<Redirect, RouteError> {
|
) -> Result<Redirect, RouteError> {
|
||||||
|
|
@ -227,14 +240,13 @@ async fn leave(
|
||||||
.db
|
.db
|
||||||
.transaction(|txn| {
|
.transaction(|txn| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
HouseholdMembers::delete_by_id((household.0.id, user.model.id))
|
HouseholdMembers::delete_by_id((current.household.id, current.user.id))
|
||||||
.exec(txn)
|
.exec(txn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let Some(household) = Household::find_by_id(household.0.id)
|
let Some(household) = Household::find_by_id(current.household.id).one(txn).await?
|
||||||
.one(txn)
|
else {
|
||||||
.await? else {
|
return Err(RouteError::InvalidRequest("No such household".into()));
|
||||||
return Err(RouteError::InvalidRequest("No such household".into()));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let member_count = household.find_related(User).count(txn).await?;
|
let member_count = household.find_related(User).count(txn).await?;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use super::{
|
||||||
confirm_danger_modal, error_alert,
|
confirm_danger_modal, error_alert,
|
||||||
household::CurrentHousehold,
|
household::CurrentHousehold,
|
||||||
sidebar::{sidebar, SidebarLocation},
|
sidebar::{sidebar, SidebarLocation},
|
||||||
AppState, AuthenticatedUser, RouteError,
|
AppState, RouteError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn routes() -> Router<AppState> {
|
pub(super) fn routes() -> Router<AppState> {
|
||||||
|
|
@ -118,12 +118,11 @@ fn render_ingredients(error: Option<String>, ingredient_list: &[ingredient::Mode
|
||||||
|
|
||||||
async fn ingredients_view(
|
async fn ingredients_view(
|
||||||
error: Option<String>,
|
error: Option<String>,
|
||||||
household: &CurrentHousehold,
|
current: &CurrentHousehold,
|
||||||
user: &AuthenticatedUser,
|
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let list = household
|
let list = current
|
||||||
.0
|
.household
|
||||||
.find_related(Ingredient)
|
.find_related(Ingredient)
|
||||||
.order_by_asc(ingredient::Column::Id)
|
.order_by_asc(ingredient::Column::Id)
|
||||||
.all(db)
|
.all(db)
|
||||||
|
|
@ -131,27 +130,25 @@ async fn ingredients_view(
|
||||||
|
|
||||||
Ok(sidebar(
|
Ok(sidebar(
|
||||||
SidebarLocation::Ingredients,
|
SidebarLocation::Ingredients,
|
||||||
household,
|
current,
|
||||||
user,
|
|
||||||
render_ingredients(error, &list),
|
render_ingredients(error, &list),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn ingredients(
|
async fn ingredients(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
ingredients_view(None, &household, &user, &state.db).await
|
ingredients_view(None, ¤t, &state.db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_ingredient_delete(
|
async fn do_ingredient_delete(
|
||||||
household: &CurrentHousehold,
|
current: &CurrentHousehold,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
id: i64,
|
id: i64,
|
||||||
) -> Result<Option<String>, RouteError> {
|
) -> Result<Option<String>, RouteError> {
|
||||||
if household
|
if current
|
||||||
.0
|
.household
|
||||||
.find_related(Ingredient)
|
.find_related(Ingredient)
|
||||||
.filter(ingredient::Column::Id.eq(id))
|
.filter(ingredient::Column::Id.eq(id))
|
||||||
.count(db)
|
.count(db)
|
||||||
|
|
@ -182,14 +179,12 @@ async fn do_ingredient_delete(
|
||||||
|
|
||||||
async fn delete_ingredient(
|
async fn delete_ingredient(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
ig: Path<i64>,
|
ig: Path<i64>,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
ingredients_view(
|
ingredients_view(
|
||||||
do_ingredient_delete(&household, &state.db, ig.0).await?,
|
do_ingredient_delete(¤t, &state.db, ig.0).await?,
|
||||||
&household,
|
¤t,
|
||||||
&user,
|
|
||||||
&state.db,
|
&state.db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
@ -203,12 +198,12 @@ struct IngredientDesc {
|
||||||
|
|
||||||
async fn edit_ingredient(
|
async fn edit_ingredient(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
household: CurrentHousehold,
|
current: CurrentHousehold,
|
||||||
ig: Path<i64>,
|
ig: Path<i64>,
|
||||||
form: Form<IngredientDesc>,
|
form: Form<IngredientDesc>,
|
||||||
) -> Result<Redirect, RouteError> {
|
) -> Result<Redirect, RouteError> {
|
||||||
let ingredient = household
|
let ingredient = current
|
||||||
.0
|
.household
|
||||||
.find_related(Ingredient)
|
.find_related(Ingredient)
|
||||||
.filter(ingredient::Column::Id.eq(ig.0))
|
.filter(ingredient::Column::Id.eq(ig.0))
|
||||||
.one(&state.db)
|
.one(&state.db)
|
||||||
|
|
@ -228,7 +223,7 @@ async fn edit_ingredient(
|
||||||
|
|
||||||
async fn add_ingredient(
|
async fn add_ingredient(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
household: CurrentHousehold,
|
current: CurrentHousehold,
|
||||||
form: Form<IngredientDesc>,
|
form: Form<IngredientDesc>,
|
||||||
) -> Result<Redirect, RouteError> {
|
) -> Result<Redirect, RouteError> {
|
||||||
let mut ingredient = ingredient::ActiveModel::new();
|
let mut ingredient = ingredient::ActiveModel::new();
|
||||||
|
|
@ -237,7 +232,7 @@ async fn add_ingredient(
|
||||||
true => None,
|
true => None,
|
||||||
false => Some(form.0.unit),
|
false => Some(form.0.unit),
|
||||||
});
|
});
|
||||||
ingredient.household = ActiveValue::Set(household.0.id);
|
ingredient.household = ActiveValue::Set(current.household.id);
|
||||||
|
|
||||||
ingredient.insert(&state.db).await?;
|
ingredient.insert(&state.db).await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,13 +345,12 @@ fn confirm_danger_modal(id: &str, inner: &str, action: &str, title: &str) -> Mar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn index(user: AuthenticatedUser, household: CurrentHousehold) -> Markup {
|
async fn index(current: CurrentHousehold) -> Markup {
|
||||||
sidebar::sidebar(
|
sidebar::sidebar(
|
||||||
SidebarLocation::Home,
|
SidebarLocation::Home,
|
||||||
&household,
|
¤t,
|
||||||
&user,
|
|
||||||
html! {
|
html! {
|
||||||
"Hello world in " (household.0.name) "!"
|
"Hello world in " (current.household.name) "!"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use super::{
|
||||||
base_page,
|
base_page,
|
||||||
household::CurrentHousehold,
|
household::CurrentHousehold,
|
||||||
sidebar::{sidebar, SidebarLocation},
|
sidebar::{sidebar, SidebarLocation},
|
||||||
AppState, AuthenticatedUser, RouteError,
|
AppState, RouteError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn routes() -> Router<AppState> {
|
pub(super) fn routes() -> Router<AppState> {
|
||||||
|
|
@ -72,11 +72,10 @@ fn recipe_list(recipes: &[recipe::Model], household: Option<Uuid>) -> Markup {
|
||||||
|
|
||||||
async fn list_recipes(
|
async fn list_recipes(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let recipes = household
|
let recipes = current
|
||||||
.0
|
.household
|
||||||
.find_related(Recipe)
|
.find_related(Recipe)
|
||||||
.order_by_asc(recipe::Column::Name)
|
.order_by_asc(recipe::Column::Name)
|
||||||
.all(&state.db)
|
.all(&state.db)
|
||||||
|
|
@ -84,8 +83,7 @@ async fn list_recipes(
|
||||||
|
|
||||||
Ok(sidebar(
|
Ok(sidebar(
|
||||||
SidebarLocation::RecipeList,
|
SidebarLocation::RecipeList,
|
||||||
&household,
|
¤t,
|
||||||
&user,
|
|
||||||
recipe_list(&recipes, None),
|
recipe_list(&recipes, None),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -222,12 +220,11 @@ async fn recipe_view(
|
||||||
|
|
||||||
async fn view_recipe(
|
async fn view_recipe(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
id: Path<i32>,
|
id: Path<i32>,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let recipe = household
|
let recipe = current
|
||||||
.0
|
.household
|
||||||
.find_related(Recipe)
|
.find_related(Recipe)
|
||||||
.filter(recipe::Column::Id.eq(id.0))
|
.filter(recipe::Column::Id.eq(id.0))
|
||||||
.one(&state.db)
|
.one(&state.db)
|
||||||
|
|
@ -236,9 +233,8 @@ async fn view_recipe(
|
||||||
|
|
||||||
Ok(sidebar(
|
Ok(sidebar(
|
||||||
SidebarLocation::RecipeList,
|
SidebarLocation::RecipeList,
|
||||||
&household,
|
¤t,
|
||||||
&user,
|
recipe_view(&recipe, current.household.id, true, &state.db).await?,
|
||||||
recipe_view(&recipe, household.0.id, true, &state.db).await?,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,12 +286,11 @@ struct CreateAddIngredient {
|
||||||
|
|
||||||
async fn create_recipe_ingredient(
|
async fn create_recipe_ingredient(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
_user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
Form(form): Form<CreateAddIngredient>,
|
Form(form): Form<CreateAddIngredient>,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let ingredient = ingredient::ActiveModel {
|
let ingredient = ingredient::ActiveModel {
|
||||||
household: sea_orm::ActiveValue::Set(household.0.id),
|
household: sea_orm::ActiveValue::Set(current.household.id),
|
||||||
name: sea_orm::ActiveValue::Set(form.name),
|
name: sea_orm::ActiveValue::Set(form.name),
|
||||||
unit: sea_orm::ActiveValue::Set(form.unit),
|
unit: sea_orm::ActiveValue::Set(form.unit),
|
||||||
id: sea_orm::ActiveValue::NotSet,
|
id: sea_orm::ActiveValue::NotSet,
|
||||||
|
|
@ -363,9 +358,13 @@ fn create_ingredient_modal() -> Markup {
|
||||||
|
|
||||||
async fn ingredient_list(
|
async fn ingredient_list(
|
||||||
state: &State<AppState>,
|
state: &State<AppState>,
|
||||||
household: &CurrentHousehold,
|
current: &CurrentHousehold,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let list = household.0.find_related(Ingredient).all(&state.db).await?;
|
let list = current
|
||||||
|
.household
|
||||||
|
.find_related(Ingredient)
|
||||||
|
.all(&state.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(html! {
|
Ok(html! {
|
||||||
@for ig in list {
|
@for ig in list {
|
||||||
|
|
@ -376,10 +375,10 @@ async fn ingredient_list(
|
||||||
|
|
||||||
async fn select_ingredient(
|
async fn select_ingredient(
|
||||||
state: &State<AppState>,
|
state: &State<AppState>,
|
||||||
household: &CurrentHousehold,
|
current: &CurrentHousehold,
|
||||||
extra_controls: Markup,
|
extra_controls: Markup,
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let ingredients = ingredient_list(state, household).await?;
|
let ingredients = ingredient_list(state, current).await?;
|
||||||
|
|
||||||
Ok(html! {
|
Ok(html! {
|
||||||
.d-flex.flex-column.align-items-start {
|
.d-flex.flex-column.align-items-start {
|
||||||
|
|
@ -469,8 +468,7 @@ igAdd.addEventListener("click", function(event) {
|
||||||
|
|
||||||
async fn do_create_recipe(
|
async fn do_create_recipe(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
_user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
Form(form): Form<Vec<(String, String)>>,
|
Form(form): Form<Vec<(String, String)>>,
|
||||||
) -> Result<Redirect, RouteError> {
|
) -> Result<Redirect, RouteError> {
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
|
|
@ -527,7 +525,7 @@ async fn do_create_recipe(
|
||||||
person_count: extract("person_count", person_count)?,
|
person_count: extract("person_count", person_count)?,
|
||||||
ranking: extract("rating", rating)?,
|
ranking: extract("rating", rating)?,
|
||||||
steps: extract("steps", steps)?,
|
steps: extract("steps", steps)?,
|
||||||
household: sea_orm::ActiveValue::Set(household.0.id),
|
household: sea_orm::ActiveValue::Set(current.household.id),
|
||||||
}
|
}
|
||||||
.insert(tx)
|
.insert(tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
@ -552,8 +550,7 @@ async fn do_create_recipe(
|
||||||
|
|
||||||
async fn create_recipe(
|
async fn create_recipe(
|
||||||
state: State<AppState>,
|
state: State<AppState>,
|
||||||
user: AuthenticatedUser,
|
current: CurrentHousehold,
|
||||||
household: CurrentHousehold,
|
|
||||||
) -> Result<Markup, RouteError> {
|
) -> Result<Markup, RouteError> {
|
||||||
let create_ig = html! {
|
let create_ig = html! {
|
||||||
button .btn.btn-primary
|
button .btn.btn-primary
|
||||||
|
|
@ -564,8 +561,7 @@ async fn create_recipe(
|
||||||
|
|
||||||
Ok(sidebar(
|
Ok(sidebar(
|
||||||
SidebarLocation::RecipeCreator,
|
SidebarLocation::RecipeCreator,
|
||||||
&household,
|
¤t,
|
||||||
&user,
|
|
||||||
html! {
|
html! {
|
||||||
script { (PreEscaped(r#"
|
script { (PreEscaped(r#"
|
||||||
function removeIngredient (self) {
|
function removeIngredient (self) {
|
||||||
|
|
@ -603,7 +599,7 @@ function removeIngredient (self) {
|
||||||
|
|
||||||
.d-flex.flex-column.justify-content-start {
|
.d-flex.flex-column.justify-content-start {
|
||||||
h2 { "Ingredients" }
|
h2 { "Ingredients" }
|
||||||
(select_ingredient(&state, &household, create_ig).await?)
|
(select_ingredient(&state, ¤t, create_ig).await?)
|
||||||
ul .list-group.list-group-flush.text-start #recipeIngredients {}
|
ul .list-group.list-group-flush.text-start #recipeIngredients {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use maud::{html, Markup};
|
use maud::{html, Markup};
|
||||||
|
|
||||||
use super::{base_page, confirm_danger_modal, household::CurrentHousehold, AuthenticatedUser};
|
use super::{base_page, confirm_danger_modal, household::CurrentHousehold};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub(super) enum SidebarLocation {
|
pub(super) enum SidebarLocation {
|
||||||
|
|
@ -80,9 +80,8 @@ fn rename_hs_modal(current: &str) -> Markup {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn sidebar(
|
pub(super) fn sidebar(
|
||||||
current: SidebarLocation,
|
current_page: SidebarLocation,
|
||||||
household: &CurrentHousehold,
|
current: &CurrentHousehold,
|
||||||
user: &AuthenticatedUser,
|
|
||||||
inner: Markup,
|
inner: Markup,
|
||||||
) -> Markup {
|
) -> Markup {
|
||||||
let entries = &[
|
let entries = &[
|
||||||
|
|
@ -118,7 +117,7 @@ pub(super) fn sidebar(
|
||||||
li .nav-item."w-100" {
|
li .nav-item."w-100" {
|
||||||
a href=(entry.location.to())
|
a href=(entry.location.to())
|
||||||
class={"nav-link text-white" (
|
class={"nav-link text-white" (
|
||||||
(entry.location == current).then_some(" active").unwrap_or("")
|
(entry.location == current_page).then_some(" active").unwrap_or("")
|
||||||
)} {
|
)} {
|
||||||
i class={"fs-4 " (entry.icon)} {}
|
i class={"fs-4 " (entry.icon)} {}
|
||||||
span ."ms-2".d-none.d-sm-inline { (entry.label) }
|
span ."ms-2".d-none.d-sm-inline { (entry.label) }
|
||||||
|
|
@ -129,17 +128,17 @@ pub(super) fn sidebar(
|
||||||
hr ."w-100";
|
hr ."w-100";
|
||||||
(confirm_danger_modal(
|
(confirm_danger_modal(
|
||||||
"leaveModal",
|
"leaveModal",
|
||||||
&format!("Are you sure you want to leave the household {}", household.0.name),
|
&format!("Are you sure you want to leave the household {}", current.household.name),
|
||||||
"/household/leave",
|
"/household/leave",
|
||||||
"Leave Household",
|
"Leave Household",
|
||||||
))
|
))
|
||||||
(rename_hs_modal(&household.0.name))
|
(rename_hs_modal(¤t.household.name))
|
||||||
.dropdown {
|
.dropdown {
|
||||||
a href="#" "data-bs-toggle"="dropdown" "aria-expanded"="false"
|
a href="#" "data-bs-toggle"="dropdown" "aria-expanded"="false"
|
||||||
.d-flex.align-items-center.text-white.text-decoration-none.dropdown-toggle {
|
.d-flex.align-items-center.text-white.text-decoration-none.dropdown-toggle {
|
||||||
i ."fs-4".bi-house-door-fill {}
|
i ."fs-4".bi-house-door-fill {}
|
||||||
strong ."ms-2".d-none.d-sm-inline {
|
strong ."ms-2".d-none.d-sm-inline {
|
||||||
(household.0.name) " (" (user.model.name) ")"
|
(current.household.name) " (" (current.user.name) ")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul .dropdown-menu {
|
ul .dropdown-menu {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue