Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@

## Unreleased

### Changed

- 入力画面を目的別の8セクションへ再編し、暖房・冷房は選択方式の項目を同じ
セクション内に表示するようにした。建研Web由来項目の表示名を建研Webの文言へ
揃え、各セクション・グループ・主要入力に用途と計算への影響を説明する文を追加した。
- 入力画面ガイドを追加し、床下関連設定の入力ガイドを新しい画面構成へ更新した。

## [1.2.0] - 2026-08-13

### Added
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ docker run --rm -p 8080:8080 verification-platform-next
- [アーキテクチャ](docs/ARCHITECTURE.md)
- [リリースと成果物の版管理](docs/RELEASING.md)
- [変更履歴](CHANGELOG.md)
- [入力画面ガイド](docs/input_guide.md)
- [床下関連設定の入力ガイド](docs/underfloor_ac_input_guide.md)
- [床下空調計算の7つの変更点](docs/underfloor_ac_seven_changes.md)
- [Excelとの床下計算整合](docs/underfloor_ac_excel_alignment.md)
Expand Down
36 changes: 30 additions & 6 deletions apps/gradio/src/verification_app/form_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,19 @@
font-size: 1rem !important;
font-weight: 600 !important;
line-height: 1.45 !important;
margin: 0.65rem 0 0.35rem !important;
margin: 0.65rem 0 0.2rem !important;
}
.input-section-description p,
.input-group-heading p {
color: var(--body-text-color-subdued);
font-size: 0.88rem !important;
line-height: 1.55 !important;
}
.input-section-description p {
margin: 0 0 0.75rem !important;
}
.input-group-heading p {
margin: 0 0 0.45rem !important;
}
.annual-summary {
margin: 0.85rem 0 1rem;
Expand Down Expand Up @@ -222,7 +234,12 @@ def build_app(
) as section_container:
section_containers[section.name] = section_container
section_dom_ids[section.name] = section_dom_id
if section.name == "⑥ その他":
if section.description:
gr.Markdown(
section.description,
elem_classes=["input-section-description"],
)
if section.name == "④ 床下・空気搬送":
gr.Markdown(
"📘 床下関係の方式選択、推奨値、入力例は"
f"[床下関連設定の入力ガイド]({_UNDERFLOOR_INPUT_GUIDE_URL})"
Expand All @@ -234,7 +251,8 @@ def build_app(
form_field.definition for form_field in group.fields
)
gr.Markdown(
f"## {group.name}",
f"## {group.name}"
+ (f"\n\n{group.description}" if group.description else ""),
elem_id=group_dom_id,
elem_classes=["input-group-heading"],
)
Expand All @@ -245,6 +263,9 @@ def build_app(
field_dom_id = f"input-field-container-{len(components)}"
component = _input_component(
form_field.definition,
label=form_field.label,
description=form_field.description,
choices=form_field.choices,
visible=form_field.visible,
min_width=280,
elem_id=field_dom_id,
Expand Down Expand Up @@ -537,15 +558,18 @@ def _section_is_visible(
def _input_component(
field: FieldDefinition,
*,
label: str | None = None,
description: str | None = None,
choices: tuple[Any, ...] | None = None,
visible: bool = True,
min_width: int | None = None,
elem_id: str | None = None,
elem_classes: list[str] | None = None,
) -> Any:
common = {
"label": field.label,
"label": label or field.label,
"value": field.default,
"info": field.description or None,
"info": description if description is not None else field.description or None,
"key": f"field:{field.key}",
"visible": visible,
"min_width": min_width,
Expand All @@ -560,7 +584,7 @@ def _input_component(
return gr.Checkbox(**common)
if field.kind is FieldKind.SELECT:
return gr.Dropdown(
choices=list(field.choices),
choices=list(choices if choices is not None else field.choices),
allow_custom_value=False,
**common,
)
Expand Down
46 changes: 40 additions & 6 deletions apps/gradio/src/verification_app/form_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@

from verification_core import FieldDefinition, FieldKind, InputSchema, load_input_schema

from .form_presentation import (
SECTION_DESCRIPTIONS,
SECTION_ORDER,
group_description,
present_field,
)


@dataclass(frozen=True, slots=True)
class FormField:
definition: FieldDefinition
visible: bool
label: str
description: str
choices: tuple[Any, ...]

@property
def key(self) -> str:
Expand All @@ -20,12 +30,14 @@ def key(self) -> str:
class FormGroup:
name: str
fields: tuple[FormField, ...]
description: str = ""


@dataclass(frozen=True, slots=True)
class FormSection:
name: str
groups: tuple[FormGroup, ...]
description: str = ""


@dataclass(frozen=True, slots=True)
Expand Down Expand Up @@ -72,24 +84,46 @@ def load_form_model(
resolved_values.update(values)
visibility = _visibility(schema, resolved_values)

presented_fields = tuple(
(field, present_field(field))
for field in schema.fields
)
sections: list[FormSection] = []
for section_name in dict.fromkeys(field.section for field in schema.fields):
section_fields = tuple(field for field in schema.fields if field.section == section_name)
for section_name in SECTION_ORDER:
section_fields = tuple(
(field, presentation)
for field, presentation in presented_fields
if presentation.section == section_name
)
if not section_fields:
continue
groups = tuple(
FormGroup(
name=group_name,
fields=tuple(
FormField(
definition=field,
visible=visibility[field.key],
label=presentation.label,
description=presentation.description,
choices=presentation.choices,
)
for field in section_fields
if field.group == group_name
for field, presentation in section_fields
if presentation.group == group_name
),
description=group_description(group_name),
)
for group_name in dict.fromkeys(
presentation.group for _, presentation in section_fields
)
)
sections.append(
FormSection(
name=section_name,
groups=groups,
description=SECTION_DESCRIPTIONS.get(section_name, ""),
)
for group_name in dict.fromkeys(field.group for field in section_fields)
)
sections.append(FormSection(name=section_name, groups=groups))
return FormModel(schema=schema, sections=tuple(sections))


Expand Down
Loading