short and long description
This commit is contained in:
@@ -171,6 +171,8 @@ artist = Artist
|
||||
release-date = Release date
|
||||
cover-image = Cover image
|
||||
description = Description
|
||||
short-description = Short description
|
||||
short-description-hint = Shown on product cards (max 200 characters).
|
||||
songs-in-album = Songs in this album
|
||||
admin-new-album-desc = Fill in the details, then tick the songs to include.
|
||||
cover-help = Optional - png, jpg, webp or gif; shown on the album page.
|
||||
|
||||
@@ -171,6 +171,8 @@ artist = Interpret
|
||||
release-date = Dátum vydania
|
||||
cover-image = Obrázok obalu
|
||||
description = Popis
|
||||
short-description = Krátky popis
|
||||
short-description-hint = Zobrazuje sa na kartách produktov (max 200 znakov).
|
||||
songs-in-album = Skladby v albume
|
||||
admin-new-album-desc = Vyplň údaje a potom označ skladby, ktoré chceš zahrnúť.
|
||||
cover-help = Voliteľné - png, jpg, webp alebo gif; zobrazí sa na stránke albumu.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,9 +18,9 @@
|
||||
{{ ui::csrf_field() }}
|
||||
|
||||
{% if product %}
|
||||
{% set v_name = product.name %}{% set v_currency = product.currency %}{% set v_desc = product.description | default(value="") %}{% set v_pub = product.published %}
|
||||
{% set v_name = product.name %}{% set v_currency = product.currency %}{% set v_desc = product.description | default(value="") %}{% set v_short = product.short_description | default(value="") %}{% set v_pub = product.published %}
|
||||
{% else %}
|
||||
{% set v_name = "" %}{% set v_currency = "EUR" %}{% set v_desc = "" %}{% set v_pub = false %}
|
||||
{% set v_name = "" %}{% set v_currency = "EUR" %}{% set v_desc = "" %}{% set v_short = "" %}{% set v_pub = false %}
|
||||
{% endif %}
|
||||
{% set inp = "w-full rounded-radius border border-outline bg-surface-alt px-3 py-2 text-sm text-on-surface focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary dark:border-outline-dark dark:bg-surface-dark-alt/50 dark:text-on-surface-dark dark:focus-visible:outline-primary-dark" %}
|
||||
{% set sublabel = "text-xs font-medium text-on-surface/70 dark:text-on-surface-dark/70" %}
|
||||
@@ -116,6 +116,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-1.5">
|
||||
<label for="short_description" class="text-sm font-medium text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="short-description", lang=lang | default(value='sk')) }}</label>
|
||||
<p class="{{ sublabel }}">{{ t(key="short-description-hint", lang=lang | default(value='sk')) }}</p>
|
||||
{{ ui::textarea(name="short_description", id="short_description", rows="2", value=v_short, attrs='maxlength="200"') }}
|
||||
</div>
|
||||
|
||||
<div class="space-y-1.5">
|
||||
<label for="description" class="text-sm font-medium text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="description", lang=lang | default(value='sk')) }}</label>
|
||||
{{ ui::textarea(name="description", id="description", rows="5", value=v_desc) }}
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
:class="view === 'list' ? 'p-4 sm:p-5' : 'p-6 pb-2'">
|
||||
<!-- Header: Title & Price (stacked so neither overflows the narrow card) -->
|
||||
<h3 class="break-words text-lg font-bold text-on-surface-strong dark:text-on-surface-dark-strong">{{ product.name }}</h3>
|
||||
{# Short blurb for the card; falls back to the full description (clamped)
|
||||
for products without a dedicated short one. Overflow is truncated with an
|
||||
ellipsis: 2 lines in the grid, 3 in the roomier list row. #}
|
||||
{% if product.short_description or product.description %}
|
||||
<p class="line-clamp-2 break-words text-sm text-on-surface/70 dark:text-on-surface-dark/70"
|
||||
:class="view === 'list' && 'line-clamp-3'">{% if product.short_description %}{{ product.short_description }}{% else %}{{ product.description }}{% endif %}</p>
|
||||
{% endif %}
|
||||
{% if product.on_sale %}
|
||||
<div class="flex flex-wrap items-baseline gap-x-2 leading-tight">
|
||||
<span class="text-xl font-semibold text-danger"><span class="sr-only">Price</span>{% if product.has_options %}{{ t(key="from-price", price=product.price, lang=lang | default(value='sk')) }}{% else %}{{ product.price }}{% endif %} {{ product.currency }}</span>
|
||||
|
||||
@@ -45,6 +45,7 @@ mod m20260622_000003_variant_stock_nullable;
|
||||
mod m20260622_000004_product_search;
|
||||
mod m20260622_000005_product_search_aggregate;
|
||||
mod m20260622_000006_order_search_indexes;
|
||||
mod m20260623_000001_add_short_description_to_products;
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -94,6 +95,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260622_000004_product_search::Migration),
|
||||
Box::new(m20260622_000005_product_search_aggregate::Migration),
|
||||
Box::new(m20260622_000006_order_search_indexes::Migration),
|
||||
Box::new(m20260623_000001_add_short_description_to_products::Migration),
|
||||
// inject-above (do not remove this comment)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
use loco_rs::schema::*;
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> {
|
||||
// A short blurb shown on product cards (grid/list), distinct from the full
|
||||
// `description` rendered on the product detail page.
|
||||
add_column(m, "products", "short_description", ColType::TextNull).await
|
||||
}
|
||||
|
||||
async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> {
|
||||
remove_column(m, "products", "short_description").await
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ struct ProductFields {
|
||||
name: String,
|
||||
slug: String,
|
||||
description: Option<String>,
|
||||
short_description: Option<String>,
|
||||
currency: String,
|
||||
category_id: Option<i32>,
|
||||
published: bool,
|
||||
@@ -67,6 +68,7 @@ async fn parse_product_fields(
|
||||
.ok_or_else(|| Error::BadRequest("product name is required".to_string()))?;
|
||||
let currency = form.text("currency").unwrap_or_else(|| "EUR".to_string());
|
||||
let description = form.text("description");
|
||||
let short_description = form.text("short_description");
|
||||
let category_id = form.text("category_id").and_then(|s| s.parse::<i32>().ok());
|
||||
let published = form.checked("published");
|
||||
|
||||
@@ -91,6 +93,7 @@ async fn parse_product_fields(
|
||||
name,
|
||||
slug,
|
||||
description,
|
||||
short_description,
|
||||
currency,
|
||||
category_id,
|
||||
published,
|
||||
@@ -438,6 +441,7 @@ async fn create(
|
||||
name: Set(fields.name),
|
||||
slug: Set(fields.slug),
|
||||
description: Set(fields.description),
|
||||
short_description: Set(fields.short_description),
|
||||
currency: Set(fields.currency),
|
||||
view_count: Set(0),
|
||||
published: Set(fields.published),
|
||||
@@ -552,6 +556,7 @@ async fn update(
|
||||
product.name = Set(fields.name);
|
||||
product.slug = Set(fields.slug);
|
||||
product.description = Set(fields.description);
|
||||
product.short_description = Set(fields.short_description);
|
||||
product.currency = Set(fields.currency);
|
||||
product.category_id = Set(fields.category_id);
|
||||
product.published = Set(fields.published);
|
||||
|
||||
@@ -15,6 +15,8 @@ pub struct Model {
|
||||
pub slug: String,
|
||||
#[sea_orm(column_type = "Text", nullable)]
|
||||
pub description: Option<String>,
|
||||
#[sea_orm(column_type = "Text", nullable)]
|
||||
pub short_description: Option<String>,
|
||||
pub currency: String,
|
||||
pub view_count: i32,
|
||||
pub published: bool,
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn product_card(
|
||||
"name": product.name,
|
||||
"slug": product.slug,
|
||||
"description": product.description,
|
||||
"short_description": product.short_description,
|
||||
"price": format_price(priced.price_cents),
|
||||
"on_sale": priced.is_reduced(),
|
||||
"is_business": priced.is_business,
|
||||
@@ -69,6 +70,7 @@ pub fn product_form(product: &products::Model, images: &[product_images::Model])
|
||||
"name": product.name,
|
||||
"slug": product.slug,
|
||||
"description": product.description,
|
||||
"short_description": product.short_description,
|
||||
"currency": product.currency,
|
||||
"published": product.published,
|
||||
"category_id": product.category_id,
|
||||
|
||||
Reference in New Issue
Block a user