Optymalizacja soneta-form-xml skill

This commit is contained in:
Marcin Wojas
2026-03-05 15:31:31 +01:00
parent 3f5d9a795e
commit 898fd6a98d
43 changed files with 5677 additions and 525 deletions
@@ -0,0 +1,187 @@
{
"metadata": {
"skill_name": "soneta-form-xml",
"skill_path": "/Users/marcin/d/Skills/soneta-form-xml",
"executor_model": "claude-sonnet-4-6",
"timestamp": "2026-03-05T12:00:00Z",
"evals_run": ["pageform-z-gridem", "viewform-lista", "warunkowa-widocznosc"],
"runs_per_configuration": 1
},
"runs": [
{
"eval_id": 1,
"eval_name": "pageform-z-gridem",
"configuration": "with_skill",
"run_number": 1,
"result": {
"pass_rate": 1.0,
"passed": 8,
"failed": 0,
"total": 8,
"time_seconds": 37.8,
"tokens": 32707,
"tool_calls": 9,
"errors": 0
},
"expectations": [
{"text": "Plik zaczyna się od <?xml...?>", "passed": true, "evidence": "Poprawna deklaracja XML"},
{"text": "DataForm ma Priority=\"10\"", "passed": true, "evidence": "Atrybut w elemencie root"},
{"text": "Page ma DataContext=\"{DataSource}\"", "passed": true, "evidence": "Linia 8"},
{"text": "Trzy grupy: Dane podstawowe, Warunki, Pozycje", "passed": true, "evidence": "Linie 10,17,30"},
{"text": "Układ Row>Stack w grupie Warunki", "passed": true, "evidence": "Linie 18-28"},
{"text": "Grid: IsToolbarVisible, EditInPlace, NewInPlace", "passed": true, "evidence": "Linie 31-35"},
{"text": "Footer=Sum na Ilosc i Wartosc", "passed": true, "evidence": "Linie 38,40"},
{"text": "Binding {NazwaPola}", "passed": true, "evidence": "EditValue we wszystkich polach"}
]
},
{
"eval_id": 1,
"eval_name": "pageform-z-gridem",
"configuration": "without_skill",
"run_number": 1,
"result": {
"pass_rate": 0.5,
"passed": 4,
"failed": 4,
"total": 8,
"time_seconds": 17.7,
"tokens": 4263,
"tool_calls": 3,
"errors": 0
},
"expectations": [
{"text": "Plik zaczyna się od <?xml...?>", "passed": true, "evidence": "Poprawna deklaracja"},
{"text": "DataForm ma Priority=\"10\"", "passed": false, "evidence": "Używa <PageForm.Priority> zamiast atrybutu"},
{"text": "Page ma DataContext=\"{DataSource}\"", "passed": false, "evidence": "Brak Page i DataContext"},
{"text": "Trzy grupy: Dane podstawowe, Warunki, Pozycje", "passed": false, "evidence": "Grupy z Name= zamiast CaptionHtml="},
{"text": "Układ Row>Stack w grupie Warunki", "passed": true, "evidence": "Row>Stack obecne"},
{"text": "Grid: IsToolbarVisible, EditInPlace, NewInPlace", "passed": true, "evidence": "Atrybuty obecne"},
{"text": "Footer=Sum na Ilosc i Wartosc", "passed": true, "evidence": "Footer=Sum na Column"},
{"text": "Binding {NazwaPola}", "passed": false, "evidence": "Brak EditValue — używa Name= na Control"}
]
},
{
"eval_id": 2,
"eval_name": "viewform-lista",
"configuration": "with_skill",
"run_number": 1,
"result": {
"pass_rate": 1.0,
"passed": 7,
"failed": 0,
"total": 7,
"time_seconds": 38.4,
"tokens": 34304,
"tool_calls": 10,
"errors": 0
},
"expectations": [
{"text": "Poprawna deklaracja XML", "passed": true, "evidence": "Linia 1"},
{"text": "xmlns='http://www.enova.pl/schema/form.xsd'", "passed": true, "evidence": "Poprawny namespace"},
{"text": "Element Grid", "passed": true, "evidence": "Grid z ViewType=Folder"},
{"text": "OrderBy='NazwiskoImie'", "passed": true, "evidence": "Linia 12"},
{"text": "IsToolbarVisible i IsFilterRowVisible", "passed": true, "evidence": "Linie 10-11"},
{"text": "6 pól: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia", "passed": true, "evidence": "Linie 13-18"},
{"text": "Dzial ma Width='*'", "passed": true, "evidence": "Linia 16"}
]
},
{
"eval_id": 2,
"eval_name": "viewform-lista",
"configuration": "without_skill",
"run_number": 1,
"result": {
"pass_rate": 0.43,
"passed": 3,
"failed": 4,
"total": 7,
"time_seconds": 13.9,
"tokens": 3821,
"tool_calls": 3,
"errors": 0
},
"expectations": [
{"text": "Poprawna deklaracja XML", "passed": true, "evidence": "Linia 1"},
{"text": "xmlns='http://www.enova.pl/schema/form.xsd'", "passed": false, "evidence": "Błędny namespace: http://www.soneta.pl/viewform"},
{"text": "Element Grid", "passed": false, "evidence": "<grid> lowercase — błędna nazwa elementu"},
{"text": "OrderBy='NazwiskoImie'", "passed": false, "evidence": "defaultsort= zamiast OrderBy="},
{"text": "IsToolbarVisible i IsFilterRowVisible", "passed": false, "evidence": "Atrybuty lowercase — błędna składnia"},
{"text": "6 pól: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia", "passed": true, "evidence": "<column> z właściwymi nazwami"},
{"text": "Dzial ma Width='*'", "passed": true, "evidence": "width='*' na Dzial"}
]
},
{
"eval_id": 3,
"eval_name": "warunkowa-widocznosc",
"configuration": "with_skill",
"run_number": 1,
"result": {
"pass_rate": 1.0,
"passed": 5,
"failed": 0,
"total": 5,
"time_seconds": 72.7,
"tokens": 37262,
"tool_calls": 10,
"errors": 0
},
"expectations": [
{"text": "Visibility='{?Pole=Wartość}'", "passed": true, "evidence": "Linia 30: {?TypKlienta=Korporacyjny}"},
{"text": "OR: {?Status=Premium or Status=VIP}", "passed": true, "evidence": "Linia 48"},
{"text": "Negacja: {?!Status=Aktywny}", "passed": true, "evidence": "Linia 65"},
{"text": "Class='Collapsable' na Group", "passed": true, "evidence": "Linia 109"},
{"text": "Renderable dla licencji", "passed": true, "evidence": "Linia 110: Renderable='{Licence.HAN}'"}
]
},
{
"eval_id": 3,
"eval_name": "warunkowa-widocznosc",
"configuration": "without_skill",
"run_number": 1,
"result": {
"pass_rate": 0.0,
"passed": 0,
"failed": 5,
"total": 5,
"time_seconds": 50.3,
"tokens": 5896,
"tool_calls": 3,
"errors": 0
},
"expectations": [
{"text": "Visibility='{?Pole=Wartość}'", "passed": false, "evidence": "RowCondition= (nie istnieje) zamiast Visibility"},
{"text": "OR: {?Status=Premium or Status=VIP}", "passed": false, "evidence": "SQL-like OR syntax zamiast {?... or ...}"},
{"text": "Negacja: {?!Status=Aktywny}", "passed": false, "evidence": "NOT (...) zamiast {?!...}"},
{"text": "Class='Collapsable' na Group", "passed": false, "evidence": "Collapsable='True' atrybut zamiast Class="},
{"text": "Renderable dla licencji", "passed": false, "evidence": "Session.Features.IsAvailable() — błędna składnia"}
]
}
],
"run_summary": {
"with_skill": {
"pass_rate": {"mean": 1.0, "stddev": 0.0, "min": 1.0, "max": 1.0},
"time_seconds": {"mean": 49.6, "stddev": 18.1, "min": 37.8, "max": 72.7},
"tokens": {"mean": 34758, "stddev": 2284, "min": 32707, "max": 37262}
},
"without_skill": {
"pass_rate": {"mean": 0.31, "stddev": 0.22, "min": 0.0, "max": 0.5},
"time_seconds": {"mean": 27.3, "stddev": 19.1, "min": 13.9, "max": 50.3},
"tokens": {"mean": 4660, "stddev": 1080, "min": 3821, "max": 5896}
},
"delta": {
"pass_rate": "+0.69",
"time_seconds": "+22.3",
"tokens": "+30098"
}
},
"notes": [
"Skill daje 100% pass rate we wszystkich 3 ewalach vs 31% bez skilla — poprawa o 69 punktów procentowych",
"Bez skilla model halucynuje nieistniejące elementy XML: <PageForm>, <Control>, <viewform>, <Edit>, RowCondition=",
"Najsłabszy wynik bez skilla: warunkowa-widocznosc (0%) — model zna pojęcia ale ma zupełnie błędną składnię",
"Skill kosztuje więcej tokenów (30k vs 4.7k) i czasu (50s vs 27s) — uzasadnione biorąc pod uwagę czytanie SKILL.md i ELEMENTS.md",
"Asercja 'Poprawna deklaracja XML' zawsze przechodzi — mało dyskryminująca, ale utrzymana dla kompletności"
]
}
@@ -0,0 +1,15 @@
{
"eval_id": 1,
"eval_name": "pageform-z-gridem",
"prompt": "Utwórz plik Zamowienie.Szczegoly.pageform.xml dla platformy enova365. Zakładka powinna zawierać:\n- Grupę 'Dane podstawowe' z polami: Numer (szerokość 20), DataZlozenia (szerokość 15), Kontrahent (szerokość *), Status (szerokość 15)\n- Grupę 'Warunki' z układem dwukolumnowym (Row > Stack): lewa kolumna ma SposobDostawy (20) i TerminDostawy (15), prawa kolumna ma SposobZaplaty (20) i TerminZaplaty (15)\n- Grupę 'Pozycje' z Grid (IsToolbarVisible, EditInPlace, NewInPlace) i kolumnami: Lp (5), Towar (*), Ilosc (10) z Footer=Sum, CenaJednostkowa (18), Wartosc (15) z Footer=Sum\nPriority zakładki: 10.",
"assertions": [
"Plik zaczyna się od <?xml version=\"1.0\" encoding=\"utf-8\"?>",
"Element DataForm ma atrybut Priority=\"10\"",
"Element Page ma atrybut DataContext=\"{DataSource}\"",
"Są trzy elementy Group: 'Dane podstawowe', 'Warunki', 'Pozycje'",
"Układ dwukolumnowy w grupie Warunki używa Row zawierającego Stack",
"Element Grid ma atrybuty IsToolbarVisible=\"true\", EditInPlace=\"true\", NewInPlace=\"true\"",
"Pola Ilosc i Wartosc w Grid mają atrybut Footer=\"Sum\"",
"Binding pól używa składni {NazwaPola} w cudzysłowie"
]
}
@@ -0,0 +1,50 @@
{
"expectations": [
{
"text": "Plik zaczyna się od <?xml version=\"1.0\" encoding=\"utf-8\"?>",
"passed": true,
"evidence": "Linia 1: <?xml version=\"1.0\" encoding=\"utf-8\"?>"
},
{
"text": "Element DataForm ma atrybut Priority=\"10\"",
"passed": true,
"evidence": "Linia 6: Priority=\"10\" w elemencie DataForm"
},
{
"text": "Element Page ma atrybut DataContext=\"{DataSource}\"",
"passed": true,
"evidence": "Linia 8: <Page CaptionHtml=\"Szczegoly\" DataContext=\"{DataSource}\">"
},
{
"text": "Są trzy elementy Group: 'Dane podstawowe', 'Warunki', 'Pozycje'",
"passed": true,
"evidence": "Linie 10, 17, 30: Group CaptionHtml=\"Dane podstawowe\", \"Warunki\", \"Pozycje\""
},
{
"text": "Układ dwukolumnowy w grupie Warunki używa Row zawierającego Stack",
"passed": true,
"evidence": "Linie 18-28: <Row><Stack>SposobDostawy, TerminDostawy</Stack><Stack>SposobZaplaty, TerminZaplaty</Stack></Row>"
},
{
"text": "Element Grid ma atrybuty IsToolbarVisible=\"true\", EditInPlace=\"true\", NewInPlace=\"true\"",
"passed": true,
"evidence": "Linie 31-35: Grid z IsToolbarVisible=\"true\" EditInPlace=\"true\" NewInPlace=\"true\""
},
{
"text": "Pola Ilosc i Wartosc w Grid mają atrybut Footer=\"Sum\"",
"passed": true,
"evidence": "Linia 38: Footer=\"Sum\" na Ilosc; Linia 40: Footer=\"Sum\" na Wartosc"
},
{
"text": "Binding pól używa składni {NazwaPola} w cudzysłowie",
"passed": true,
"evidence": "EditValue=\"{Numer}\", EditValue=\"{DataZlozenia}\" itp. — poprawna składnia"
}
],
"summary": {
"passed": 8,
"failed": 0,
"total": 8,
"pass_rate": 1.0
}
}
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
Priority="10">
<Page CaptionHtml="Szczegoly" DataContext="{DataSource}">
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Numer" Width="20" EditValue="{Numer}" />
<Field CaptionHtml="DataZlozenia" Width="15" EditValue="{DataZlozenia}" />
<Field CaptionHtml="Kontrahent" Width="*" EditValue="{Kontrahent}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Group>
<Group CaptionHtml="Warunki">
<Row>
<Stack>
<Field CaptionHtml="SposobDostawy" Width="20" EditValue="{SposobDostawy}" />
<Field CaptionHtml="TerminDostawy" Width="15" EditValue="{TerminDostawy}" />
</Stack>
<Stack>
<Field CaptionHtml="SposobZaplaty" Width="20" EditValue="{SposobZaplaty}" />
<Field CaptionHtml="TerminZaplaty" Width="15" EditValue="{TerminZaplaty}" />
</Stack>
</Row>
</Group>
<Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*"
EditValue="{Pozycje}"
IsToolbarVisible="true"
EditInPlace="true"
NewInPlace="true">
<Field CaptionHtml="Lp" Width="5" EditValue="{Lp}" />
<Field CaptionHtml="Towar" Width="*" EditValue="{Towar}" />
<Field CaptionHtml="Ilosc" Width="10" EditValue="{Ilosc}" Footer="Sum" />
<Field CaptionHtml="CenaJednostkowa" Width="18" EditValue="{CenaJednostkowa}" />
<Field CaptionHtml="Wartosc" Width="15" EditValue="{Wartosc}" Footer="Sum" />
</Grid>
</Group>
</Page>
</DataForm>
@@ -0,0 +1,4 @@
{
"files_created": ["Zamowienie.Szczegoly.pageform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 32707,
"duration_ms": 37772,
"total_duration_seconds": 37.8
}
@@ -0,0 +1,50 @@
{
"expectations": [
{
"text": "Plik zaczyna się od <?xml version=\"1.0\" encoding=\"utf-8\"?>",
"passed": true,
"evidence": "Linia 1: <?xml version=\"1.0\" encoding=\"utf-8\"?>"
},
{
"text": "Element DataForm ma atrybut Priority=\"10\"",
"passed": false,
"evidence": "Użyto <PageForm> zamiast <DataForm>, a Priority jako child element <PageForm.Priority>10</PageForm.Priority> zamiast atrybutu"
},
{
"text": "Element Page ma atrybut DataContext=\"{DataSource}\"",
"passed": false,
"evidence": "Brak elementu Page i DataContext. Użyto <PageForm.Groups> zamiast <Page DataContext=...>"
},
{
"text": "Są trzy elementy Group: 'Dane podstawowe', 'Warunki', 'Pozycje'",
"passed": false,
"evidence": "Grupy istnieją ale z atrybutem Name zamiast CaptionHtml i wewnątrz błędnej struktury <PageForm.Groups>"
},
{
"text": "Układ dwukolumnowy w grupie Warunki używa Row zawierającego Stack",
"passed": true,
"evidence": "Linie 15-25: <Row><Stack>...</Stack><Stack>...</Stack></Row> — poprawny layout"
},
{
"text": "Element Grid ma atrybuty IsToolbarVisible=\"true\", EditInPlace=\"true\", NewInPlace=\"true\"",
"passed": true,
"evidence": "Linia 29: Grid z IsToolbarVisible=\"true\" EditInPlace=\"true\" NewInPlace=\"true\""
},
{
"text": "Pola Ilosc i Wartosc w Grid mają atrybut Footer=\"Sum\"",
"passed": true,
"evidence": "Linie 33, 35: Footer=\"Sum\" na Column Ilosc i Wartosc"
},
{
"text": "Binding pól używa składni {NazwaPola} w cudzysłowie",
"passed": false,
"evidence": "Brak atrybutu EditValue. Używa <Control Name=\"Numer\" Width=\"20\" /> bez bindowania danych"
}
],
"summary": {
"passed": 4,
"failed": 4,
"total": 8,
"pass_rate": 0.5
}
}
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<PageForm xmlns="http://www.enova.pl/schemas/form">
<PageForm.Priority>10</PageForm.Priority>
<PageForm.Groups>
<Group Name="Dane podstawowe">
<Group.Controls>
<Control Name="Numer" Width="20" />
<Control Name="DataZlozenia" Width="15" />
<Control Name="Kontrahent" Width="*" />
<Control Name="Status" Width="15" />
</Group.Controls>
</Group>
<Group Name="Warunki">
<Group.Controls>
<Row>
<Stack>
<Control Name="SposobDostawy" Width="20" />
<Control Name="TerminDostawy" Width="15" />
</Stack>
<Stack>
<Control Name="SposobZaplaty" Width="20" />
<Control Name="TerminZaplaty" Width="15" />
</Stack>
</Row>
</Group.Controls>
</Group>
<Group Name="Pozycje">
<Group.Controls>
<Grid IsToolbarVisible="true" EditInPlace="true" NewInPlace="true">
<Grid.Columns>
<Column Name="Lp" Width="5" />
<Column Name="Towar" Width="*" />
<Column Name="Ilosc" Width="10" Footer="Sum" />
<Column Name="CenaJednostkowa" Width="18" />
<Column Name="Wartosc" Width="15" Footer="Sum" />
</Grid.Columns>
</Grid>
</Group.Controls>
</Group>
</PageForm.Groups>
</PageForm>
@@ -0,0 +1,4 @@
{
"files_created": ["Zamowienie.Szczegoly.pageform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 4263,
"duration_ms": 17660,
"total_duration_seconds": 17.7
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
{
"eval_id": 2,
"eval_name": "viewform-lista",
"prompt": "Stwórz plik Pracownicy.viewform.xml dla widoku listy pracowników w enova365. Widok listy powinien zawierać kolumny: Kod (8), NazwiskoImie (30), NumerPracownika (20), Dzial (*), Stanowisko (20), DataZatrudnienia (15). Domyślne sortowanie po NazwiskoImie. Dodaj IsToolbarVisible i IsFilterRowVisible. Zachowaj właściwą strukturę pliku viewform.xml.",
"assertions": [
"Plik ma poprawną deklarację XML",
"Element DataForm ma xmlns=\"http://www.enova.pl/schema/form.xsd\"",
"Jest element Grid z EditValue lub bez (dla widoku listy)",
"Grid ma atrybut OrderBy=\"NazwiskoImie\"",
"Grid ma IsToolbarVisible=\"true\" i IsFilterRowVisible=\"true\"",
"Są kolumny Field dla: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia",
"Pole Dzial ma Width=\"*\""
]
}
@@ -0,0 +1,45 @@
{
"expectations": [
{
"text": "Plik ma poprawną deklarację XML",
"passed": true,
"evidence": "Linia 1: <?xml version=\"1.0\" encoding=\"utf-8\"?>"
},
{
"text": "Element DataForm ma xmlns=\"http://www.enova.pl/schema/form.xsd\"",
"passed": true,
"evidence": "Linia 5: xmlns=\"http://www.enova.pl/schema/form.xsd\" — poprawny namespace"
},
{
"text": "Jest element Grid z EditValue lub bez (dla widoku listy)",
"passed": true,
"evidence": "Linia 9: <Grid Width=\"*\" Height=\"*\" IsToolbarVisible=\"true\" ...>"
},
{
"text": "Grid ma atrybut OrderBy=\"NazwiskoImie\"",
"passed": true,
"evidence": "Linia 12: OrderBy=\"NazwiskoImie\""
},
{
"text": "Grid ma IsToolbarVisible=\"true\" i IsFilterRowVisible=\"true\"",
"passed": true,
"evidence": "Linie 10-11: IsToolbarVisible=\"true\" IsFilterRowVisible=\"true\""
},
{
"text": "Są kolumny Field dla: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia",
"passed": true,
"evidence": "Linie 13-18: 6 elementów Field z EditValue dla każdego z wymienionych pól"
},
{
"text": "Pole Dzial ma Width=\"*\"",
"passed": true,
"evidence": "Linia 16: <Field CaptionHtml=\"Dział\" Width=\"*\" EditValue=\"{Dzial}\" />"
}
],
"summary": {
"passed": 7,
"failed": 0,
"total": 7,
"pass_rate": 1.0
}
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
ViewType="Folder"
Mode="Folder">
<Grid Width="*" Height="*"
IsToolbarVisible="true"
IsFilterRowVisible="true"
OrderBy="NazwiskoImie">
<Field CaptionHtml="Kod" Width="8" EditValue="{Kod}" />
<Field CaptionHtml="Nazwisko i imię" Width="30" EditValue="{NazwiskoImie}" />
<Field CaptionHtml="Numer pracownika" Width="20" EditValue="{NumerPracownika}" />
<Field CaptionHtml="Dział" Width="*" EditValue="{Dzial}" />
<Field CaptionHtml="Stanowisko" Width="20" EditValue="{Stanowisko}" />
<Field CaptionHtml="Data zatrudnienia" Width="15" EditValue="{DataZatrudnienia}" />
</Grid>
</DataForm>
@@ -0,0 +1,4 @@
{
"files_created": ["Pracownicy.viewform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 34304,
"duration_ms": 38406,
"total_duration_seconds": 38.4
}
@@ -0,0 +1,45 @@
{
"expectations": [
{
"text": "Plik ma poprawną deklarację XML",
"passed": true,
"evidence": "Linia 1: <?xml version=\"1.0\" encoding=\"utf-8\"?>"
},
{
"text": "Element DataForm ma xmlns=\"http://www.enova.pl/schema/form.xsd\"",
"passed": false,
"evidence": "Użyto <viewform xmlns=\"http://www.soneta.pl/viewform\"> zamiast <DataForm xmlns=\"http://www.enova.pl/schema/form.xsd\">"
},
{
"text": "Jest element Grid z EditValue lub bez (dla widoku listy)",
"passed": false,
"evidence": "Użyto <grid> (lowercase) zamiast <Grid>. Elementy XML są case-sensitive — to błąd."
},
{
"text": "Grid ma atrybut OrderBy=\"NazwiskoImie\"",
"passed": false,
"evidence": "Użyto defaultsort=\"NazwiskoImie\" zamiast OrderBy=\"NazwiskoImie\""
},
{
"text": "Grid ma IsToolbarVisible=\"true\" i IsFilterRowVisible=\"true\"",
"passed": false,
"evidence": "Użyto istoolbarvisible=\"true\" isfilterrowvisible=\"true\" (lowercase) zamiast PascalCase"
},
{
"text": "Są kolumny Field dla: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia",
"passed": true,
"evidence": "6 elementów <column> z właściwymi nazwami — poprawne pola, choć element to <column> nie <Field>"
},
{
"text": "Pole Dzial ma Width=\"*\"",
"passed": true,
"evidence": "Linia 8: <column name=\"Dzial\" width=\"*\" /> — prawidłowe *"
}
],
"summary": {
"passed": 3,
"failed": 4,
"total": 7,
"pass_rate": 0.43
}
}
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<viewform xmlns="http://www.soneta.pl/viewform">
<grid name="Pracownicy" defaultsort="NazwiskoImie" istoolbarvisible="true" isfilterrowvisible="true">
<columns>
<column name="Kod" width="8" />
<column name="NazwiskoImie" width="30" />
<column name="NumerPracownika" width="20" />
<column name="Dzial" width="*" />
<column name="Stanowisko" width="20" />
<column name="DataZatrudnienia" width="15" />
</columns>
</grid>
</viewform>
@@ -0,0 +1,4 @@
{
"files_created": ["Pracownicy.viewform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 3821,
"duration_ms": 13888,
"total_duration_seconds": 13.9
}
@@ -0,0 +1,12 @@
{
"eval_id": 3,
"eval_name": "warunkowa-widocznosc",
"prompt": "Pokaż jak w pageform.xml enova365 zastosować warunkową widoczność pól używając wyrażeń RowCondition. Stwórz przykładowy plik Kontrahent.Kredyt.pageform.xml z następującymi wzorcami:\n1. Pole 'LimitKredytu' widoczne tylko gdy TypKlienta='Korporacyjny'\n2. Pole 'WarunkiSpecjalne' widoczne gdy Status='Premium' LUB Status='VIP'\n3. Pole 'OstrzezenieBranze' widoczne gdy NIE Status='Aktywny'\n4. Przycisk Command widoczny gdy ObrotyRoczne > 0 (użyj WorkCondition lub własność bool)\n5. Cała Grupa 'Dane zaawansowane' zwijalna (Collapsable) z Renderable uzależnionym od licencji",
"assertions": [
"Użyto składni Visibility=\"{?Pole=Wartość}\" dla warunku równości",
"Użyto składni OR dla wielu wartości: {?Status=Premium or Status=VIP}",
"Użyto negacji: {?!Status=Aktywny}",
"Klasa Collapsable jest zastosowana do grupy",
"Atrybut Renderable jest użyty dla warunku licencji"
]
}
@@ -0,0 +1,35 @@
{
"expectations": [
{
"text": "Użyto składni Visibility=\"{?Pole=Wartość}\" dla warunku równości",
"passed": true,
"evidence": "Linia 30: Visibility=\"{?TypKlienta=Korporacyjny}\" — poprawna składnia RowCondition"
},
{
"text": "Użyto składni OR dla wielu wartości: {?Status=Premium or Status=VIP}",
"passed": true,
"evidence": "Linia 48: Visibility=\"{?Status=Premium or Status=VIP}\" — poprawny operator or"
},
{
"text": "Użyto negacji: {?!Status=Aktywny}",
"passed": true,
"evidence": "Linia 65: Visibility=\"{?!Status=Aktywny}\" — poprawna negacja z !"
},
{
"text": "Klasa Collapsable jest zastosowana do grupy",
"passed": true,
"evidence": "Linia 109: <Group CaptionHtml=\"Dane zaawansowane\" Class=\"Collapsable\" ...>"
},
{
"text": "Atrybut Renderable jest użyty dla warunku licencji",
"passed": true,
"evidence": "Linia 110: Renderable=\"{Licence.HAN}\" — licencja HAN jako warunek renderowania"
}
],
"summary": {
"passed": 5,
"failed": 0,
"total": 5,
"pass_rate": 1.0
}
}
@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Zakładka: Kredyt kontrahenta
Plik: Kontrahent.Kredyt.pageform.xml
Demonstruje wzorce warunkowej widoczności przy użyciu:
- RowCondition ({?...}) dla porównań wartości pól
- Visibility z bindowaniem do właściwości bool
- Renderable uzależniony od licencji (liczony raz przy logowaniu)
- Class="Collapsable" dla zwijanych grup
-->
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
Priority="30">
<Page CaptionHtml="Kredyt" DataContext="{DataSource}">
<!-- =====================================================================
WZORZEC 1: Pole widoczne tylko gdy TypKlienta = 'Korporacyjny'
Używamy wyrażenia RowCondition: {?TypKlienta=Korporacyjny}
Pole LimitKredytu jest zwijane (Collapsed) gdy warunek nie jest spełniony.
====================================================================== -->
<Group CaptionHtml="Limit kredytu">
<Field CaptionHtml="Typ klienta" Width="20" EditValue="{TypKlienta}" />
<Field CaptionHtml="Limit kredytu"
Width="18"
EditValue="{LimitKredytu}"
Visibility="{?TypKlienta=Korporacyjny}" />
<Field CaptionHtml="Waluta limitu"
Width="10"
EditValue="{WalutaLimitu}"
Visibility="{?TypKlienta=Korporacyjny}" />
</Group>
<!-- =====================================================================
WZORZEC 2: Pole widoczne gdy Status = 'Premium' LUB Status = 'VIP'
Używamy operatora 'or' w wyrażeniu RowCondition.
Składnia: {?Pole=Wartość1 or Pole=Wartość2}
====================================================================== -->
<Group CaptionHtml="Warunki specjalne">
<Field CaptionHtml="Status klienta" Width="20" EditValue="{Status}" />
<Field CaptionHtml="Warunki specjalne"
Width="*"
Height="3"
EditValue="{WarunkiSpecjalne}"
Visibility="{?Status=Premium or Status=VIP}" />
<Field CaptionHtml="Opiekun VIP"
Width="30"
EditValue="{OpiekunVIP}"
Visibility="{?Status=Premium or Status=VIP}" />
</Group>
<!-- =====================================================================
WZORZEC 3: Pole widoczne gdy NIE Status = 'Aktywny'
Używamy negacji w wyrażeniu RowCondition: {?!Status=Aktywny}
Ostrzeżenie o branży pojawia się tylko dla nieaktywnych kontrahentów.
====================================================================== -->
<Group CaptionHtml="Ostrzeżenia">
<Field CaptionHtml="Ostrzezenie branze"
Width="*"
EditValue="{OstrzezenieBranzy}"
Class="WarningLabel"
Visibility="{?!Status=Aktywny}" />
<Field CaptionHtml="Powod nieaktywnosci"
Width="*"
EditValue="{PowodNieaktywnosci}"
Visibility="{?!Status=Aktywny}" />
</Group>
<!-- =====================================================================
WZORZEC 4: Przycisk Command widoczny gdy ObrotyRoczne > 0
Dla porównań numerycznych (> < >= <=) RowCondition nie obsługuje
operatorów arytmetycznych bezpośrednio — zamiast tego:
a) Używamy właściwości bool z logiki biznesowej: {MaObrotyRoczne}
(właściwość C# zwracająca: ObrotyRoczne > 0)
b) Alternatywnie: worker z właściwością bool: {Workers.KredytWorker.MaObroty}
====================================================================== -->
<Group CaptionHtml="Analiza obrotow">
<Row>
<Field CaptionHtml="Obroty roczne" Width="18" EditValue="{ObrotyRoczne}" />
<Field CaptionHtml="Obroty miesieczne" Width="18" EditValue="{ObrotyMiesieczne}" />
<Gap Width="*" />
<!-- Przycisk widoczny gdy ObrotyRoczne > 0 (via właściwość bool MaObrotyRoczne) -->
<Command CaptionHtml="Analiza kredytowa"
Width="18"
MethodName="WykonajAnalize"
CommandStyle="Important"
Visibility="{MaObrotyRoczne}" />
<!-- Alternatywny wzorzec: worker z właściwością bool -->
<Command CaptionHtml="Raport obrotow"
Width="16"
MethodName="GenerujRaport"
DataContext="{new KredytExtender}"
Visibility="{Workers.KredytWorker.MaObroty}" />
</Row>
</Group>
<!-- =====================================================================
WZORZEC 5: Grupa zwijalna (Collapsable) z Renderable uzależnionym
od licencji.
- Class="Collapsable" — użytkownik może zwijać/rozwijać grupę
- Renderable="{Licence.HAN}" — renderowana tylko gdy licencja HAN
aktywna (wartość liczona RAZ przy logowaniu operatora, optymalne
dla warunków środowiskowych i licencyjnych)
====================================================================== -->
<Group CaptionHtml="Dane zaawansowane"
Class="Collapsable"
Renderable="{Licence.HAN}">
<Row>
<Stack LabelWidth="20">
<Field CaptionHtml="Scoring kredytowy" Width="10" EditValue="{ScoringKredytowy}" />
<Field CaptionHtml="Kategoria ryzyka" Width="20" EditValue="{KategoriaRyzyka}" />
<Field CaptionHtml="Data ostatniej oceny" Width="15" EditValue="{DataOstOceny}" />
</Stack>
<Stack LabelWidth="20">
<Field CaptionHtml="Maksymalna ekspozycja" Width="18" EditValue="{MaksEkspozycja}" />
<Field CaptionHtml="Ubezpieczenie kredytu" Width="8" EditValue="{UbezpieczenieKredytu}" />
<Field CaptionHtml="Firma ubezpieczeniowa" Width="25" EditValue="{FirmaUbezpieczeniowa}"
Visibility="{UbezpieczenieKredytu}" />
</Stack>
</Row>
<Field CaptionHtml="Uwagi analityka" Width="*" Height="3" EditValue="{UwagiAnalityka}" />
</Group>
</Page>
</DataForm>
@@ -0,0 +1,4 @@
{
"files_created": ["Kontrahent.Kredyt.pageform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 37262,
"duration_ms": 72689,
"total_duration_seconds": 72.7
}
@@ -0,0 +1,35 @@
{
"expectations": [
{
"text": "Użyto składni Visibility=\"{?Pole=Wartość}\" dla warunku równości",
"passed": false,
"evidence": "Użyto RowCondition=\"Kontrahent.TypKlienta = 'Korporacyjny'\" (nie istniejący atrybut) zamiast Visibility=\"{?...}\""
},
{
"text": "Użyto składni OR dla wielu wartości: {?Status=Premium or Status=VIP}",
"passed": false,
"evidence": "Użyto RowCondition=\"... OR ...\" (SQL-like syntax) zamiast Visibility=\"{?... or ...}\""
},
{
"text": "Użyto negacji: {?!Status=Aktywny}",
"passed": false,
"evidence": "Użyto RowCondition=\"NOT (...)\" zamiast Visibility=\"{?!...}\""
},
{
"text": "Klasa Collapsable jest zastosowana do grupy",
"passed": false,
"evidence": "Użyto Collapsable=\"True\" jako atrybut zamiast Class=\"Collapsable\""
},
{
"text": "Atrybut Renderable jest użyty dla warunku licencji",
"passed": false,
"evidence": "Użyto Renderable=\"Session.Features.IsAvailable(...)\" — błędna składnia wyrażenia, nie jest to format {Licence.X}"
}
],
"summary": {
"passed": 0,
"failed": 5,
"total": 5,
"pass_rate": 0.0
}
}
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Kontrahent.Kredyt.pageform.xml
Przykład warunkowej widoczności pól w enova365 za pomocą wyrażeń RowCondition/Renderable.
Obiekt biznesowy: Kontrahent (moduł Handel)
-->
<Form
xmlns="http://www.enova.pl/schema/Form.xsd"
Caption="Kredyt kontrahenta"
Domain="Handel"
Class="Kontrahent"
View="Kredyt">
<!-- ============================================================
ŹRÓDŁO DANYCH
============================================================ -->
<DataSources>
<DataSource Name="Kontrahent" Class="Kontrahent" />
</DataSources>
<!-- ============================================================
KONTROLKI / LAYOUT
============================================================ -->
<Controls>
<!-- ──────────────────────────────────────────────────────────
1. Pole 'LimitKredytu' widoczne tylko gdy TypKlienta = 'Korporacyjny'
Użycie atrybutu RowCondition z wyrażeniem porównania wartości enumeracji/stringa.
────────────────────────────────────────────────────────── -->
<Edit
Name="LimitKredytu"
Caption="Limit kredytu"
Source="Kontrahent.LimitKredytu"
RowCondition="Kontrahent.TypKlienta = 'Korporacyjny'"
Visible="True" />
<!--
Uwaga: atrybut RowCondition przyjmuje wyrażenie ewaluowane przez silnik
wyrażeń Soneta (podobne do SQL WHERE). Gdy warunek jest False, wiersz
(kontrolka) jest ukrywany odpowiednik Visible=False ustawianego
dynamicznie w runtime.
-->
<!-- ──────────────────────────────────────────────────────────
2. Pole 'WarunkiSpecjalne' widoczne gdy Status = 'Premium' LUB Status = 'VIP'
Łączenie warunków operatorem OR (w Soneta: słowo kluczowe OR lub ||).
────────────────────────────────────────────────────────── -->
<Edit
Name="WarunkiSpecjalne"
Caption="Warunki specjalne"
Source="Kontrahent.WarunkiSpecjalne"
RowCondition="Kontrahent.Status = 'Premium' OR Kontrahent.Status = 'VIP'"
Visible="True" />
<!--
Alternatywna forma z nawiasami (zalecana dla czytelności):
RowCondition="(Kontrahent.Status = 'Premium') OR (Kontrahent.Status = 'VIP')"
-->
<!-- ──────────────────────────────────────────────────────────
3. Pole 'OstrzezenieBranze' widoczne gdy NIE Status = 'Aktywny'
Negacja warunku operator NOT lub <> (różne od).
────────────────────────────────────────────────────────── -->
<Edit
Name="OstrzezenieBranze"
Caption="Ostrzeżenie branży"
Source="Kontrahent.OstrzezenieBranze"
RowCondition="NOT (Kontrahent.Status = 'Aktywny')"
Visible="True" />
<!--
Równoważna postać z operatorem nierówności:
RowCondition="Kontrahent.Status &lt;&gt; 'Aktywny'"
W XML znaki < i > muszą być escapowane jako &lt; i &gt;.
-->
<!-- ──────────────────────────────────────────────────────────
4. Przycisk Command widoczny gdy ObrotyRoczne > 0
Dla warunków numerycznych zalecane jest mapowanie na właściwość bool
po stronie C# (np. MaObroty : bool { get => ObrotyRoczne > 0; })
i użycie jej w RowCondition lub WorkCondition.
Wariant A bezpośrednie wyrażenie numeryczne w RowCondition:
────────────────────────────────────────────────────────── -->
<Command
Name="PrzeliczKredyt"
Caption="Przelicz limit kredytu"
Action="Kontrahent.PrzeliczKredyt"
RowCondition="Kontrahent.ObrotyRoczne &gt; 0" />
<!--
Wariant B użycie właściwości bool z obiektu biznesowego (ZALECANE):
<Command
Name="PrzeliczKredyt"
Caption="Przelicz limit kredytu"
Action="Kontrahent.PrzeliczKredyt"
WorkCondition="Kontrahent.MaObroty" />
WorkCondition kontroluje AKTYWNOŚĆ (enabled) przycisku,
RowCondition kontroluje WIDOCZNOŚĆ (visible).
Można stosować oba jednocześnie.
Wariant C oba atrybuty razem:
<Command
Name="PrzeliczKredyt"
Caption="Przelicz limit kredytu"
Action="Kontrahent.PrzeliczKredyt"
RowCondition="Kontrahent.ObrotyRoczne &gt; 0"
WorkCondition="Kontrahent.MaObroty" />
-->
<!-- ──────────────────────────────────────────────────────────
5. Grupa 'Dane zaawansowane' zwijalna (Collapsable) z Renderable
uzależnionym od licencji.
Collapsable="True" pozwala użytkownikowi zwinąć grupę w UI.
Renderable wyrażenie decydujące, czy kontrolka jest w ogóle
renderowana (silniejsze niż Visible: nie zajmuje
miejsca w DOM formularza gdy False).
Tu: sprawdzamy dostępność modułu/licencji
przez wywołanie metody pomocniczej lub właściwość
sesji, np. Session.IsModuleAvailable('CRM').
────────────────────────────────────────────────────────── -->
<Group
Name="DaneZaawansowane"
Caption="Dane zaawansowane"
Collapsable="True"
Collapsed="False"
Renderable="Session.Features.IsAvailable('Kontrahent.DaneZaawansowane')">
<!-- Pola wewnątrz grupy zaawansowanej -->
<Edit
Name="KategoriaRyzyka"
Caption="Kategoria ryzyka"
Source="Kontrahent.KategoriaRyzyka" />
<Edit
Name="SkorKredytowy"
Caption="Skor kredytowy"
Source="Kontrahent.SkorKredytowy" />
<Edit
Name="DataOstatnejWeryfikacji"
Caption="Data ostatniej weryfikacji"
Source="Kontrahent.DataOstatnejWeryfikacji" />
</Group>
<!--
Uwaga do Renderable:
Gdy Renderable = False, kontrolka NIE jest tworzona w ogóle (brak węzła w drzewie UI).
Gdy Visible = False lub RowCondition = False, kontrolka istnieje, ale jest ukryta.
Renderable jest lepsze dla elementów zależnych od licencji/uprawnień,
ponieważ eliminuje element z drzewa renderowania.
Przykładowe wyrażenia Renderable uzależnione od licencji:
Renderable="Session.IsLicensed('ModulCRM')"
Renderable="Session.Rights.HasFeature('KredytKorporacyjny')"
Renderable="App.Configuration.GetBool('pokazDaneZaawansowane')"
-->
</Controls>
</Form>
@@ -0,0 +1,4 @@
{
"files_created": ["Kontrahent.Kredyt.pageform.xml"],
"errors_encountered": 0
}
@@ -0,0 +1,5 @@
{
"total_tokens": 5896,
"duration_ms": 50293,
"total_duration_seconds": 50.3
}
+57
View File
@@ -0,0 +1,57 @@
Split: 13 train, 6 test (holdout=0.4)
============================================================
Iteration 1/5
Description: Tworzenie plików form.xml opisujących formularze, zakładki i widoki UI dla platformy enova365/Soneta Enterprise. Używaj gdy użytkownik prosi o utworzenie zakładki formularza (pageform.xml), widoku listy (viewform.xml), gridform.xml, lookupform.xml lub form.xml — albo gdy pyta o składnię, elementy, bindowanie, warunkową widoczność, Appearance lub układ UI enova365. Trigger także gdy użytkownik pokazuje lub pyta o pliki XML z elementami DataForm, Page, Group, Grid, Field, Row, Stack, Flow, Command, Include dla enova365.
============================================================
Train: 15/39 correct, precision=100% recall=0% accuracy=38% (38.7s)
[FAIL] rate=0/3 expected=True: chcę zrobić Appearance warunkowe formatowanie wierszy w Grid
[FAIL] rate=0/3 expected=True: potrzebuję lookupform.xml dla wyboru Towaru z kolumnami Kod
[FAIL] rate=0/3 expected=True: jak używać DataContext i EditValue żeby wyświetlić pola zagn
[FAIL] rate=0/3 expected=True: jak ukryć pole w form.xml enova365 gdy Status nie jest równy
[FAIL] rate=0/3 expected=True: zrób mi zakładkę Towar.Ogolne.pageform.xml z grupą 'Dane pod
[FAIL] rate=0/3 expected=True: utwórz zakładkę pageform.xml dla obiektu Dokument z polami N
[FAIL] rate=0/3 expected=True: jak zrobić widok listy viewform.xml dla Kontrahentów z kolum
[FAIL] rate=0/3 expected=True: jak zmodyfikować istniejący pageform.xml — chcę dodać nowe p
[PASS] rate=0/3 expected=False: jak skonfigurować business.xml dla nowego modułu? potrzebuję
[PASS] rate=0/3 expected=False: zrób mi worker C# który liczy saldo kontrahenta i eksponuje
[PASS] rate=0/3 expected=False: jak skonfigurować uprawnienia RightName i RightContext dla m
[PASS] rate=0/3 expected=False: napisz mi metodę w C# która oblicza VAT dla pozycji faktury
[PASS] rate=0/3 expected=False: jak zbudować API REST w ASP.NET Core do pobierania danych ko
Test : 6/18 correct, precision=100% recall=0% accuracy=33% (0.0s)
[FAIL] rate=0/3 expected=True: co to Class Collapsable w enova365? chcę zwinąć grupę filtró
[FAIL] rate=0/3 expected=True: jak dodać Grid z IsToolbarVisible EditInPlace NewInPlace i F
[FAIL] rate=0/3 expected=True: potrzebuję plik Adres.form.xml jako współdzielony fragment z
[FAIL] rate=0/3 expected=True: jak w viewform.xml dodać Flow jako panel filtrów nad gridem?
[PASS] rate=0/3 expected=False: jak zarejestrować FolderViewAttribute i WorkerAttribute w en
[PASS] rate=0/3 expected=False: zrób raport RDLC pokazujący listę faktur z podsumowaniem
Improving description...
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/Users/marcin/.claude/skills/skill-creator/scripts/run_loop.py", line 332, in <module>
main()
File "/Users/marcin/.claude/skills/skill-creator/scripts/run_loop.py", line 297, in main
output = run_loop(
File "/Users/marcin/.claude/skills/skill-creator/scripts/run_loop.py", line 202, in run_loop
new_description = improve_description(
File "/Users/marcin/.claude/skills/skill-creator/scripts/improve_description.py", line 114, in improve_description
response = client.messages.create(
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_utils/_utils.py", line 282, in wrapper
return func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/resources/messages/messages.py", line 996, in create
return self._post(
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_base_client.py", line 1364, in post
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_base_client.py", line 1058, in request
request = self._build_request(options, retries_taken=retries_taken)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_base_client.py", line 521, in _build_request
headers = self._build_headers(options, retries_taken=retries_taken)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_base_client.py", line 451, in _build_headers
self._validate_headers(headers_dict, custom_headers)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/anthropic/_client.py", line 196, in _validate_headers
raise TypeError(
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted"
@@ -0,0 +1,734 @@
---
name: soneta-form-xml
description: Tworzenie plików form.xml opisujących formularze, zakładki i widoki UI dla platformy enova365/Soneta Enterprise. Używaj gdy użytkownik prosi o utworzenie zakładki formularza (pageform.xml), widoku listy (viewform.xml), formularza (form.xml), lookupu (lookupform.xml), lub gdy pyta o strukturę i składnię plików form.xml dla enova365.
---
# Soneta Form XML - Formularze UI
Skill do tworzenia plików XML definiujących interfejs użytkownika w systemie enova365/Soneta Enterprise.
## Typy plików formularzy
| Typ pliku | Wzorzec nazwy | Przeznaczenie |
|-----------|---------------|---------------|
| **pageform.xml** | `{DataType}.{PageName}.pageform.xml` | Zakładka formularza edycji obiektu |
| **viewform.xml** | `{NazwaWidoku}.viewform.xml` | Widok listy zarejestrowanej jako folder (listy główne) |
| **gridform.xml** | `{IdentyfikatorListy}.gridform.xml` | Indywidualne ustawienia listy na formularzu |
| **lookupform.xml** | `{NazwaPodpowiedzi}.lookupform.xml` | Lista wyboru (lookup) |
| **form.xml** | `{Nazwa}.form.xml` | Współdzielony fragment UI (include) |
### Format nazwy pageform.xml
Nazwa pliku składa się z 4 części rozdzielonych kropkami:
```
{DataType}.{PageName}.pageform.xml
```
- **DataType** - typ danych, dla którego definiowana jest zakładka (np. `Towar`, `Kontrahent`, `DokumentHandlowy`)
- **PageName** - nazwa zakładki (np. `Ogolne`, `Dodatkowe`, `Adresy`)
- **pageform.xml** - stały sufiks
**Przykłady:**
- `Towar.Ogolne.pageform.xml`
- `Towar.Dodatkowe.pageform.xml`
- `Kontrahent.Adresy.pageform.xml`
- `DokumentHandlowy.Pozycje.pageform.xml`
### Format nazwy viewform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{NazwaWidoku}.viewform.xml
```
**Przykłady:**
- `Towary.viewform.xml`
- `Kontrahenci.viewform.xml`
- `DokumentyHandlowe.viewform.xml`
### Format nazwy gridform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{IdentyfikatorListy}.gridform.xml
```
**Przykłady:**
- `PozycjeDokumentu.gridform.xml`
- `RachunkiBankowe.gridform.xml`
### Format nazwy lookupform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{NazwaPodpowiedzi}.lookupform.xml
```
**Przykłady:**
- `Towary.lookupform.xml`
- `Kontrahenci.lookupform.xml`
## Hierarchia elementów XML
Elementy XML dzielą się na trzy grupy dziedziczące po `uiElement`:
1. **Elementy proste** - Field, Label, Command, Gap, Html, GroupBy, Axis
2. **Kontenery elementów** - Group, Stack, Row, Flow, Bar, Dashboard, Include, Page (dziedziczą po `ContainerElement`)
3. **Kolekcje** - Grid, Cards, Scheduler, Chart, Diagram, Pivot (dziedziczą po `CollectionElement`)
## Struktura dokumentu
Każdy plik formularza zaczyna się od deklaracji XML i elementu głównego `DataForm`:
```xml
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd">
<!-- zawartość -->
</DataForm>
```
### Atrybuty DataForm
| Atrybut | Opis |
|---------|------|
| `Priority` | Kolejność zakładek (domyślnie 100, niższa = wcześniej) |
| `RightName` | Opcjonalny. Nazwa uprawnienia do zakładki (tylko gdy inna niż standardowa) |
| `Contexts` | Warunki licencyjne, np. `"Licence.HAN \| Licence.FA"` (nie bindowane) |
| `ViewType` | Typ widoku: `None`, `Dialog`, `Form`, `Folder` |
| `Mode` | Tryb: `None`, `Form`, `Folder`, `Wizard`, `Modal`, `Popup`, `Frame` |
| `DataType` | Opcjonalny. Pełne określenie typu danych (wymagany tylko gdy nazwa pliku nie określa jednoznacznie typu), np. `"Soneta.Handel.DokumentHandlowy,Soneta.Handel"` |
## Wspólne atrybuty elementów
Następujące atrybuty mogą być użyte w **dowolnym** elemencie form.xml:
| Atrybut | Opis |
|---------|------|
| `Name` | Identyfikator elementu, który można wykorzystać w kodzie C# |
| `Class` | Klasy stylów (lista wartości oddzielonych spacją) |
| `DataContext` | Zmienia kontekst danych dla elementu i wszystkich jego elementów podrzędnych |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową) |
| `Renderable` | Czy element ma być dostępny. Wyrażenie liczone **raz** przy logowaniu operatora - optymalne dla warunków zależnych od środowiska, licencji i innych parametrów niezmiennych w trakcie sesji |
### Atrybut CaptionHtml
Atrybut `CaptionHtml` występuje w elementach: `Label`, `Field`, `Group`, `Page`, `Command` i innych.
Może zawierać:
- Tekst etykiety (w formacie HTML)
- Wyrażenia bindowane w klamrach: `{wyrażenie}` - wartość tekstowa jest automatycznie kodowana do HTML
- Wyrażenia zwracające kod HTML: `{WłaściwośćHtml}` - nazwa musi mieć sufiks `Html`, wtedy wartość nie jest kodowana
- Podwójne klamry dla literalnych znaków: `{{``{`, `}}``}`
**Specjalne przypadki w `Field`:**
- Brak atrybutu → automatyczna etykieta wyliczana na podstawie danych
- `CaptionHtml=" "` (spacja) → pusta etykieta (miejsce na etykietę zostaje zachowane)
- `CaptionHtml=""` (pusty) → brak etykiety (pole bez miejsca na etykietę)
**Alternatywa:** Zamiast `CaptionHtml` można użyć `CaptionMarkdown` dla etykiet w formacie Markdown.
## Elementy kontenerowe
### Page - Zakładka
Główny kontener dla zawartości zakładki:
```xml
<Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<!-- zawartość zakładki -->
</Page>
```
| Atrybut | Opis |
|---------|------|
| `Name` | Opcjonalny. Unikalny identyfikator zakładki |
| `CaptionHtml` | Tytuł zakładki. Może zawierać `/` do grupowania zakładek (np. `"Dokumenty/Faktury"`) |
| `DataContext` | Źródło danych. `{DataSource}` oznacza obiekt edytowany na zakładce, ale można wskazać inne dane |
| `Visibility` | Wyrażenie warunkowe widoczności (bindowalne) |
| `Renderable` | Czy zakładka ma być dostępna. Wyrażenie liczone raz przy logowaniu - optymalne dla warunków zależnych od środowiska, licencji itp. |
| `Key` | Skrót klawiaturowy wywołujący zakładkę formularza |
| `GroupIcon` | Ikona grupy zakładek |
### Zasada budowania zakładki formularza
Zakładka składa się z elementów `<Group>`. Każda grupa może zawierać:
1. **Listę pól w kolumnie** - pola ułożone pionowo jedno pod drugim
2. **Układ wielokolumnowy** - `<Row>` zawierający kilka `<Stack>` z polami
3. **Listę elementów podrzędnych** - np. Grid, ewentualnie poprzedzony polami filtrującymi
```xml
<Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<!-- Grupa z polami w jednej kolumnie -->
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Group>
<!-- Grupa z układem dwukolumnowym -->
<Group CaptionHtml="Dane szczegółowe">
<Row>
<Stack>
<Field CaptionHtml="Data" Width="15" EditValue="{Data}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Stack>
<Stack>
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
<Field CaptionHtml="Źródło" Width="15" EditValue="{Zrodlo}" />
</Stack>
</Row>
</Group>
<!-- Grupa z listą -->
<Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*" EditValue="{Pozycje}">
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Grid>
</Group>
</Page>
```
### Group - Grupa pól
Wizualna ramka grupująca powiązane pola:
```xml
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Group>
```
| Atrybut | Opis |
|---------|------|
| `CaptionHtml` | Tytuł grupy |
| `LabelWidth` | Opcjonalny. Szerokość etykiet dla wszystkich pól w kontenerze |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową) |
| `Renderable` | Czy grupa ma być dostępna (liczone raz przy logowaniu) |
### Stack - Układ pionowy
Układa elementy jeden pod drugim:
```xml
<Stack LabelWidth="15">
<Field CaptionHtml="Pole 1" EditValue="{Pole1}" />
<Field CaptionHtml="Pole 2" EditValue="{Pole2}" />
</Stack>
```
### Row - Układ poziomy
Układa elementy obok siebie w wierszu:
```xml
<Row>
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
</Row>
```
**Pole na całą szerokość:** użyj `Width="*"`
**Pola dosunięte do prawej:** umieść `<Gap Width="*"/>` na początku:
```xml
<Row>
<Gap Width="*" />
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
</Row>
```
### Flow - Układ płynny
Elementy umieszczane są od lewej do prawej. Gdy nie mieszczą się na formularzu, przenoszone są do nowego wiersza:
```xml
<Flow Align="true">
<Field CaptionHtml="Data od" Width="15" EditValue="{DataOd}" />
<Field CaptionHtml="Data do" Width="15" EditValue="{DataDo}" />
<Field CaptionHtml="Status" Width="12" EditValue="{Status}" />
</Flow>
```
## Elementy pól i kontrolek
### Field - Pole edycyjne
Podstawowy element do wyświetlania i edycji danych. Jest generowany **dynamicznie** - w zależności od typu właściwości wyświetla odpowiednią kontrolkę (int → pole numeryczne, bool → checkbox, double → pole z kalkulatorem, typ Sonety → lookup z listą wyboru).
Minimalny `<Field>` powinien zawierać:
- `EditValue` - **wymagany**, binding do właściwości
- `CaptionHtml` - etykieta pola
- `Width` - szerokość pola
```xml
<Field CaptionHtml="Nazwa pola" Width="20" EditValue="{Właściwość}" />
```
| Atrybut | Opis |
|---------|------|
| `EditValue` | **Wymagany**. Binding do właściwości: `{Właściwość}` lub `{new Extender.Właściwość}` |
| `CaptionHtml` | Etykieta pola (patrz sekcja "Atrybut CaptionHtml") |
| `Width` | Szerokość pola w znakach lub px (`*` = wypełnij) |
| `OuterWidth` | Całkowita szerokość z etykietą (do wyrównywania w pionie) |
| `LabelWidth` | Szerokość etykiety |
| `Height` | Wysokość w wierszach lub px (dla pól wieloliniowych) |
| `IsReadOnly` | Warunek tylko do odczytu (bindowalne z logiką biznesową). Logika biznesowa ma wyższy priorytet |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową): `true`/`false`/`Visible`/`Hidden`/`Collapsed` |
| `Renderable` | Czy pole ma być dostępne (liczone raz przy logowaniu) |
| `Format` | Formatowanie wartości w standardzie .NET `string.Format`. Pole `{0}` to wartość edytowana |
| `Footer` | Agregacja w stopce **tylko na listach**: `Sum`, `Count`, `Average`, `Min`, `Max` |
| `CheckedValue` | Wartość dla **RadioButton** |
| `Class` | Klasy stylów (patrz sekcja Class) |
| `DataContext` | Zmienia kontekst danych dla tego pola i elementów podrzędnych |
#### RadioButton
Aby utworzyć RadioButton, dodaj parametr `CheckedValue`:
```xml
<Field Width="20" CaptionHtml="Towar" EditValue="{Typ}" CheckedValue="Towar" />
<Field Width="20" CaptionHtml="Usługa" EditValue="{Typ}" CheckedValue="Usługa" />
<Field Width="20" CaptionHtml="Receptura" EditValue="{Typ}" CheckedValue="Receptura" />
```
Pola z tym samym `EditValue` i różnymi `CheckedValue` tworzą grupę RadioButton.
### Label - Etykieta
Tekst bez możliwości edycji:
```xml
<Label CaptionHtml="Tekst informacyjny" Width="30" />
```
### Gap - Odstęp
Wypełniacz przestrzeni. Użyteczny do dosunięcia elementów do prawej strony (gdy `<Gap Width="*" />` jest na początku wiersza).
```xml
<Row>
<Gap Width="*" />
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
</Row>
```
**Uwaga:** `<Gap Width="*" />` jako ostatni element w wierszu nie jest potrzebny - nic nie zmienia.
### Command - Przycisk/Polecenie
```xml
<Command CaptionHtml="Zapisz"
MethodName="Zapisz"
DataContext="{new MojExtender}"
Visibility="{IsVisibleButton}" />
```
| Atrybut | Opis |
|---------|------|
| `MethodName` | Nazwa metody do wywołania (szukana w klasie z kontekstu formularza) |
| `MoreMethodName` | Dodatkowa metoda (dla przycisków dzielonych - wersja przeglądowa) |
| `Key` | Skrót klawiszowy |
| `CommandStyle` | Styl: `Default`, `Important`, `Red`, `Green`, `Blue` |
| `Icon` | Nazwa ikony (nie działa w enova365 desktop) |
| `Class` | Klasy stylów |
| `DataContext` | Zmienia kontekst danych (np. `{new MojExtender}` - patrz sekcja Bindowanie danych) |
| `Renderable` | Czy przycisk ma być dostępny (liczone raz przy logowaniu) |
### Include - Dołączenie fragmentu
Wstawia zawartość innego pliku form.xml lub dynamicznie generowany element UI:
```xml
<!-- Statyczne dołączenie pliku -->
<Include Source="Adres.form.xml" />
<!-- Z kontekstem danych -->
<Include Source="Adres.form.xml" DataContext="{AdresKorespondencyjny}" />
<!-- Dynamiczny element z kodu C# -->
<Include Source="{DynamicznyFormularz}" />
```
| Atrybut | Opis |
|---------|------|
| `Source` | Nazwa pliku form.xml **lub** wyrażenie bindujące zwracające element DOM (`UIElement`) z kodu. Wyrażenie bindujące jest wywoływane po każdej zmianie danych, co pozwala budować dynamiczne formularze |
| `DataContext` | Opcjonalny. Kontekst danych dla dołączanego fragmentu |
| `Path` | Opcjonalny. Określa element pliku form.xml, który zostanie wstawiony (gdy Source jest nazwą pliku) |
| `Suffix` | Opcjonalny. Napis dodawany do każdej nazwy (`Name`) elementów dołączonych przez Include |
## Kolekcje i listy
### Grid / List - Tabela danych
```xml
<Grid Width="*" Height="*"
EditValue="{Pozycje}"
SelectedValue="{WybranePozycje}"
FocusedValue="{AktualnaPozycja}"
IsToolbarVisible="true"
EditInPlace="true"
NewInPlace="true"
OrderBy="Data desc"
SumType="All"
OpenMethodName="OtworzFormularz"
IsSmartOpen="true">
<Field CaptionHtml="Kod" Width="15" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="30" EditValue="{Nazwa}" />
<Field CaptionHtml="Ilość" Width="10" EditValue="{Ilość}" Footer="Sum" />
<GroupBy EditValue="{Kategoria}" IsDescending="false" />
</Grid>
```
| Atrybut | Opis | Default |
|---------|------|---------|
| `EditValue` | Źródło danych kolekcji | - |
| `SelectedValue` | Binding do zaznaczonych wierszy - typ `DataType[]` (tablica) | - |
| `FocusedValue` | Binding do podświetlonego wiersza - typ `DataType` (obiekt) | - |
| `IsToolbarVisible` | Pokazuj pasek narzędzi | `false` |
| `IsFilterRowVisible` | Pokazuj wiersz filtrujący | `false` |
| `IsHeaderVisible` | Widoczność nagłówków z tytułami kolumn | `true` |
| `EditInPlace` | Edycja bezpośrednio w komórkach | `false` |
| `NewInPlace` | Dodawanie przez kliknięcie pustego wiersza | `false` |
| `AlwaysAddNewRow` | Nowy wiersz od razu dodawany (Esc nie usuwa) | `false` |
| `PreventNewRowOnFocus` | Zapobiegaj nowemu wierszowi przy fokusie | `false` |
| `KeepsSequence` | Czy po edycji in-place zachować kolejność wierszy (`true`) czy ponownie sortować (`false`) | `false` |
| `OpenMethodName` | Metoda wywoływana po Enter/double-click (domyślnie otwarcie formularza) | - |
| `IsSmartOpen` | Kolumna ze strzałką do otwarcia formularza | - |
| `NewButton` | Stan przycisku Nowy: `Auto`, `None`, `Visible` | auto |
| `EditButton` | Stan przycisku Otwórz | auto |
| `UpdateButton` | Stan przycisku Aktualizuj | auto |
| `RemoveButton` | Stan przycisku Usuń | auto |
| `SearchButton` | Stan przycisku Szukaj | auto |
| `MoreButton` | Przycisk więcej: `None`, `Visible`, `Actions` | auto |
| `OrderBy` | Domyślne sortowanie (np. `"Kolumna desc"`) | - |
| `Filter` | Filtr danych | - |
| `ResourceName` | Nazwa pliku grid.xml z indywidualnymi ustawieniami | - |
| `SumType` | Typ sum: `None`, `Selected`, `All`, `Groups`, `GroupsNewLine` | `None` |
| `ActionsMode` | Czy workery przypięte do listy mają być w menu Czynności formularza: `FormAndControl`, `Control`, `Form` | - |
#### Atrybuty dla drzewa (Tree)
| Atrybut | Opis | Default |
|---------|------|---------|
| `TreeNodesValue` | Binding do węzłów | - |
| `TreeHasNodesValue` | Binding sprawdzający czy ma węzły | - |
| `TreeParentValue` | Binding do rodzica | - |
| `TreeExpandingLevel` | Poziom rozwinięcia: `Collapsed`, `ExpandRoot`, `ExpandRootFix`, `ExpandAll` | `Collapsed` |
### GroupBy - Grupowanie w Grid
```xml
<Grid EditValue="{Pozycje}">
<GroupBy EditValue="{Kategoria}" />
<Field CaptionHtml="Nazwa" EditValue="{Nazwa}" />
</Grid>
```
## Elementy specjalne
### Chart - Wykres
```xml
<Chart EditValue="{DaneWykresu}"
Type="Bar"
ChartColor="Blue"
IsLegendVisible="true">
<Field CaptionHtml="Miesiąc" EditValue="{Miesiac}" />
<Field CaptionHtml="Wartość" EditValue="{Wartosc}" />
<Axis Direction="X" EditValue="{Miesiac}" />
<Axis Direction="Y" EditValue="{Wartosc}" />
</Chart>
```
Typy wykresów: `Line`, `Bar`, `Pie`, `Donut`, `Spider`, `Polar`, `Area`, `Pyramid`, `Funnel`, `Bubble`, `Scatter`
### Scheduler - Kalendarz
```xml
<Scheduler EditValue="{Zdarzenia}"
View="Weekly"
SelectedInterval="{WybranyOkres}">
<Field CaptionHtml="Tytuł" EditValue="{Tytul}" />
<Field CaptionHtml="Początek" EditValue="{DataOd}" />
<Field CaptionHtml="Koniec" EditValue="{DataDo}" />
</Scheduler>
```
### Gantt / GanttDiagram - Harmonogram
```xml
<Gantt EditValue="{Zadania}" ViewType="WeekDay">
<Field CaptionHtml="Zadanie" EditValue="{Nazwa}" />
<Field CaptionHtml="Początek" EditValue="{Start}" />
<Field CaptionHtml="Koniec" EditValue="{Finish}" />
</Gantt>
```
### Html / Markdown - Treść formatowana
```xml
<Html EditValue="{TrescHtml}" Width="*" Height="200" />
<Markdown EditValue="{TrescMarkdown}" Width="*" />
```
### Indicator - Wskaźnik
```xml
<Indicator CaptionHtml="Sprzedaż"
EditValue="{WartoscSprzedazy}"
UnitSymbol="PLN" />
```
### Dashboard - Panel kafelkowy
```xml
<Dashboard>
<Group Class="DashboardItem" CaptionHtml="Sprzedaż">
<Indicator EditValue="{Sprzedaz}" />
</Group>
</Dashboard>
```
## Bindowanie danych
Każdy element form.xml znajduje się w odpowiednim kontekście powiązanego obiektu C#. Powiązany typ danych zależy od typu danych dla którego zdefiniowany jest pageform.xml.
### Powiązanie typu z formularzem
Powiązanie z typem w elemencie root odbywa się przez:
1. **Przez nazwę pliku pageform.xml** - pierwszy człon nazwy pliku (DataType) określa typ obiektu. Np. dla pliku `Towar.Ogolne.pageform.xml` kontekstem jest klasa `Towar`.
2. **Przez atrybut DataType w DataForm** - jawne określenie typu:
```xml
<DataForm DataType="Soneta.Handel.Towar,Soneta.Handel">
```
3. **Przez rejestrację FolderViewAttribute** - wiążącą folder programu z obiektem biznesowym i formularzem prezentującym ten folder.
### Zmiana kontekstu danych
- **DataContext** - zmienia kontekst **aktualnego elementu i wszystkich elementów podrzędnych**:
```xml
<Group DataContext="{Adres}">
<!-- wszystkie pola wewnątrz odwołują się do właściwości obiektu Adres -->
<Field CaptionHtml="Miasto" EditValue="{Miasto}" />
</Group>
```
- **EditValue** - zmienia kontekst **tylko elementów podrzędnych** (bez aktualnego kontenera):
```xml
<Grid EditValue="{Pozycje}">
<!-- pola wewnątrz odwołują się do właściwości elementu kolekcji Pozycje -->
<Field CaptionHtml="Nazwa" EditValue="{Nazwa}" />
</Grid>
```
### Składnia wyrażeń w klamrach
W wyrażeniach `{...}` można odwoływać się do:
| Składnia | Opis |
|----------|------|
| `{Właściwość}` | Publiczna właściwość obiektu w kontekście |
| `{Metoda()}` | Wartość zwracana przez publiczną metodę. Parametry metody są uzupełniane automatycznie na podstawie aktualnego kontekstu UI (`Soneta.Business.Context`) |
| `{Obiekt.Właściwość}` | Właściwość zagnieżdżona |
| `{Context.TypDanych.Pole}` | Wartość z aktualnego kontekstu UI (`Soneta.Business.Context`) |
| `{Features.NazwaCechy}` | Cechy powiązane z obiektem biznesowym `Row` |
| `{Workers.NazwaWorkera.Pole}` | Właściwość workera powiązanego z obiektem (`WorkerAttribute`) |
| `{new NazwaExtender.Pole}` | Właściwość extendera (worker niepowiązany z konkretnymi danymi) |
| `{Tablica[indeks]}` | Element tablicy pod wskazanym indeksem |
| `{.}` | Aktualna wartość w kontekście elementu |
### Wyrażenia porównań
| Składnia | Opis |
|----------|------|
| `{Pole=wartość}` | Porównanie równości |
| `{Pole!=wartość}` | Porównanie nierówności |
| `{!PoleLogiczne}` | Negacja wartości logicznej |
| `{?warunek}` | Warunek oparty o klasę `RowCondition` |
### Przykłady bindingów
```xml
<!-- Proste właściwości -->
<Field CaptionHtml="Kod" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa kontrahenta" EditValue="{Kontrahent.Nazwa}" />
<!-- Właściwości workerów -->
<Field CaptionHtml="Saldo" EditValue="{Workers.SaldoWorker.SaldoOgolem}" />
<!-- Extendery (obiekty tworzone dynamicznie) -->
<Field EditValue="{new MojExtender.Właściwość}" />
<Command MethodName="Wykonaj" DataContext="{new MojExtender}" />
<!-- Cechy -->
<Field CaptionHtml="Cecha" EditValue="{Features.MojaCecha}" />
<!-- Kontekst UI -->
<Field EditValue="{Context.Operator.Nazwa}" IsReadOnly="true" />
<!-- Aktualna wartość -->
<Field EditValue="{.}" />
```
### Wyrażenia warunkowe (RowCondition)
```xml
Visibility="{?State=Added}" <!-- stan obiektu -->
Visibility="{?!State=Added}" <!-- negacja -->
Visibility="{?Typ=Towar or Typ=Usługa}" <!-- OR -->
Visibility="{?Aktywny and Widoczny}" <!-- AND -->
```
## Atrybut Class - Style i zachowania
Atrybut `Class` może zawierać wiele wartości oddzielonych spacją:
```xml
<Field Class="BoldLabel LeftAlign ImageEdit" ... />
```
### Style etykiet
- `BoldLabel` - pogrubiona etykieta
- `CenterLabel` - wycentrowana
- `RightLabel` - wyrównana do prawej
- `MultilineLabel` - wieloliniowa
- `NoColonLabel` - bez dwukropka
- `WarningLabel` - ostrzeżenie
- `InfoLabel` - informacja
- `TipLabel` - podpowiedź
### Style czcionek
- `LargeFont` - duża czcionka
- `BoldFont` - pogrubiona
- `GreenFont` - zielona
- `RedFont` - czerwona
- `WarningFont` - ostrzegawcza
- `FixedWidthFont` - stała szerokość
### Wyrównanie
- `LeftAlign`, `RightAlign`, `TextRight`
### Typy edytorów
- `PasswordEdit` - hasło
- `ColorEdit` - wybór koloru
- `RichEdit` - edytor HTML
- `ImageEdit` - obraz
- `FileEdit` - wybór pliku
- `FolderEdit` - wybór folderu
- `PathPropertyEdit` - ścieżka
- `HyperlinkEdit` - hiperłącze
- `EmailEdit` - email
- `PhoneEdit` - telefon
- `RatingEdit` - ocena gwiazdkowa
- `ProgressEdit` - pasek postępu
- `IconEdit` - ikona
- `CheckButtonEdit` - checkbox jako przycisk
- `XmlEdit` - edytor XML
- `DataTextEdit` - tekst danych
### Zachowania
- `Collapsable` - zwijalna grupa
- `Expandable` - rozwijalna
- `Expanded` - domyślnie rozwinięta
- `Hidden` - ukryty
- `FirstResponder` - pole z fokusem zaraz po otwarciu formularza
- `Scrollable` - przewijalna
- `ImageCircle` - okrągły obraz
- `Tree` - drzewo
### Układy i pozycjonowanie
- `GroupItem` - element umieszczony na wysokości nagłówka `<Group>` (zwykle po prawej stronie), służy do sterowania zawartością pozostałych elementów grupy
- `Reverse` - układa elementy w odwrotnej kolejności (od prawej do lewej lub od dołu do góry)
- `SmartOpen` - kolumna w `Grid` wyróżniona do szybkiego otwierania formularza (ze strzałką)
### Przyciski
- `MainCommand` - główny przycisk
- `SplitCommand` - przycisk z menu
- `CommandNoText` - tylko ikona
- `CommandIcoText` - ikona i tekst
- `WorkerCommand` - przycisk workera
- `WizardCommand` - przycisk kreatora
- `PrintButton` - przycisk drukowania
## Appearance - Warunkowe formatowanie
```xml
<Field CaptionHtml="Saldo" EditValue="{Saldo}">
<Appearance Condition="{?Saldo&lt;0}" ForeColor="Red" FontBold="true" />
<Appearance Condition="{?Saldo&gt;1000}" BackColor="LightGreen" />
</Field>
```
## Przykłady
### Prosta zakładka (pageform.xml)
Plik: `MojObiekt.Ogolne.pageform.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns="http://www.enova.pl/schema/form.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
Priority="10">
<Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
<Row>
<Field CaptionHtml="Data" Width="15" EditValue="{Data}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Row>
</Group>
<Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*" EditValue="{Pozycje}" IsToolbarVisible="true">
<Field CaptionHtml="Lp" Width="5" EditValue="{Lp}" />
<Field CaptionHtml="Opis" Width="*" EditValue="{Opis}" />
<Field CaptionHtml="Wartość" Width="15" EditValue="{Wartosc}" Footer="Sum" />
</Grid>
</Group>
</Page>
</DataForm>
```
### Współdzielony fragment (form.xml)
Plik: `Adres.form.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns="http://www.enova.pl/schema/form.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd">
<Stack>
<Row>
<Field CaptionHtml="Ulica" Width="40" EditValue="{Ulica}" />
<Field CaptionHtml="Nr domu" Width="10" EditValue="{NrDomu}" />
</Row>
<Row>
<Field CaptionHtml="Kod pocztowy" Width="12" EditValue="{KodPocztowy}" />
<Field CaptionHtml="Miasto" Width="*" EditValue="{Miasto}" />
</Row>
</Stack>
</DataForm>
```
## Referencje
- Pełna specyfikacja elementów: [references/ELEMENTS.md](references/ELEMENTS.md)
- Schemat XSD: [references/Form.xsd](references/Form.xsd)
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Szablon: Współdzielony fragment formularza (form.xml)
Format nazwy pliku: {Nazwa}.form.xml
Przykłady:
- Adres.form.xml
- AdresH.form.xml
- KontaktDane.form.xml
Dołączanie w innym pliku:
<Include DataContext="{Adres}" Source="Adres.form.xml" />
-->
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd">
<!-- Stack jako główny kontener - układ pionowy -->
<Stack>
<Row>
<Field CaptionHtml="Ulica" Width="40" EditValue="{Ulica}" />
<Field CaptionHtml="Nr domu" Width="10" EditValue="{NrDomu}" />
<Field CaptionHtml="Nr lokalu" Width="10" EditValue="{NrLokalu}" />
</Row>
<Row>
<Field CaptionHtml="Kod pocztowy" Width="12" EditValue="{KodPocztowy}" Class="LeftAlign" />
<Field CaptionHtml="Miejscowość" Width="*" EditValue="{Miejscowosc}" />
</Row>
<Row>
<Field CaptionHtml="Poczta" Width="30" EditValue="{Poczta}" />
</Row>
<Row>
<Field CaptionHtml="Województwo" Width="25" EditValue="{Wojewodztwo}" />
<Field CaptionHtml="Kraj" Width="6" EditValue="{KodKraju}" />
<Field CaptionHtml="" Width="20" EditValue="{Kraj}" />
</Row>
</Stack>
</DataForm>
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Szablon: Zakładka z warunkami handlowymi
Plik: Kontrahent.WarunkiHandlowe.pageform.xml
Zawiera przykłady: Row, Gap, Command, Grid z rachunkami bankowymi
-->
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
Priority="20">
<Page CaptionHtml="Warunki handlowe" DataContext="{DataSource}">
<!-- Warunki płatności -->
<Group CaptionHtml="Warunki płatności">
<Row>
<Field CaptionHtml="Sposób płatności" Width="20" EditValue="{SposobZaplaty}" />
<Field CaptionHtml="Termin (dni)" Width="10" EditValue="{Termin}" />
</Row>
<Row>
<Field CaptionHtml="Waluta" Width="10" EditValue="{Waluta}" />
<Field CaptionHtml="Domyślny płatnik" Width="*" EditValue="{Platnik}" />
<!-- Przyciski akcji -->
<Command CaptionHtml="Dodaj" Width="8" MethodName="Dodaj"
DataContext="{new PlatnikExtender}" Visibility="{IsVisibleDodaj}" />
<Command CaptionHtml="Usuń" Width="8" MethodName="Usun"
DataContext="{new PlatnikExtender}" Visibility="{IsVisibleUsun}" />
</Row>
</Group>
<!-- Limity kredytowe -->
<Group CaptionHtml="Limity">
<Row>
<Field CaptionHtml="Blokada sprzedaży" Width="8" Class="LeftAlign" EditValue="{BlokadaSprzedazy}" />
</Row>
<Row>
<Field CaptionHtml="Limit kredytu" Width="18" EditValue="{TypLimitu}" />
<Field CaptionHtml="" Width="15" EditValue="{LimitKredytu}" />
<Field CaptionHtml="Dostępny" Width="15" EditValue="{LimitDostepny}"
Visibility="{new LimitExtender.IsVisible()}" />
</Row>
</Group>
<!-- Rachunki bankowe - tabela -->
<Group CaptionHtml="Rachunki bankowe">
<Grid Width="*" Height="*"
EditValue="{Rachunki}"
IsToolbarVisible="true"
NewInPlace="true"
EditInPlace="true">
<Field CaptionHtml="Bank" Width="25" EditValue="{Rachunek.Bank}" />
<Field CaptionHtml="Numer rachunku" Width="35" EditValue="{Rachunek.Numer}" />
<Field CaptionHtml="Domyślny" Width="8" EditValue="{Domyslne}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Grid>
</Group>
</Page>
</DataForm>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Szablon: Zakładka formularza (pageform.xml)
Format nazwy pliku: {DataType}.{PageName}.pageform.xml
Przykłady:
- Towar.Ogolne.pageform.xml
- Kontrahent.Adresy.pageform.xml
- Zamowienie.Pozycje.pageform.xml
-->
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd"
Priority="10">
<Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<!-- Grupa z polami w jednej kolumnie -->
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
<Row>
<Field CaptionHtml="Data utworzenia" Width="15" EditValue="{DataUtworzenia}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Row>
</Group>
<!-- Grupa z układem dwukolumnowym -->
<Group CaptionHtml="Dane szczegółowe">
<Row>
<Stack>
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
<Field CaptionHtml="Kategoria" Width="20" EditValue="{Kategoria}" />
</Stack>
<Stack>
<Field CaptionHtml="Źródło" Width="15" EditValue="{Zrodlo}" />
<Field CaptionHtml="Priorytet" Width="10" EditValue="{Priorytet}" />
</Stack>
</Row>
</Group>
<!-- Grupa z listą pozycji -->
<Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*"
EditValue="{Pozycje}"
IsToolbarVisible="true"
EditInPlace="true"
NewInPlace="true">
<Field CaptionHtml="Lp" Width="5" EditValue="{Lp}" />
<Field CaptionHtml="Opis" Width="*" EditValue="{Opis}" />
<Field CaptionHtml="Ilość" Width="10" EditValue="{Ilosc}" Footer="Sum" />
<Field CaptionHtml="Wartość" Width="15" EditValue="{Wartosc}" Footer="Sum" />
</Grid>
</Group>
</Page>
</DataForm>
@@ -0,0 +1,49 @@
{
"skill_name": "soneta-form-xml",
"evals": [
{
"id": 1,
"prompt": "Utwórz plik Zamowienie.Szczegoly.pageform.xml dla platformy enova365. Zakładka powinna zawierać:\n- Grupę 'Dane podstawowe' z polami: Numer (szerokość 20), DataZlozenia (szerokość 15), Kontrahent (szerokość *), Status (szerokość 15)\n- Grupę 'Warunki' z układem dwukolumnowym (Row > Stack): lewa kolumna ma SposobDostawy (20) i TerminDostawy (15), prawa kolumna ma SposobZaplaty (20) i TerminZaplaty (15)\n- Grupę 'Pozycje' z Grid (IsToolbarVisible, EditInPlace, NewInPlace) i kolumnami: Lp (5), Towar (*), Ilosc (10) z Footer=Sum, CenaJednostkowa (18), Wartosc (15) z Footer=Sum\nPriority zakładki: 10.",
"expected_output": "Poprawny plik XML pageform.xml z deklaracją XML, elementem DataForm z atrybutami xmlns i Priority=10, elementem Page z DataContext={DataSource}, trzema grupami z odpowiednimi polami i gridem. Plik powinien być gotowy do użycia w projekcie enova365.",
"files": [],
"assertions": [
"Plik zaczyna się od <?xml version=\"1.0\" encoding=\"utf-8\"?>",
"Element DataForm ma atrybut Priority=\"10\"",
"Element Page ma atrybut DataContext=\"{DataSource}\"",
"Są trzy elementy Group: 'Dane podstawowe', 'Warunki', 'Pozycje'",
"Układ dwukolumnowy w grupie Warunki używa Row zawierającego Stack",
"Element Grid ma atrybuty IsToolbarVisible=\"true\", EditInPlace=\"true\", NewInPlace=\"true\"",
"Pola Ilosc i Wartosc w Grid mają atrybut Footer=\"Sum\"",
"Binding pól używa składni {NazwaPola} w cudzysłowie"
]
},
{
"id": 2,
"prompt": "Stwórz plik Pracownicy.viewform.xml dla widoku listy pracowników w enova365. Widok listy powinien zawierać kolumny: Kod (8), NazwiskoImie (30), NumerPracownika (20), Dzial (*), Stanowisko (20), DataZatrudnienia (15). Domyślne sortowanie po NazwiskoImie. Dodaj IsToolbarVisible i IsFilterRowVisible. Zachowaj właściwą strukturę pliku viewform.xml.",
"expected_output": "Poprawny plik viewform.xml z elementem DataForm (bez Page), elementem Grid z kolumnami i sortowaniem OrderBy=\"NazwiskoImie\". Plik zgodny ze standardem enova365.",
"files": [],
"assertions": [
"Plik ma poprawną deklarację XML",
"Element DataForm ma xmlns=\"http://www.enova.pl/schema/form.xsd\"",
"Jest element Grid z EditValue lub bez (dla widoku listy)",
"Grid ma atrybut OrderBy=\"NazwiskoImie\"",
"Grid ma IsToolbarVisible=\"true\" i IsFilterRowVisible=\"true\"",
"Są kolumny Field dla: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia",
"Pole Dzial ma Width=\"*\""
]
},
{
"id": 3,
"prompt": "Pokaż jak w pageform.xml enova365 zastosować warunkową widoczność pól używając wyrażeń RowCondition. Stwórz przykładowy plik Kontrahent.Kredyt.pageform.xml z następującymi wzorcami:\n1. Pole 'LimitKredytu' widoczne tylko gdy TypKlienta='Korporacyjny'\n2. Pole 'WarunkiSpecjalne' widoczne gdy Status='Premium' LUB Status='VIP'\n3. Pole 'OstrzezenieBranze' widoczne gdy NIE Status='Aktywny'\n4. Przycisk Command widoczny gdy ObrotyRoczne > 0 (użyj WorkCondition lub własność bool)\n5. Cała Grupa 'Dane zaawansowane' zwijalna (Collapsable) z Renderable uzależnionym od licencji",
"expected_output": "Plik pageform.xml demonstrujący różne wzorce warunkowej widoczności: Visibility=\"{?TypKlienta=Korporacyjny}\", Visibility=\"{?Status=Premium or Status=VIP}\", Visibility=\"{?!Status=Aktywny}\", użycie klasy Collapsable dla grupy.",
"files": [],
"assertions": [
"Użyto składni Visibility=\"{?Pole=Wartość}\" dla warunku równości",
"Użyto składni OR dla wielu wartości: {?Status=Premium or Status=VIP}",
"Użyto negacji: {?!Status=Aktywny}",
"Klasa Collapsable jest zastosowana do grupy",
"Atrybut Renderable jest użyty dla warunku licencji"
]
}
]
}
@@ -0,0 +1,864 @@
# Pełna specyfikacja elementów Form XML
Kompletna lista elementów XML dostępnych w plikach form.xml platformy enova365.
## Spis treści
1. [Elementy kontenerowe](#elementy-kontenerowe)
2. [Elementy pól](#elementy-pól)
3. [Elementy kolekcji](#elementy-kolekcji)
4. [Elementy wykresów i wizualizacji](#elementy-wykresów-i-wizualizacji)
5. [Elementy specjalne](#elementy-specjalne)
6. [Typy wyliczeniowe (Enum)](#typy-wyliczeniowe)
7. [Wspólne atrybuty (uiElement)](#wspólne-atrybuty)
---
## Elementy kontenerowe
### Stack
Układ pionowy - elementy jeden pod drugim.
```xml
<Stack LabelWidth="15" Visibility="{Warunek}">
<!-- elementy potomne -->
</Stack>
```
Dziedziczy atrybuty z `containerElement`.
### Row
Układ poziomy - elementy obok siebie.
```xml
<Row OuterWidth="80" Visibility="{Warunek}">
<!-- elementy potomne -->
</Row>
```
### Flow
Układ płynny z automatycznym zawijaniem.
```xml
<Flow Align="true" Arrange="Horizontally">
<!-- elementy potomne -->
</Flow>
```
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Align` | boolean | Wyrównanie elementów |
| `Arrange` | enum | `Horizontally` lub `Vertically` |
### Group
Wizualna ramka grupująca elementy.
```xml
<Group CaptionHtml="Nazwa grupy" LabelWidth="20" DescriptionHtml="{Opis}">
<!-- elementy potomne -->
</Group>
```
### Page
Zakładka formularza.
```xml
<Page Name="NazwaPage"
CaptionHtml="Tytuł zakładki"
DataContext="{DataSource}"
Key="klucz"
MultiDataSource="źródło"
GroupIcon="ikona"
DefaultVisible="true"
FirstAction="akcja">
<!-- zawartość zakładki -->
</Page>
```
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Name` | string | Unikalny identyfikator |
| `CaptionHtml` | string | Tytuł zakładki |
| `Key` | string | Klucz zakładki |
| `MultiDataSource` | string | Wielokrotne źródło danych |
| `GroupIcon` | string | Ikona grupy |
| `DefaultVisible` | boolean | Domyślna widoczność |
| `FirstAction` | string | Pierwsza akcja |
### Bar
Pasek narzędzi.
```xml
<Bar>
<Command CaptionHtml="Akcja" MethodName="Wykonaj" />
</Bar>
```
### Dashboard
Panel kafelkowy/kokpit.
```xml
<Dashboard TileChangedMethodName="OnTileChanged"
FocusedValue="{FocusedTile}"
ArrangeMode="Default">
<Group Class="DashboardItem">
<!-- zawartość kafelka -->
</Group>
</Dashboard>
```
| Atrybut | Typ | Wartości |
|---------|-----|----------|
| `ArrangeMode` | enum | `Default`, `Canvas`, `Size`, `Visibility` |
### Include
Dołączenie zewnętrznego fragmentu lub dynamicznie generowanego elementu UI.
```xml
<!-- Statyczne dołączenie pliku -->
<Include Source="Adres.form.xml" />
<!-- Z kontekstem danych -->
<Include Source="Adres.form.xml" DataContext="{Adres}" Suffix="Koresp" />
<!-- Dynamiczny element z kodu C# -->
<Include Source="{DynamicznyFormularz}" />
```
| Atrybut | Wymagany | Opis |
|---------|----------|------|
| `Source` | **Tak** | Nazwa pliku form.xml **lub** wyrażenie bindujące zwracające element DOM (`UIElement`). Wyrażenie jest wywoływane po każdej zmianie danych - umożliwia dynamiczne formularze |
| `DataContext` | Nie | Kontekst danych dla dołączanego fragmentu |
| `Path` | Nie | Określa element pliku form.xml do wstawienia (gdy Source jest nazwą pliku) |
| `Suffix` | Nie | Napis dodawany do każdej nazwy (`Name`) elementów dołączonych przez Include |
---
## Elementy pól
### Field
Podstawowe pole edycyjne.
```xml
<Field CaptionHtml="Etykieta"
CaptionMarkdown="Etykieta _z formatowaniem_"
EditValue="{Właściwość}"
Width="20"
OuterWidth="50"
LabelWidth="15"
Height="3"
LabelHeight="2"
Format="N2"
IsReadOnly="{Warunek}"
Visibility="{Warunek}"
CheckedValue="Wartość"
Footer="Sum"
Aggregate="Average"
Important="true"
Class="BoldLabel LeftAlign" />
```
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Format` | string | Format wyświetlania (np. `N2`, `d`, `C`) |
| `CheckedValue` | string | Wartość dla RadioButton |
| `Footer` | enum | Agregacja w stopce |
| `Aggregate` | enum | Typ agregacji |
| `Important` | boolean | Oznaczenie jako ważne |
### Label
Etykieta tekstowa (tylko do odczytu).
```xml
<Label CaptionHtml="Tekst etykiety"
Width="30"
Class="BoldLabel CenterLabel" />
```
### Gap
Odstęp/wypełniacz.
```xml
<Gap Width="*" Height="10" />
```
### Splitter
Rozdzielacz paneli.
```xml
<Splitter Class="HorizontalSplitter" />
```
### Data
Element danych (niewidoczny).
```xml
<Data Name="nazwaParametru" Value="wartość" EditValue="{Binding}" />
```
---
## Elementy poleceń
### Command
Przycisk/polecenie.
```xml
<Command CaptionHtml="Tekst przycisku"
MethodName="NazwaMetody"
MoreMethodName="MetodaDodatkowa"
Key="F5"
CommandStyle="Important"
DataContext="{new MojExtender}"
Visibility="{IsVisible}"
Icon="ikona">
<!-- zagnieżdżone polecenia (submenu) -->
<Command CaptionHtml="Podmenu" MethodName="Akcja" />
<Group CaptionHtml="Grupa poleceń">
<Command ... />
</Group>
</Command>
```
| Atrybut | Typ | Wartości/Opis |
|---------|-----|---------------|
| `CommandStyle` | enum | `Default`, `Important`, `Red`, `Green`, `Blue` |
| `Key` | string | Skrót klawiszowy |
---
## Elementy kolekcji
### Grid / List
Tabela danych.
```xml
<Grid Width="*" Height="*"
EditValue="{Kolekcja}"
SelectedValue="{Zaznaczony}"
FocusedValue="{Aktywny}"
OrderBy="Kolumna desc"
Filter="Warunek"
IsToolbarVisible="true"
IsDateNavigatorVisible="false"
IsSmartFilterVisible="true"
IsFilterRowVisible="false"
FilterPanelWidth="200"
VisibleFeatures="search,filter"
LocatorFields="Kod,Nazwa"
EditInPlace="true"
ForceEditInPlace="false"
NewInPlace="true"
AlwaysAddNewRow="false"
PreventNewRowOnFocus="false"
OpenMethodName="Otwórz"
SequenceMethodName="Sekwencja"
IsSmartOpen="true"
IsNonOptimalWarning="false"
NewButton="Visible"
EditButton="Auto"
UpdateButton="None"
RemoveButton="Visible"
SearchButton="Auto"
MoreButton="Actions"
SumType="All"
ActionsMode="FormAndControl"
ResourceName="NazwaZasobu"
TreeNodesValue="{Węzły}"
TreeHasNodesValue="{MaWęzły}"
TreeParentValue="{Rodzic}"
TreeExpandingLevel="ExpandRoot"
FocusedColumnValue="{AktywnaKolumna}"
IsHeaderVisible="true"
KeepsSequence="false"
IgnoreChangingInSort="Kolumna"
SortAfterEditInPlace="true"
DragAndDrop="true"
AllowCellSelection="false"
SelectedCellsValue="{ZaznaczoneKomórki}"
Name="nazwaGrida">
<Field CaptionHtml="Kolumna" Width="20" EditValue="{Pole}" Footer="Sum" />
<GroupBy EditValue="{Grupowanie}" IsDescending="false" PreventSorting="false" />
<Data Name="param" Value="wartość" />
<UserFilter Value="filtr" />
</Grid>
```
#### Atrybuty przyciski (enumCollectionButtonState)
- `Auto` - automatycznie
- `None` - ukryty
- `Visible` - widoczny
#### TreeExpandingLevel
- `Collapsed` - zwinięte
- `ExpandRoot` - rozwiń korzeń
- `ExpandRootFix` - rozwiń korzeń (stałe)
- `ExpandAll` - rozwiń wszystko
#### SumType (enumCollectionSumType)
- `None` - brak
- `Selected` - zaznaczone
- `All` - wszystkie
- `Groups` - grupy
- `GroupsNewLine` - grupy w nowej linii
#### ActionsMode
- `FormAndControl` - formularz i kontrolka
- `Control` - tylko kontrolka
- `Form` - tylko formularz
### Cards
Widok kart (kafelków). Dziedziczy z Grid, ale **nie obsługuje**: układu kolumnowego, nagłówka, sortowania przez kliknięcie, edit-in-place, struktury drzewiastej.
```xml
<Cards Name="List" IsSmartOpen="true" MoreButton="Visible" Class="DisableSelection">
<Row>
<Field CaptionHtml="" Height="7" Width="22" EditValue="{DefaultImage}" Class="ImageEdit" />
<Stack>
<Field CaptionHtml="" Width="50" Height="2" EditValue="{Nazwa}" Class="LargeFont BoldFont" />
<Row>
<Field CaptionHtml="" Width="20" EditValue="{Kod}" />
<Stack>
<Field CaptionHtml="" Width="27" EditValue="{Cena}" />
<Field CaptionHtml="" Width="27" EditValue="{Masa}" />
</Stack>
</Row>
</Stack>
</Row>
</Cards>
```
Elementy `Field` domyślnie układają się jeden pod drugim. Można grupować je za pomocą `Row` i `Stack`.
**Układ szeroki:** Dodanie `Width="*"` do najbardziej zewnętrznego kontenera rozciąga element na całą szerokość (elementy listy jeden pod drugim).
#### Pasek narzędziowy Cards
- Umiejscowiony powyżej listy z prawej strony
- Posiada tylko przyciski Dodaj i Usuń (brak Otwórz)
- Ikony zaznaczania, otwierania i menu widoczne po najechaniu myszą na kafelek
#### Atrybuty kontrolujące ikony:
- `Class="DisableSelection"` - wyłącza ikonę zaznaczania
- `IsSmartOpen="true"` - włącza przycisk otwierania formularza
- `MoreButton="Visible"` - włącza przycisk "więcej" z dodatkowymi akcjami
### CardTemplate
Szablon karty (dziedziczy z Stack).
---
## Elementy wykresów i wizualizacji
### Chart
Wykres. Element służący do prezentacji danych w postaci wykresów.
```xml
<Chart EditValue="{Dane}"
Type="Bar"
ChartColor="Blue"
IsLegendVisible="true"
LabelFormat="{value} ({percent})"
XAxisTitle="Oś X"
YAxisTitle="Oś Y"
XAxisLabelFormat="{value} EUR"
YAxisLabelFormat="{value:N0}"
OpenMethodName="GetSerieInfo"
FocusedValue="{FocusedValue}"
FocusedColumnValue="{FocusedColumn}">
<Axis CaptionHtml="Kategoria" EditValue="{Kategoria}" Dimension="Enum" />
<Field CaptionHtml="Wartość" EditValue="{Wartosc}" Aggregate="Sum" />
</Chart>
```
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Type` | enum | Typ wykresu (patrz poniżej) |
| `ChartColor` | enum | Kolor wykresu: `None` (wielokolorowy), `Green`, `Blue`, `Grey`, `Red`, `Orange`, `Yellow` |
| `IsLegendVisible` | boolean | Widoczność legendy |
| `LabelFormat` | string | Format etykiety. Zmienne: `{value}`, `{percent}`, `{label}` |
| `XAxisTitle` | string | Podpis osi X |
| `YAxisTitle` | string | Podpis osi Y |
| `XAxisLabelFormat` | string | Format wartości na osi X (zmienne: `{value}`, `{label}`) |
| `YAxisLabelFormat` | string | Format wartości na osi Y |
| `IsDateNavigatorVisible` | boolean | Nawigator daty dla WeekByDays/MonthByDays |
| `OpenMethodName` | string | Metoda wywoływana po kliknięciu na wykres |
| `FocusedValue` | string | Property do którego zostanie podstawiony wiersz po kliknięciu |
| `FocusedColumnValue` | string | Property z nazwą kolumny po kliknięciu (dla wielu Field) |
#### Typy wykresów (enumChartType)
- `Line` - liniowy (zmiany wartości między kategoriami)
- `Bar` - słupkowy/kolumnowy (porównanie kategorii)
- `Area` - warstwowy (suma serii i udział każdej)
- `Pie` - kołowy (proporcje części całości)
- `Donut` - pierścieniowy (jak kołowy, ale z dziurą)
- `Spider` - radarowy (porównanie wielu zmiennych)
- `Polar` - radarowy z wypełnieniem
- `Pyramid` - piramida (kategorie od największej do najmniejszej)
- `Funnel` - lejek (malejące proporcje)
- `Bubble` - bąbelkowy (3 wymiary: X, Y, rozmiar)
- `Scatter` - punktowy (zbiór punktów X/Y)
#### Axis - Oś wykresu
```xml
<Axis CaptionHtml="Etykieta"
EditValue="{Pole}"
Dimension="ByMonths"
Grouping="true"
FirstDayOfWeek="Monday" />
```
| Atrybut | Opis |
|---------|------|
| `Direction` | Kierunek dla Pivot: `X` (kolumny), `Y` (wiersze) |
| `Dimension` | Sposób grupowania miar |
| `Grouping` | Czy grupować dane (tworzy tabelę przestawną) |
| `FirstDayOfWeek` | Pierwszy dzień tygodnia |
#### Dimension (PivotDimension)
- `Enum` - wartości dyskretne, tekstowe (Bar, Pie, Donut)
- `AZ` - grupowanie po pierwszej literze
- `WeekByDays` - zawężenie do tygodnia + przyciski Następny/Poprzedni
- `MonthByDays` - zawężenie do miesiąca + przyciski Następny/Poprzedni
- `ByNumbers` - miara liczbowa, proporcjonalne rozmieszczenie
- `ByDays` - daty bez grupowania, wszystkie dni z zakresu
- `ByWeeks` - grupowanie wg tygodni
- `ByMonths` - grupowanie wg miesięcy
- `ByYears` - grupowanie wg lat
#### Field w Chart - seria danych
```xml
<Field CaptionHtml="Nazwa serii" EditValue="{Wartosc}" Aggregate="Sum" />
```
| Atrybut | Wartości |
|---------|----------|
| `Aggregate` | `None`, `Sum`, `Count`, `Average`, `Min`, `Max` |
#### Zasady tworzenia różnych typów wykresów
**Line/Area (liniowy/warstwowy):**
- 1 Axis + wiele Field → wiele serii danych
- 2 Axis (jeden z `Grouping="true"`) + 1 Field → serie wg grupowania
**Bar (słupkowy):**
- 1 Axis + 1 Field → wykres zwykły
- 1 Axis + wiele Field → wykres skumulowany (stacked)
- 2 Axis + 1 Field → wykres grupowany (slide)
- 2 Axis + wiele Field → stacked-slide
**Pie/Donut (kołowy/pierścieniowy):**
- Zawsze 1 Axis + 1 Field
**Scatter (punktowy):**
- 1 Axis + 2 Field (pierwszy Field = X, drugi Field = Y)
**Bubble (bąbelkowy):**
- 1 Axis + 3 Field (X, Y, rozmiar bąbelka)
### Scheduler
Kalendarz/harmonogram.
```xml
<Scheduler EditValue="{Zdarzenia}"
View="Weekly"
AllowViewChanging="true"
SelectedInterval="{WybranyOkres}"
VisibleInterval="{WidocznyOkres}"
WorkInterval="{OkresPracy}"
Resources="{Zasoby}"
SelectedResource="{WybranyZasób}"
HideDateField="false">
<Field CaptionHtml="Tytuł" EditValue="{Tytul}" />
</Scheduler>
```
**UWAGA:** Niepoprawne wiązanie danych skutkuje błędem krytycznym (brak wyświetlenia pageform'a lub brak możliwości logowania).
| Atrybut | Typ | Opis |
|---------|-----|------|
| `View` | enum | Domyślny widok kalendarza |
| `AllowViewChanging` | boolean | Czy operator może zmieniać widok (domyślnie tak) |
| `SelectedInterval` | string | Okres zaznaczony przez użytkownika |
| `VisibleInterval` | string | Okres widoczny |
| `WorkInterval` | string | Roboczy czas dnia (domyślnie `"9:00..18:00"`). Można podać bezpośrednio lub bindować do `Soneta.Types.Interval` |
| `Resources` | string | Zasoby |
| `SelectedResource` | string | Wybrany zasób |
| `HideDateField` | boolean | Ukryj pole daty |
#### Widoki Scheduler (enumSchedulerViews)
- `Daily` - widok jednego dnia
- `WorkWeek` - widok tygodnia roboczego
- `Weekly` - widok tygodniowy
- `Monthly` - widok miesięczny
- `HoursTimeLine` - widok godzinowy na osi poziomej
- `DaysTimeLine` - widok dzienny na osi poziomej
- `SimpleMonthly` - uproszczony widok miesięczny
### Gantt
Wykres Gantta.
```xml
<Gantt EditValue="{Zadania}"
ViewType="WeekDay"
ViewMode="Standard"
AllowViewChanging="true"
Resources="{Zasoby}"
MethodsHandler="Handler">
<Field EditValue="{Nazwa}" />
<Field EditValue="{Start}" />
<Field EditValue="{Finish}" />
</Gantt>
```
#### GanttViews
- `HourMinute`, `DayHour`, `WeekDay`, `MonthDay`
#### GanttViewMode
- `Standard`, `ResourceView`
### GanttDiagram
Diagram Gantta z dodatkowymi opcjami.
```xml
<GanttDiagram EditValue="{Zadania}"
WorkTimeStart="08:00"
WorkTimeFinish="17:00"
WorkOnSaturday="false"
WorkOnSunday="false"
MarkHolidays="true" />
```
### Diagram
Diagram ogólny.
```xml
<Diagram EditValue="{Elementy}" MethodsHandler="DiagramHandler" />
```
### CustomDiagram
Diagram niestandardowy.
### TreeDiagram
Diagram drzewa.
```xml
<TreeDiagram EditValue="{Węzły}"
LayoutType="OrganizationalChart"
MethodsHandler="TreeHandler" />
```
#### TreeDiagramLayoutType
- `OrganizationalChart` - schemat organizacyjny
- `ComplexHierarchicalTree` - złożone drzewo hierarchiczne
### KanbanDiagram
Tablica Kanban.
```xml
<KanbanDiagram EditValue="{Zadania}" MethodsHandler="KanbanHandler" />
```
### Pivot
Tabela przestawna.
```xml
<Pivot EditValue="{Dane}">
<Axis Direction="X" EditValue="{Kategoria}" />
<Axis Direction="Y" EditValue="{Wartość}" />
</Pivot>
```
### PivotGrid
Siatka przestawna.
---
## Elementy specjalne
### Indicator
Wskaźnik liczbowy.
```xml
<Indicator CaptionHtml="Sprzedaż"
EditValue="{Wartość}"
UnitSymbol="PLN"
TimeSpanSymbol="miesiąc"
MethodName="Szczegóły" />
```
### PercentIndicator
Wskaźnik procentowy.
```xml
<PercentIndicator EditValue="{Procent}"
StrokeWidth="10"
StrokeColor="Green" />
```
### CircularIndicator
Wskaźnik kołowy.
```xml
<CircularIndicator EditValue="{Dane}"
Title="Tytuł"
LegendPosition="Right" />
```
#### UIAlignment
- `None`, `Left`, `Right`, `Bottom`
### RangeSlider
Suwak zakresu.
```xml
<RangeSlider EditValue="{Zakres}"
Min="0"
Max="100"
Step="5" />
```
### TimelineClock
Oś czasu z zegarem.
```xml
<TimelineClock EditValue="{Zdarzenia}" LegendPosition="Bottom" />
```
### DateNavigator
Navigator dat.
```xml
<DateNavigator EditValue="{WybranaData}" />
```
### Chips
Etykiety/tagi.
```xml
<Chips EditValue="{Tagi}" BgColor="GreenPastel" />
```
#### ChipsColorPalette
- `None`, `Black`, `White`
- `GrayPastel`, `GreenPastel`, `OrangePastel`, `RedPastel`
### Html
Treść HTML.
```xml
<Html EditValue="{TrescHtml}"
Width="*"
Height="200"
ScrollBarsEnabled="true" />
```
### Markdown
Treść Markdown.
```xml
<Markdown EditValue="{TrescMd}" ScrollBarsEnabled="true" />
```
### ThreadComments
Komentarze wątkowe.
```xml
<ThreadComments EditValue="{Komentarze}" MethodsHandler="CommentsHandler" />
```
### UserControl
Kontrolka użytkownika.
```xml
<UserControl TypeName="MojaKontrolka">
<Data Name="Param1" Value="Wartość" />
</UserControl>
```
### Template
Szablon warunkowy.
```xml
<Template Visibility="{Warunek}" AllowUpdating="true">
<!-- zawartość wyświetlana gdy warunek spełniony -->
</Template>
```
---
## Typy wyliczeniowe
### enumAggregationType (Footer/Aggregate)
- `Auto` - automatycznie
- `None` - brak
- `Sum` - suma
- `Count` - liczba
- `Average` - średnia
- `Min` - minimum
- `Max` - maksimum
- `Concat` - konkatenacja
- `UniqueConcat` - unikalna konkatenacja
- `Same` - ta sama wartość
### enumDataFormView (ViewType)
- `None`, `Dialog`, `Form`, `Folder`
### enumDataFormMode (Mode)
- `None`, `Form`, `Folder`, `Wizard`, `Modal`, `Popup`, `Frame`
### enumLayoutMode
- `Default`, `Canvas`, `Size`, `Visibility`
### enumMoreButtonState
- `None`, `Visible`, `Actions`
---
## Wspólne atrybuty (uiElement)
Wszystkie elementy UI dziedziczą następujące atrybuty z `uiElement`:
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Name` | string | Identyfikator elementu (musi być unikalny na poziomie strony). Automatycznie generowany jeśli nie podano. |
| `DataContext` | string (bindowalne) | Kontekst danych. `{DataSource}` = otwarty obiekt. Można wskazać podrzędną właściwość. |
| `EditValue` | string (bindowalne) | Binding do wartości |
| `CaptionHtml` | string (bindowalne) | Etykieta kontrolki (tekst lub `{Właściwość}`) |
| `CaptionMarkdown` | string | Etykieta Markdown |
| `DescriptionHtml` | string | Dodatkowy opis |
| `LangContext` | string | Kontekst językowy |
| `Icon` | string | Ikona |
| `Class` | string | Klasy stylów (lista wartości oddzielonych spacją) |
| `Width` | string | Szerokość w znakach lub px (np. `"50px"`). `"*"` = dopasuj do dostępnej przestrzeni |
| `Height` | string | Wysokość w wierszach lub px. `"*"` = dopasuj automatycznie |
| `OuterWidth` | string | Całkowita szerokość z etykietą (do wyrównywania kontrolek) |
| `OuterHeight` | string | Całkowita wysokość (może dodawać puste miejsce pod kontrolką) |
| `LabelWidth` | string | Szerokość etykiety |
| `LabelHeight` | string | Wysokość etykiety |
| `Column` | integer | Kolumna (w siatce) |
| `Row` | integer | Wiersz (w siatce) |
| `Visibility` | string (bindowalne) | Widoczność: `Visible`, `Hidden`, `Collapsed`, `true`, `false` |
| `LayoutMode` | enum | Tryb układu: `Default`, `Canvas`, `Size`, `Visibility` |
| `IsReadOnly` | string (bindowalne) | Tylko do odczytu (`true`/`false`). **Uwaga:** tryb z logiki biznesowej ma wyższy priorytet |
| `Tag` | string | Dodatkowa wartość do wykorzystania w skryptach |
| `TagInfo` | string | Informacja tagu |
| `Priority` | integer | Priorytet |
| `RenderMethodName` | string | Metoda renderowania |
| `Renderable` | string | Czy renderowalne |
| `RenderKey` | string | Klucz renderowania |
### Appearance (formatowanie warunkowe)
```xml
<Field EditValue="{Wartość}">
<Appearance Condition="{?Wartość&lt;0}"
BackColor="LightPink"
ForeColor="Red"
FontBold="true"
FontItalic="false" />
</Field>
```
| Atrybut | Typ | Opis |
|---------|-----|------|
| `Condition` | string | Warunek (wyrażenie) |
| `BackColor` | string | Kolor tła |
| `ForeColor` | string | Kolor tekstu |
| `FontBold` | boolean | Pogrubienie |
| `FontItalic` | boolean | Kursywa |
---
## Wartości Class (enumSingleClass)
### Zachowania kontenerów
- `Collapsable` - zwijalna
- `Expandable` - rozwijalna
- `Expanded` - rozwinięta
- `Dialog` - okno dialogowe
- `NoSave` - bez zapisu
- `MainPage` - strona główna
- `Menu` - menu
- `Panel`, `PanelItem`, `PanelWinItem`
- `NoLayout` - bez układu
- `RemoveEmpty` - usuń puste
- `GroupItem` - element grupy
- `Reverse` - odwrócony
- `MainGroup`, `MenuGroup`
- `NoClose` - bez zamykania
- `CascadeMenu`, `CascadeMenuGroup`, `CascadeSubmenuGroup`
- `FilterGroup` - grupa filtrów
- `Scrollable` - przewijalna
### Style przycisków
- `PrintButton` - drukowanie
- `MainCommand` - główne polecenie
- `SplitCommand` - polecenie dzielone
- `CommandNoText` - bez tekstu
- `CommandIcoText` - ikona i tekst
- `WorkerCommand` - polecenie workera
- `WizardCommand` - polecenie kreatora
- `SchedulerCommand` - polecenie harmonogramu
- `FormNavigationCommand` - nawigacja formularza
### Style pól
- `PasswordEdit`, `PathPropertyEdit`, `PropertyGridEdit`
- `CheckButtonEdit`, `ColorEdit`, `HistoryEdit`
- `RichEdit`, `AspxEdit`, `FolderEdit`, `FileEdit`
- `SaveFileEdit`, `ImageEdit`, `XmlEdit`
- `AlgorithmEdit`, `DataTextEdit`, `ConditionEdit`
- `RatingEdit`, `SignatureEdit`, `OneTimePasswordEdit`
- `HyperlinkEdit`, `EmailEdit`, `PhoneEdit`
- `SkypeEdit`, `GpsEdit`, `IconEdit`
- `ProgressEdit`, `TrafficLightEdit`
### Style etykiet
- `NoColonLabel` - bez dwukropka
- `BoldLabel` - pogrubiona
- `CenterLabel` - wyśrodkowana
- `RightLabel` - wyrównana w prawo
- `WarningLabel` - ostrzeżenie
- `MultilineLabel` - wieloliniowa
- `InfoLabel` - informacja
- `TipLabel` - podpowiedź
- `SchedulerLabel` - etykieta harmonogramu
### Style czcionek
- `LargeFont` - duża
- `GreenFont` - zielona
- `RedFont` - czerwona
- `FixedWidthFont` - stała szerokość
- `BoldFont` - pogrubiona
- `WarningFont` - ostrzegawcza
### Wyrównanie
- `RightAlign` - do prawej
- `LeftAlign` - do lewej
- `TextRight` - tekst do prawej
### Inne
- `Information`, `Question` - typy komunikatów
- `DataBar`, `PreviewLine`, `Header`
- `FirstResponder` - pierwszy fokus
- `SmartOpen` - inteligentne otwieranie
- `Tight`, `Special`, `Important`
- `LateCalculate` - późne obliczanie
- `AllowDragging`, `AllowEditing`
- `DisableSelection` - wyłącz zaznaczanie
- `HorizontalSplitter` - poziomy rozdzielacz
- `Info`, `Tree`
- `ImageCircle` - okrągły obraz
- `DashboardItem`, `LocatorItem`
- `SmallSize`, `NormalSize`, `LargeSize`
- `AutoUpdate` - automatyczna aktualizacja
- `ArrowsSelectNext` - strzałki wybierają następny
- `Hidden` - ukryty
- `NonClickable` - nieklikowalny
- `LabelTop`, `LebelLeft` - pozycja etykiety
- `FilesDropTarget` - cel upuszczania plików
- `Rss` - kanał RSS
- `PreventOrderBy` - zapobiegaj sortowaniu
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,78 @@
[
{
"query": "utwórz zakładkę pageform.xml dla obiektu Dokument z polami Numer, Data, Kontrahent i listą pozycji",
"should_trigger": true
},
{
"query": "jak zrobić widok listy viewform.xml dla Kontrahentów z kolumnami Kod, Nazwa, NIP, Miasto?",
"should_trigger": true
},
{
"query": "potrzebuję plik Adres.form.xml jako współdzielony fragment z polami adresowymi do użycia przez Include",
"should_trigger": true
},
{
"query": "jak ukryć pole w form.xml enova365 gdy Status nie jest równy 'Aktywny'? co to Visibility i RowCondition?",
"should_trigger": true
},
{
"query": "zrób mi zakładkę Towar.Ogolne.pageform.xml z grupą 'Dane podstawowe' i grupą z dwukolumnowym układem Row Stack",
"should_trigger": true
},
{
"query": "jak dodać Grid z IsToolbarVisible EditInPlace NewInPlace i Footer Sum do pageform.xml?",
"should_trigger": true
},
{
"query": "potrzebuję lookupform.xml dla wyboru Towaru z kolumnami Kod Nazwa Cena",
"should_trigger": true
},
{
"query": "co to Class Collapsable w enova365? chcę zwinąć grupę filtrów we ViewInfo i uzależnić Renderable od licencji HAN",
"should_trigger": true
},
{
"query": "jak w viewform.xml dodać Flow jako panel filtrów nad gridem? chcę użyć FilterPanelWidth i operatora + w EditValue",
"should_trigger": true
},
{
"query": "chcę zrobić Appearance warunkowe formatowanie wierszy w Grid — jak ustawić ForeColor gdy Typ='usługa'?",
"should_trigger": true
},
{
"query": "napisz mi metodę w C# która oblicza VAT dla pozycji faktury w enova365",
"should_trigger": false
},
{
"query": "jak skonfigurować business.xml dla nowego modułu? potrzebuję definicję tabeli z relacją do Kontrahenta",
"should_trigger": false
},
{
"query": "zrób raport RDLC pokazujący listę faktur z podsumowaniem",
"should_trigger": false
},
{
"query": "jak zarejestrować FolderViewAttribute i WorkerAttribute w enova365?",
"should_trigger": false
},
{
"query": "jak zbudować API REST w ASP.NET Core do pobierania danych kontrahentów?",
"should_trigger": false
},
{
"query": "zrób mi worker C# który liczy saldo kontrahenta i eksponuje je jako właściwość w enova365",
"should_trigger": false
},
{
"query": "jak skonfigurować uprawnienia RightName i RightContext dla modułu enova365?",
"should_trigger": false
},
{
"query": "jak zmodyfikować istniejący pageform.xml — chcę dodać nowe pole do już istniejącej zakładki Ogólne Towaru",
"should_trigger": true
},
{
"query": "jak używać DataContext i EditValue żeby wyświetlić pola zagnieżdżonego obiektu np. Adres.Miasto w formularzu enova365?",
"should_trigger": true
}
]
@@ -0,0 +1,82 @@
[
{
"query": "utwórz zakładkę pageform.xml dla obiektu Dokument z polami Numer, Data, Kontrahent i listą pozycji",
"should_trigger": true
},
{
"query": "jak zrobić widok listy viewform.xml dla Kontrahentów z kolumnami Kod, Nazwa, NIP, Miasto?",
"should_trigger": true
},
{
"query": "potrzebuję plik Adres.form.xml jako współdzielony fragment z polami adresowymi do użycia przez Include",
"should_trigger": true
},
{
"query": "jak ukryć pole w form.xml enova365 gdy Status nie jest równy 'Aktywny'? co to Visibility i RowCondition?",
"should_trigger": true
},
{
"query": "zrób mi zakładkę Towar.Ogolne.pageform.xml z grupą 'Dane podstawowe' i grupą z dwukolumnowym układem Row Stack",
"should_trigger": true
},
{
"query": "jak dodać Grid z IsToolbarVisible EditInPlace NewInPlace i Footer Sum do pageform.xml?",
"should_trigger": true
},
{
"query": "potrzebuję lookupform.xml dla wyboru Towaru z kolumnami Kod Nazwa Cena",
"should_trigger": true
},
{
"query": "co to Class Collapsable w enova365? chcę zwinąć grupę pól w formularzu i uzależnić Renderable od licencji HAN",
"should_trigger": true
},
{
"query": "jak w viewform.xml dodać Flow jako panel filtrów nad gridem? chcę użyć FilterPanelWidth i operatora + w EditValue",
"should_trigger": true
},
{
"query": "chcę zrobić Appearance warunkowe formatowanie wierszy w Grid — jak ustawić ForeColor gdy Typ='usługa'?",
"should_trigger": true
},
{
"query": "napisz mi metodę w C# która oblicza VAT dla pozycji faktury w enova365",
"should_trigger": false
},
{
"query": "jak skonfigurować business.xml dla nowego modułu? potrzebuję definicję tabeli z relacją do Kontrahenta",
"should_trigger": false
},
{
"query": "zrób raport RDLC pokazujący listę faktur z podsumowaniem",
"should_trigger": false
},
{
"query": "jak zarejestrować FolderViewAttribute i WorkerAttribute w enova365?",
"should_trigger": false
},
{
"query": "jak zrobić formularz HTML w React z polami adresowymi? potrzebuję Formik i yup validation",
"should_trigger": false
},
{
"query": "jak zbudować API REST w ASP.NET Core do pobierania danych kontrahentów?",
"should_trigger": false
},
{
"query": "zrób mi worker C# który liczy saldo kontrahenta i eksponuje je jako właściwość w enova365",
"should_trigger": false
},
{
"query": "jak skonfigurować uprawnienia RightName i RightContext dla modułu enova365?",
"should_trigger": false
},
{
"query": "jak zmodyfikować istniejący pageform.xml — chcę dodać nowe pole do już istniejącej zakładki Ogólne Towaru",
"should_trigger": true
},
{
"query": "jak używać DataContext i EditValue żeby wyświetlić pola zagnieżdżonego obiektu np. Adres.Miasto w formularzu enova365?",
"should_trigger": true
}
]
+168 -520
View File
@@ -1,12 +1,10 @@
--- ---
name: soneta-form-xml name: soneta-form-xml
description: Tworzenie plików form.xml opisujących formularze, zakładki i widoki UI dla platformy enova365/Soneta Enterprise. Używaj gdy użytkownik prosi o utworzenie zakładki formularza (pageform.xml), widoku listy (viewform.xml), formularza (form.xml), lookupu (lookupform.xml), lub gdy pyta o strukturę i składnię plików form.xml dla enova365. description: "Specjalistyczna wiedza o WŁASNOŚCIOWYM formacie plików form.xml platformy enova365/Soneta — bez tego skilla Claude generuje błędne XML z nieistniejącymi elementami. ZAWSZE używaj tego skilla gdy użytkownik: (1) prosi o utworzenie lub modyfikację pliku pageform.xml, viewform.xml, form.xml, lookupform.xml lub gridform.xml dla enova365/Soneta; (2) pyta o elementy DataForm, Page, Group, Grid, Field, Row, Stack, Flow, Command, Include, Appearance, GroupBy w enova365; (3) pyta o składnię EditValue, DataContext, Visibility, RowCondition, Renderable, CaptionHtml, Footer, Class lub układ UI formularzy enova365; (4) pokazuje istniejący plik form.xml/pageform.xml/viewform.xml i pyta o jego strukturę lub chce go rozszerzyć; (5) pyta o warunkową widoczność, formatowanie warunkowe (Appearance), bindowanie danych lub wzorce UI w Soneta/enova365."
--- ---
# Soneta Form XML - Formularze UI # Soneta Form XML - Formularze UI
Skill do tworzenia plików XML definiujących interfejs użytkownika w systemie enova365/Soneta Enterprise.
## Typy plików formularzy ## Typy plików formularzy
| Typ pliku | Wzorzec nazwy | Przeznaczenie | | Typ pliku | Wzorzec nazwy | Przeznaczenie |
@@ -17,72 +15,11 @@ Skill do tworzenia plików XML definiujących interfejs użytkownika w systemie
| **lookupform.xml** | `{NazwaPodpowiedzi}.lookupform.xml` | Lista wyboru (lookup) | | **lookupform.xml** | `{NazwaPodpowiedzi}.lookupform.xml` | Lista wyboru (lookup) |
| **form.xml** | `{Nazwa}.form.xml` | Współdzielony fragment UI (include) | | **form.xml** | `{Nazwa}.form.xml` | Współdzielony fragment UI (include) |
### Format nazwy pageform.xml **Przykłady pageform.xml:** `Towar.Ogolne.pageform.xml`, `Kontrahent.Adresy.pageform.xml`
Nazwa pliku składa się z 4 części rozdzielonych kropkami:
```
{DataType}.{PageName}.pageform.xml
```
- **DataType** - typ danych, dla którego definiowana jest zakładka (np. `Towar`, `Kontrahent`, `DokumentHandlowy`)
- **PageName** - nazwa zakładki (np. `Ogolne`, `Dodatkowe`, `Adresy`)
- **pageform.xml** - stały sufiks
**Przykłady:**
- `Towar.Ogolne.pageform.xml`
- `Towar.Dodatkowe.pageform.xml`
- `Kontrahent.Adresy.pageform.xml`
- `DokumentHandlowy.Pozycje.pageform.xml`
### Format nazwy viewform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{NazwaWidoku}.viewform.xml
```
**Przykłady:**
- `Towary.viewform.xml`
- `Kontrahenci.viewform.xml`
- `DokumentyHandlowe.viewform.xml`
### Format nazwy gridform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{IdentyfikatorListy}.gridform.xml
```
**Przykłady:**
- `PozycjeDokumentu.gridform.xml`
- `RachunkiBankowe.gridform.xml`
### Format nazwy lookupform.xml
Nazwa pliku składa się z 3 części rozdzielonych kropkami:
```
{NazwaPodpowiedzi}.lookupform.xml
```
**Przykłady:**
- `Towary.lookupform.xml`
- `Kontrahenci.lookupform.xml`
## Hierarchia elementów XML
Elementy XML dzielą się na trzy grupy dziedziczące po `uiElement`:
1. **Elementy proste** - Field, Label, Command, Gap, Html, GroupBy, Axis
2. **Kontenery elementów** - Group, Stack, Row, Flow, Bar, Dashboard, Include, Page (dziedziczą po `ContainerElement`)
3. **Kolekcje** - Grid, Cards, Scheduler, Chart, Diagram, Pivot (dziedziczą po `CollectionElement`)
## Struktura dokumentu ## Struktura dokumentu
Każdy plik formularza zaczyna się od deklaracji XML i elementu głównego `DataForm`: Każdy plik formularza zaczyna się od deklaracji XML i elementu `DataForm`:
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
@@ -99,47 +36,41 @@ Każdy plik formularza zaczyna się od deklaracji XML i elementu głównego `Dat
| Atrybut | Opis | | Atrybut | Opis |
|---------|------| |---------|------|
| `Priority` | Kolejność zakładek (domyślnie 100, niższa = wcześniej) | | `Priority` | Kolejność zakładek (domyślnie 100, niższa = wcześniej) |
| `RightName` | Opcjonalny. Nazwa uprawnienia do zakładki (tylko gdy inna niż standardowa) | | `RightName` | Opcjonalny. Nazwa uprawnienia do zakładki |
| `Contexts` | Warunki licencyjne, np. `"Licence.HAN \| Licence.FA"` (nie bindowane) | | `Contexts` | Warunki licencyjne, np. `"Licence.HAN \| Licence.FA"` |
| `ViewType` | Typ widoku: `None`, `Dialog`, `Form`, `Folder` | | `ViewType` | Typ widoku: `None`, `Dialog`, `Form`, `Folder` |
| `Mode` | Tryb: `None`, `Form`, `Folder`, `Wizard`, `Modal`, `Popup`, `Frame` | | `Mode` | Tryb: `None`, `Form`, `Folder`, `Wizard`, `Modal`, `Popup`, `Frame` |
| `DataType` | Opcjonalny. Pełne określenie typu danych (wymagany tylko gdy nazwa pliku nie określa jednoznacznie typu), np. `"Soneta.Handel.DokumentHandlowy,Soneta.Handel"` | | `DataType` | Opcjonalny. Pełna nazwa typu gdy nie wynika z nazwy pliku |
## Wspólne atrybuty elementów ## Wspólne atrybuty elementów
Następujące atrybuty mogą być użyte w **dowolnym** elemencie form.xml:
| Atrybut | Opis | | Atrybut | Opis |
|---------|------| |---------|------|
| `Name` | Identyfikator elementu, który można wykorzystać w kodzie C# | | `Name` | Identyfikator elementu (dostępny w kodzie C#) |
| `Class` | Klasy stylów (lista wartości oddzielonych spacją) | | `Class` | Klasy stylów (lista wartości oddzielonych spacją) |
| `DataContext` | Zmienia kontekst danych dla elementu i wszystkich jego elementów podrzędnych | | `DataContext` | Zmienia kontekst danych dla elementu i elementów podrzędnych |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową) | | `Visibility` | Warunek widoczności (bindowalne): `true`/`false`/`{wyrażenie}` |
| `Renderable` | Czy element ma być dostępny. Wyrażenie liczone **raz** przy logowaniu operatora - optymalne dla warunków zależnych od środowiska, licencji i innych parametrów niezmiennych w trakcie sesji | | `Renderable` | Czy element ma być dostępny liczone **raz** przy logowaniu |
| `Width` | Szerokość w znakach lub px; `"*"` = wypełnij |
| `Height` | Wysokość w wierszach lub px; `"*"` = wypełnij |
### Atrybut CaptionHtml ### Atrybut CaptionHtml
Atrybut `CaptionHtml` występuje w elementach: `Label`, `Field`, `Group`, `Page`, `Command` i innych.
Może zawierać:
- Tekst etykiety (w formacie HTML) - Tekst etykiety (w formacie HTML)
- Wyrażenia bindowane w klamrach: `{wyrażenie}` - wartość tekstowa jest automatycznie kodowana do HTML - Wyrażenia bindowane: `{Właściwość}` wartość automatycznie kodowana do HTML
- Wyrażenia zwracające kod HTML: `{WłaściwośćHtml}` - nazwa musi mieć sufiks `Html`, wtedy wartość nie jest kodowana - Wyrażenia HTML: `{WłaściwośćHtml}` sufiks `Html` wyłącza kodowanie
- Podwójne klamry dla literalnych znaków: `{{``{`, `}}``}` - Podwójne klamry dla literałów: `{{``{`
- Alternatywa: `CaptionMarkdown` dla Markdown
**Specjalne przypadki w `Field`:** **Specjalne przypadki w `Field`:**
- Brak atrybutu → automatyczna etykieta wyliczana na podstawie danych - Brak atrybutu → automatyczna etykieta wyliczana na podstawie danych
- `CaptionHtml=" "` (spacja) → pusta etykieta (miejsce na etykietę zostaje zachowane) - `CaptionHtml=" "` (spacja) → pusta etykieta (miejsce zachowane)
- `CaptionHtml=""` (pusty) → brak etykiety (pole bez miejsca na etykietę) - `CaptionHtml=""` (pusty) → brak etykiety i miejsca
**Alternatywa:** Zamiast `CaptionHtml` można użyć `CaptionMarkdown` dla etykiet w formacie Markdown.
## Elementy kontenerowe ## Elementy kontenerowe
### Page - Zakładka ### Page - Zakładka
Główny kontener dla zawartości zakładki:
```xml ```xml
<Page CaptionHtml="Ogólne" DataContext="{DataSource}"> <Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<!-- zawartość zakładki --> <!-- zawartość zakładki -->
@@ -148,224 +79,114 @@ Główny kontener dla zawartości zakładki:
| Atrybut | Opis | | Atrybut | Opis |
|---------|------| |---------|------|
| `Name` | Opcjonalny. Unikalny identyfikator zakładki | | `CaptionHtml` | Tytuł; może zawierać `/` do grupowania (np. `"Dokumenty/Faktury"`) |
| `CaptionHtml` | Tytuł zakładki. Może zawierać `/` do grupowania zakładek (np. `"Dokumenty/Faktury"`) | | `DataContext` | Źródło danych; `{DataSource}` = obiekt edytowany |
| `DataContext` | Źródło danych. `{DataSource}` oznacza obiekt edytowany na zakładce, ale można wskazać inne dane |
| `Visibility` | Wyrażenie warunkowe widoczności (bindowalne) | | `Visibility` | Wyrażenie warunkowe widoczności (bindowalne) |
| `Renderable` | Czy zakładka ma być dostępna. Wyrażenie liczone raz przy logowaniu - optymalne dla warunków zależnych od środowiska, licencji itp. | | `Renderable` | Liczone raz przy logowaniu dla warunków licencji/środowiska |
| `Key` | Skrót klawiaturowy wywołujący zakładkę formularza | | `Key` | Skrót klawiaturowy |
| `GroupIcon` | Ikona grupy zakładek |
### Zasada budowania zakładki formularza ### Group - Grupa pól
Zakładka składa się z elementów `<Group>`. Każda grupa może zawierać:
1. **Listę pól w kolumnie** - pola ułożone pionowo jedno pod drugim
2. **Układ wielokolumnowy** - `<Row>` zawierający kilka `<Stack>` z polami
3. **Listę elementów podrzędnych** - np. Grid, ewentualnie poprzedzony polami filtrującymi
```xml ```xml
<Page CaptionHtml="Ogólne" DataContext="{DataSource}"> <Group CaptionHtml="Dane podstawowe" LabelWidth="20">
<!-- Grupa z polami w jednej kolumnie -->
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" /> <Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" /> <Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Group> </Group>
```
<!-- Grupa z układem dwukolumnowym --> `LabelWidth` ustawia szerokość etykiet dla wszystkich pól w grupie.
<Group CaptionHtml="Dane szczegółowe">
### Stack, Row, Flow - Układ elementów
```xml
<!-- Stack: układ pionowy (elementy jeden pod drugim) -->
<Stack LabelWidth="15">
<Field CaptionHtml="Pole 1" EditValue="{Pole1}" />
</Stack>
<!-- Row: układ poziomy -->
<Row> <Row>
<Stack> <Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Data" Width="15" EditValue="{Data}" /> <Gap Width="*" /> <!-- przesuwa kolejne elementy do prawej -->
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" /> <Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Stack> </Row>
<Stack>
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" /> <!-- Flow: elementy od lewej do prawej z zawijaniem -->
<Field CaptionHtml="Źródło" Width="15" EditValue="{Zrodlo}" /> <Flow Align="true">
</Stack> <Field CaptionHtml="Data od" Width="15" EditValue="{DataOd}" />
<Field CaptionHtml="Data do" Width="15" EditValue="{DataDo}" />
</Flow>
```
**Układ dwukolumnowy:** `<Row>` zawierający dwa `<Stack>`.
### Zasada budowania zakładki
```xml
<Page CaptionHtml="Ogólne" DataContext="{DataSource}">
<Group CaptionHtml="Dane podstawowe">
<!-- pola pionowo -->
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<!-- lub wielokolumnowo: -->
<Row>
<Stack><Field ... /></Stack>
<Stack><Field ... /></Stack>
</Row> </Row>
</Group> </Group>
<!-- Grupa z listą -->
<Group CaptionHtml="Pozycje"> <Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*" EditValue="{Pozycje}"> <Grid Width="*" Height="*" EditValue="{Pozycje}" IsToolbarVisible="true">
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" /> <Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Grid> </Grid>
</Group> </Group>
</Page> </Page>
``` ```
### Group - Grupa pól
Wizualna ramka grupująca powiązane pola:
```xml
<Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
</Group>
```
| Atrybut | Opis |
|---------|------|
| `CaptionHtml` | Tytuł grupy |
| `LabelWidth` | Opcjonalny. Szerokość etykiet dla wszystkich pól w kontenerze |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową) |
| `Renderable` | Czy grupa ma być dostępna (liczone raz przy logowaniu) |
### Stack - Układ pionowy
Układa elementy jeden pod drugim:
```xml
<Stack LabelWidth="15">
<Field CaptionHtml="Pole 1" EditValue="{Pole1}" />
<Field CaptionHtml="Pole 2" EditValue="{Pole2}" />
</Stack>
```
### Row - Układ poziomy
Układa elementy obok siebie w wierszu:
```xml
<Row>
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
</Row>
```
**Pole na całą szerokość:** użyj `Width="*"`
**Pola dosunięte do prawej:** umieść `<Gap Width="*"/>` na początku:
```xml
<Row>
<Gap Width="*" />
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Typ" Width="15" EditValue="{Typ}" />
</Row>
```
### Flow - Układ płynny
Elementy umieszczane są od lewej do prawej. Gdy nie mieszczą się na formularzu, przenoszone są do nowego wiersza:
```xml
<Flow Align="true">
<Field CaptionHtml="Data od" Width="15" EditValue="{DataOd}" />
<Field CaptionHtml="Data do" Width="15" EditValue="{DataDo}" />
<Field CaptionHtml="Status" Width="12" EditValue="{Status}" />
</Flow>
```
## Elementy pól i kontrolek ## Elementy pól i kontrolek
### Field - Pole edycyjne ### Field - Pole edycyjne
Podstawowy element do wyświetlania i edycji danych. Jest generowany **dynamicznie** - w zależności od typu właściwości wyświetla odpowiednią kontrol (int → pole numeryczne, bool → checkbox, double → pole z kalkulatorem, typ Sonety → lookup z listą wyboru). Jest generowany **dynamicznie** typ właściwości decyduje o kontrolce (int → liczba, bool → checkbox, typ Sonety → lookup).
Minimalny `<Field>` powinien zawierać:
- `EditValue` - **wymagany**, binding do właściwości
- `CaptionHtml` - etykieta pola
- `Width` - szerokość pola
```xml ```xml
<Field CaptionHtml="Nazwa pola" Width="20" EditValue="{Właściwość}" /> <Field CaptionHtml="Nazwa pola" Width="20" EditValue="{Właściwość}"
Important="true" IsReadOnly="{Warunek}" />
``` ```
| Atrybut | Opis | | Atrybut | Opis |
|---------|------| |---------|------|
| `EditValue` | **Wymagany**. Binding do właściwości: `{Właściwość}` lub `{new Extender.Właściwość}` | | `EditValue` | **Wymagany**. Binding do właściwości: `{Właściwość}` lub `{new Ext.Właściwość}` |
| `CaptionHtml` | Etykieta pola (patrz sekcja "Atrybut CaptionHtml") | | `CaptionHtml` | Etykieta pola |
| `Width` | Szerokość pola w znakach lub px (`*` = wypełnij) | | `Width` | Szerokość pola (`*` = wypełnij) |
| `OuterWidth` | Całkowita szerokość z etykietą (do wyrównywania w pionie) | | `Height` | Wysokość (dla pól wieloliniowych) |
| `LabelWidth` | Szerokość etykiety | | `Important` | `true` — pole oznaczone jako ważne (wyróżnione w widoku) |
| `Height` | Wysokość w wierszach lub px (dla pól wieloliniowych) | | `IsReadOnly` | Warunek tylko do odczytu (bindowalne) |
| `IsReadOnly` | Warunek tylko do odczytu (bindowalne z logiką biznesową). Logika biznesowa ma wyższy priorytet | | `Format` | Formatowanie w standardzie .NET: `N2`, `d`, `C` |
| `Visibility` | Warunek widoczności (bindowalne z logiką biznesową): `true`/`false`/`Visible`/`Hidden`/`Collapsed` | | `Footer` | Agregacja w stopce listy: `Sum`, `Count`, `Average`, `Min`, `Max` |
| `Renderable` | Czy pole ma być dostępne (liczone raz przy logowaniu) | | `CheckedValue` | Wartość dla RadioButton |
| `Format` | Formatowanie wartości w standardzie .NET `string.Format`. Pole `{0}` to wartość edytowana | | `Class` | Klasy stylów |
| `Footer` | Agregacja w stopce **tylko na listach**: `Sum`, `Count`, `Average`, `Min`, `Max` |
| `CheckedValue` | Wartość dla **RadioButton** |
| `Class` | Klasy stylów (patrz sekcja Class) |
| `DataContext` | Zmienia kontekst danych dla tego pola i elementów podrzędnych |
#### RadioButton
Aby utworzyć RadioButton, dodaj parametr `CheckedValue`:
**RadioButton** — pola z tym samym `EditValue` i różnymi `CheckedValue`:
```xml ```xml
<Field Width="20" CaptionHtml="Towar" EditValue="{Typ}" CheckedValue="Towar" /> <Field Width="15" CaptionHtml="Towar" EditValue="{Typ}" CheckedValue="Towar" />
<Field Width="20" CaptionHtml="Usługa" EditValue="{Typ}" CheckedValue="Usługa" /> <Field Width="15" CaptionHtml="Usługa" EditValue="{Typ}" CheckedValue="Usługa" />
<Field Width="20" CaptionHtml="Receptura" EditValue="{Typ}" CheckedValue="Receptura" />
``` ```
Pola z tym samym `EditValue` i różnymi `CheckedValue` tworzą grupę RadioButton. ### Label, Gap, Command, Include
### Label - Etykieta
Tekst bez możliwości edycji:
```xml ```xml
<Label CaptionHtml="Tekst informacyjny" Width="30" /> <Label CaptionHtml="Tekst informacyjny" Width="30" />
``` <Gap Width="*" /> <!-- wypełniacz; pusty na końcu wiersza nic nie zmienia -->
### Gap - Odstęp <Command CaptionHtml="Zapisz" MethodName="Zapisz"
DataContext="{new MojExtender}" Visibility="{IsVisible}"
Wypełniacz przestrzeni. Użyteczny do dosunięcia elementów do prawej strony (gdy `<Gap Width="*" />` jest na początku wiersza). CommandStyle="Important" Key="F5" />
```xml
<Row>
<Gap Width="*" />
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
</Row>
```
**Uwaga:** `<Gap Width="*" />` jako ostatni element w wierszu nie jest potrzebny - nic nie zmienia.
### Command - Przycisk/Polecenie
```xml
<Command CaptionHtml="Zapisz"
MethodName="Zapisz"
DataContext="{new MojExtender}"
Visibility="{IsVisibleButton}" />
```
| Atrybut | Opis |
|---------|------|
| `MethodName` | Nazwa metody do wywołania (szukana w klasie z kontekstu formularza) |
| `MoreMethodName` | Dodatkowa metoda (dla przycisków dzielonych - wersja przeglądowa) |
| `Key` | Skrót klawiszowy |
| `CommandStyle` | Styl: `Default`, `Important`, `Red`, `Green`, `Blue` |
| `Icon` | Nazwa ikony (nie działa w enova365 desktop) |
| `Class` | Klasy stylów |
| `DataContext` | Zmienia kontekst danych (np. `{new MojExtender}` - patrz sekcja Bindowanie danych) |
| `Renderable` | Czy przycisk ma być dostępny (liczone raz przy logowaniu) |
### Include - Dołączenie fragmentu
Wstawia zawartość innego pliku form.xml lub dynamicznie generowany element UI:
```xml
<!-- Statyczne dołączenie pliku -->
<Include Source="Adres.form.xml" />
<!-- Z kontekstem danych -->
<Include Source="Adres.form.xml" DataContext="{AdresKorespondencyjny}" />
<!-- Dołączenie pliku form.xml -->
<Include Source="Adres.form.xml" DataContext="{Adres}" />
<!-- Dynamiczny element z kodu C# --> <!-- Dynamiczny element z kodu C# -->
<Include Source="{DynamicznyFormularz}" /> <Include Source="{DynamicznyFormularz}" />
``` ```
| Atrybut | Opis |
|---------|------|
| `Source` | Nazwa pliku form.xml **lub** wyrażenie bindujące zwracające element DOM (`UIElement`) z kodu. Wyrażenie bindujące jest wywoływane po każdej zmianie danych, co pozwala budować dynamiczne formularze |
| `DataContext` | Opcjonalny. Kontekst danych dla dołączanego fragmentu |
| `Path` | Opcjonalny. Określa element pliku form.xml, który zostanie wstawiony (gdy Source jest nazwą pliku) |
| `Suffix` | Opcjonalny. Napis dodawany do każdej nazwy (`Name`) elementów dołączonych przez Include |
## Kolekcje i listy ## Kolekcje i listy
### Grid / List - Tabela danych ### Grid / List - Tabela danych
@@ -373,308 +194,109 @@ Wstawia zawartość innego pliku form.xml lub dynamicznie generowany element UI:
```xml ```xml
<Grid Width="*" Height="*" <Grid Width="*" Height="*"
EditValue="{Pozycje}" EditValue="{Pozycje}"
SelectedValue="{WybranePozycje}"
FocusedValue="{AktualnaPozycja}"
IsToolbarVisible="true" IsToolbarVisible="true"
IsFilterRowVisible="false"
EditInPlace="true" EditInPlace="true"
NewInPlace="true" NewInPlace="true"
OrderBy="Data desc" OrderBy="Data desc"
SumType="All" SumType="All"
OpenMethodName="OtworzFormularz" FilterPanelWidth="136"
IsSmartOpen="true"> SelectedValue="{WybranePozycje}"
FocusedValue="{AktualnaPozycja}">
<Field CaptionHtml="Kod" Width="15" EditValue="{Kod}" /> <Field CaptionHtml="Kod" Width="15" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="30" EditValue="{Nazwa}" /> <Field CaptionHtml="Ilość" Width="10" EditValue="{Ilosc}" Footer="Sum" />
<Field CaptionHtml="Ilość" Width="10" EditValue="{Ilość}" Footer="Sum" />
<GroupBy EditValue="{Kategoria}" IsDescending="false" /> <GroupBy EditValue="{Kategoria}" IsDescending="false" />
<UserFilter Value="Status='Aktywny'" />
<Data Name="nazwaParametru" Value="wartość" />
</Grid> </Grid>
``` ```
| Atrybut | Opis | Default | | Atrybut | Default | Opis |
|---------|------|---------| |---------|---------|------|
| `EditValue` | Źródło danych kolekcji | - | | `EditValue` | — | Źródło danych kolekcji |
| `SelectedValue` | Binding do zaznaczonych wierszy - typ `DataType[]` (tablica) | - | | `IsToolbarVisible` | `false` | Pasek narzędzi |
| `FocusedValue` | Binding do podświetlonego wiersza - typ `DataType` (obiekt) | - | | `IsFilterRowVisible` | `false` | Wiersz filtrujący |
| `IsToolbarVisible` | Pokazuj pasek narzędzi | `false` | | `EditInPlace` | `false` | Edycja bezpośrednio w komórkach |
| `IsFilterRowVisible` | Pokazuj wiersz filtrujący | `false` | | `NewInPlace` | `false` | Dodawanie przez kliknięcie pustego wiersza |
| `IsHeaderVisible` | Widoczność nagłówków z tytułami kolumn | `true` | | `OrderBy` | — | Domyślne sortowanie: `"Kolumna desc"` |
| `EditInPlace` | Edycja bezpośrednio w komórkach | `false` | | `FilterPanelWidth` | — | Szerokość panelu filtrów |
| `NewInPlace` | Dodawanie przez kliknięcie pustego wiersza | `false` | | `SumType` | `None` | `None`, `Selected`, `All`, `Groups`, `GroupsNewLine` |
| `AlwaysAddNewRow` | Nowy wiersz od razu dodawany (Esc nie usuwa) | `false` | | `IsSmartOpen` | — | Kolumna ze strzałką do otwarcia formularza |
| `PreventNewRowOnFocus` | Zapobiegaj nowemu wierszowi przy fokusie | `false` | | `VisibleFeatures` | — | Lista widocznych cech: `"Asortyment,Producent"` |
| `KeepsSequence` | Czy po edycji in-place zachować kolejność wierszy (`true`) czy ponownie sortować (`false`) | `false` | | `SelectedValue` | — | Binding do zaznaczonych wierszy (tablica) |
| `OpenMethodName` | Metoda wywoływana po Enter/double-click (domyślnie otwarcie formularza) | - | | `FocusedValue` | — | Binding do aktywnego wiersza |
| `IsSmartOpen` | Kolumna ze strzałką do otwarcia formularza | - |
| `NewButton` | Stan przycisku Nowy: `Auto`, `None`, `Visible` | auto |
| `EditButton` | Stan przycisku Otwórz | auto |
| `UpdateButton` | Stan przycisku Aktualizuj | auto |
| `RemoveButton` | Stan przycisku Usuń | auto |
| `SearchButton` | Stan przycisku Szukaj | auto |
| `MoreButton` | Przycisk więcej: `None`, `Visible`, `Actions` | auto |
| `OrderBy` | Domyślne sortowanie (np. `"Kolumna desc"`) | - |
| `Filter` | Filtr danych | - |
| `ResourceName` | Nazwa pliku grid.xml z indywidualnymi ustawieniami | - |
| `SumType` | Typ sum: `None`, `Selected`, `All`, `Groups`, `GroupsNewLine` | `None` |
| `ActionsMode` | Czy workery przypięte do listy mają być w menu Czynności formularza: `FormAndControl`, `Control`, `Form` | - |
#### Atrybuty dla drzewa (Tree) **Przyciski:** `NewButton`, `EditButton`, `RemoveButton`, `SearchButton` — wartości `Auto`, `None`, `Visible`.
| Atrybut | Opis | Default |
|---------|------|---------|
| `TreeNodesValue` | Binding do węzłów | - |
| `TreeHasNodesValue` | Binding sprawdzający czy ma węzły | - |
| `TreeParentValue` | Binding do rodzica | - |
| `TreeExpandingLevel` | Poziom rozwinięcia: `Collapsed`, `ExpandRoot`, `ExpandRootFix`, `ExpandAll` | `Collapsed` |
### GroupBy - Grupowanie w Grid
```xml
<Grid EditValue="{Pozycje}">
<GroupBy EditValue="{Kategoria}" />
<Field CaptionHtml="Nazwa" EditValue="{Nazwa}" />
</Grid>
```
## Elementy specjalne
### Chart - Wykres
```xml
<Chart EditValue="{DaneWykresu}"
Type="Bar"
ChartColor="Blue"
IsLegendVisible="true">
<Field CaptionHtml="Miesiąc" EditValue="{Miesiac}" />
<Field CaptionHtml="Wartość" EditValue="{Wartosc}" />
<Axis Direction="X" EditValue="{Miesiac}" />
<Axis Direction="Y" EditValue="{Wartosc}" />
</Chart>
```
Typy wykresów: `Line`, `Bar`, `Pie`, `Donut`, `Spider`, `Polar`, `Area`, `Pyramid`, `Funnel`, `Bubble`, `Scatter`
### Scheduler - Kalendarz
```xml
<Scheduler EditValue="{Zdarzenia}"
View="Weekly"
SelectedInterval="{WybranyOkres}">
<Field CaptionHtml="Tytuł" EditValue="{Tytul}" />
<Field CaptionHtml="Początek" EditValue="{DataOd}" />
<Field CaptionHtml="Koniec" EditValue="{DataDo}" />
</Scheduler>
```
### Gantt / GanttDiagram - Harmonogram
```xml
<Gantt EditValue="{Zadania}" ViewType="WeekDay">
<Field CaptionHtml="Zadanie" EditValue="{Nazwa}" />
<Field CaptionHtml="Początek" EditValue="{Start}" />
<Field CaptionHtml="Koniec" EditValue="{Finish}" />
</Gantt>
```
### Html / Markdown - Treść formatowana
```xml
<Html EditValue="{TrescHtml}" Width="*" Height="200" />
<Markdown EditValue="{TrescMarkdown}" Width="*" />
```
### Indicator - Wskaźnik
```xml
<Indicator CaptionHtml="Sprzedaż"
EditValue="{WartoscSprzedazy}"
UnitSymbol="PLN" />
```
### Dashboard - Panel kafelkowy
```xml
<Dashboard>
<Group Class="DashboardItem" CaptionHtml="Sprzedaż">
<Indicator EditValue="{Sprzedaz}" />
</Group>
</Dashboard>
```
## Bindowanie danych ## Bindowanie danych
Każdy element form.xml znajduje się w odpowiednim kontekście powiązanego obiektu C#. Powiązany typ danych zależy od typu danych dla którego zdefiniowany jest pageform.xml.
### Powiązanie typu z formularzem ### Powiązanie typu z formularzem
Powiązanie z typem w elemencie root odbywa się przez: 1. **Przez nazwę pliku**`Towar.Ogolne.pageform.xml` → kontekst klasy `Towar`
2. **Przez atrybut DataType**`<DataForm DataType="Soneta.Handel.Towar,Soneta.Handel">`
1. **Przez nazwę pliku pageform.xml** - pierwszy człon nazwy pliku (DataType) określa typ obiektu. Np. dla pliku `Towar.Ogolne.pageform.xml` kontekstem jest klasa `Towar`. 3. **Przez rejestrację FolderViewAttribute** — dla viewform.xml
2. **Przez atrybut DataType w DataForm** - jawne określenie typu:
```xml
<DataForm DataType="Soneta.Handel.Towar,Soneta.Handel">
```
3. **Przez rejestrację FolderViewAttribute** - wiążącą folder programu z obiektem biznesowym i formularzem prezentującym ten folder.
### Zmiana kontekstu danych ### Zmiana kontekstu danych
- **DataContext** - zmienia kontekst **aktualnego elementu i wszystkich elementów podrzędnych**: - `DataContext="{Adres}"` zmienia kontekst **aktualnego elementu i podrzędnych**
```xml - `EditValue="{Pozycje}"` na Grid — zmienia kontekst **tylko podrzędnych** (pola wewnątrz Grida)
<Group DataContext="{Adres}">
<!-- wszystkie pola wewnątrz odwołują się do właściwości obiektu Adres -->
<Field CaptionHtml="Miasto" EditValue="{Miasto}" />
</Group>
```
- **EditValue** - zmienia kontekst **tylko elementów podrzędnych** (bez aktualnego kontenera): ### Składnia wyrażeń `{...}`
```xml
<Grid EditValue="{Pozycje}">
<!-- pola wewnątrz odwołują się do właściwości elementu kolekcji Pozycje -->
<Field CaptionHtml="Nazwa" EditValue="{Nazwa}" />
</Grid>
```
### Składnia wyrażeń w klamrach
W wyrażeniach `{...}` można odwoływać się do:
| Składnia | Opis | | Składnia | Opis |
|----------|------| |----------|------|
| `{Właściwość}` | Publiczna właściwość obiektu w kontekście | | `{Właściwość}` | Publiczna właściwość w kontekście |
| `{Metoda()}` | Wartość zwracana przez publiczną metodę. Parametry metody są uzupełniane automatycznie na podstawie aktualnego kontekstu UI (`Soneta.Business.Context`) |
| `{Obiekt.Właściwość}` | Właściwość zagnieżdżona | | `{Obiekt.Właściwość}` | Właściwość zagnieżdżona |
| `{Context.TypDanych.Pole}` | Wartość z aktualnego kontekstu UI (`Soneta.Business.Context`) | | `{Obiekt+SubObiekt.Właściwość}` | Operator `+` — nawigacja przez powiązany obiekt ViewInfo |
| `{Features.NazwaCechy}` | Cechy powiązane z obiektem biznesowym `Row` | | `{Workers.NazwaWorkera.Pole}` | Właściwość workera |
| `{Workers.NazwaWorkera.Pole}` | Właściwość workera powiązanego z obiektem (`WorkerAttribute`) | | `{new NazwaExtender.Pole}` | Właściwość extendera |
| `{new NazwaExtender.Pole}` | Właściwość extendera (worker niepowiązany z konkretnymi danymi) | | `{Features.NazwaCechy}` | Cechy powiązane z Row |
| `{Tablica[indeks]}` | Element tablicy pod wskazanym indeksem | | `{Context.TypDanych.Pole}` | Wartość z kontekstu UI (`Soneta.Business.Context`) |
| `{Licence.HAN}` | Warunek licencji (używany w `Renderable`) |
| `{.}` | Aktualna wartość w kontekście elementu | | `{.}` | Aktualna wartość w kontekście elementu |
### Wyrażenia porównań
| Składnia | Opis |
|----------|------|
| `{Pole=wartość}` | Porównanie równości |
| `{Pole!=wartość}` | Porównanie nierówności |
| `{!PoleLogiczne}` | Negacja wartości logicznej |
| `{?warunek}` | Warunek oparty o klasę `RowCondition` |
### Przykłady bindingów
```xml
<!-- Proste właściwości -->
<Field CaptionHtml="Kod" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa kontrahenta" EditValue="{Kontrahent.Nazwa}" />
<!-- Właściwości workerów -->
<Field CaptionHtml="Saldo" EditValue="{Workers.SaldoWorker.SaldoOgolem}" />
<!-- Extendery (obiekty tworzone dynamicznie) -->
<Field EditValue="{new MojExtender.Właściwość}" />
<Command MethodName="Wykonaj" DataContext="{new MojExtender}" />
<!-- Cechy -->
<Field CaptionHtml="Cecha" EditValue="{Features.MojaCecha}" />
<!-- Kontekst UI -->
<Field EditValue="{Context.Operator.Nazwa}" IsReadOnly="true" />
<!-- Aktualna wartość -->
<Field EditValue="{.}" />
```
### Wyrażenia warunkowe (RowCondition) ### Wyrażenia warunkowe (RowCondition)
```xml ```xml
Visibility="{?State=Added}" <!-- stan obiektu --> Visibility="{?State=Added}" <!-- równość -->
Visibility="{?!State=Added}" <!-- negacja --> Visibility="{?!State=Added}" <!-- negacja -->
Visibility="{?Typ=Towar or Typ=Usługa}" <!-- OR --> Visibility="{?Typ=Towar or Typ=Usługa}" <!-- OR -->
Visibility="{?Aktywny and Widoczny}" <!-- AND --> Visibility="{?Aktywny and Widoczny}" <!-- AND -->
``` ```
## Atrybut Class - Style i zachowania ## Atrybut Class — najważniejsze wartości
Atrybut `Class` może zawierać wiele wartości oddzielonych spacją: **Style etykiet:** `BoldLabel`, `CenterLabel`, `RightLabel`, `WarningLabel`, `InfoLabel`, `NoColonLabel`
```xml **Style czcionek:** `BoldFont`, `LargeFont`, `GreenFont`, `RedFont`
<Field Class="BoldLabel LeftAlign ImageEdit" ... />
```
### Style etykiet **Typy edytorów:** `PasswordEdit`, `RichEdit`, `ImageEdit`, `HyperlinkEdit`, `EmailEdit`, `PhoneEdit`, `ColorEdit`, `ProgressEdit`, `RatingEdit`, `FileEdit`
- `BoldLabel` - pogrubiona etykieta
- `CenterLabel` - wycentrowana
- `RightLabel` - wyrównana do prawej
- `MultilineLabel` - wieloliniowa
- `NoColonLabel` - bez dwukropka
- `WarningLabel` - ostrzeżenie
- `InfoLabel` - informacja
- `TipLabel` - podpowiedź
### Style czcionek **Zachowania kontenerów:** `Collapsable`, `Expandable`, `Expanded`, `Scrollable`, `FirstResponder`
- `LargeFont` - duża czcionka
- `BoldFont` - pogrubiona
- `GreenFont` - zielona
- `RedFont` - czerwona
- `WarningFont` - ostrzegawcza
- `FixedWidthFont` - stała szerokość
### Wyrównanie **Przyciski:** `MainCommand`, `SplitCommand`, `CommandNoText`, `CommandIcoText`
- `LeftAlign`, `RightAlign`, `TextRight`
### Typy edytorów **Wyrównanie:** `LeftAlign`, `RightAlign`, `TextRight`
- `PasswordEdit` - hasło
- `ColorEdit` - wybór koloru
- `RichEdit` - edytor HTML
- `ImageEdit` - obraz
- `FileEdit` - wybór pliku
- `FolderEdit` - wybór folderu
- `PathPropertyEdit` - ścieżka
- `HyperlinkEdit` - hiperłącze
- `EmailEdit` - email
- `PhoneEdit` - telefon
- `RatingEdit` - ocena gwiazdkowa
- `ProgressEdit` - pasek postępu
- `IconEdit` - ikona
- `CheckButtonEdit` - checkbox jako przycisk
- `XmlEdit` - edytor XML
- `DataTextEdit` - tekst danych
### Zachowania **Pozycjonowanie:** `GroupItem` — element na poziomie nagłówka Group (zwykle po prawej)
- `Collapsable` - zwijalna grupa
- `Expandable` - rozwijalna
- `Expanded` - domyślnie rozwinięta
- `Hidden` - ukryty
- `FirstResponder` - pole z fokusem zaraz po otwarciu formularza
- `Scrollable` - przewijalna
- `ImageCircle` - okrągły obraz
- `Tree` - drzewo
### Układy i pozycjonowanie > Pełna lista Class: [references/ELEMENTS.md](references/ELEMENTS.md)
- `GroupItem` - element umieszczony na wysokości nagłówka `<Group>` (zwykle po prawej stronie), służy do sterowania zawartością pozostałych elementów grupy
- `Reverse` - układa elementy w odwrotnej kolejności (od prawej do lewej lub od dołu do góry)
- `SmartOpen` - kolumna w `Grid` wyróżniona do szybkiego otwierania formularza (ze strzałką)
### Przyciski
- `MainCommand` - główny przycisk
- `SplitCommand` - przycisk z menu
- `CommandNoText` - tylko ikona
- `CommandIcoText` - ikona i tekst
- `WorkerCommand` - przycisk workera
- `WizardCommand` - przycisk kreatora
- `PrintButton` - przycisk drukowania
## Appearance - Warunkowe formatowanie ## Appearance - Warunkowe formatowanie
```xml ```xml
<Field CaptionHtml="Saldo" EditValue="{Saldo}"> <Field EditValue="{Saldo}">
<Appearance Condition="{?Saldo&lt;0}" ForeColor="Red" FontBold="true" /> <Appearance Condition="{?Saldo&lt;0}" ForeColor="Red" FontBold="true" />
<Appearance Condition="{?Saldo&gt;1000}" BackColor="LightGreen" /> <Appearance Condition="{?Saldo&gt;1000}" BackColor="LightGreen" />
</Field> </Field>
``` ```
## Przykłady Składnia `Condition` może używać nawiasów kwadratowych gdy nazwa pola zawiera spacje lub operator porównania wymaga jawnego typu:
```xml
<Appearance Condition="{?[Typ] = 'usługa'}" ForeColor="#800080" />
```
### Prosta zakładka (pageform.xml) ## Przykład: pageform.xml
Plik: `MojObiekt.Ogolne.pageform.xml` Plik: `MojObiekt.Ogolne.pageform.xml`
@@ -689,15 +311,10 @@ Plik: `MojObiekt.Ogolne.pageform.xml`
<Group CaptionHtml="Dane podstawowe"> <Group CaptionHtml="Dane podstawowe">
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" /> <Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" /> <Field CaptionHtml="Nazwa" Width="*" EditValue="{Nazwa}" />
<Row>
<Field CaptionHtml="Data" Width="15" EditValue="{Data}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
</Row>
</Group> </Group>
<Group CaptionHtml="Pozycje"> <Group CaptionHtml="Pozycje">
<Grid Width="*" Height="*" EditValue="{Pozycje}" IsToolbarVisible="true"> <Grid Width="*" Height="*" EditValue="{Pozycje}" IsToolbarVisible="true">
<Field CaptionHtml="Lp" Width="5" EditValue="{Lp}" /> <Field CaptionHtml="Lp" Width="5" EditValue="{Lp}" />
<Field CaptionHtml="Opis" Width="*" EditValue="{Opis}" />
<Field CaptionHtml="Wartość" Width="15" EditValue="{Wartosc}" Footer="Sum" /> <Field CaptionHtml="Wartość" Width="15" EditValue="{Wartosc}" Footer="Sum" />
</Grid> </Grid>
</Group> </Group>
@@ -705,9 +322,35 @@ Plik: `MojObiekt.Ogolne.pageform.xml`
</DataForm> </DataForm>
``` ```
### Współdzielony fragment (form.xml) ## Przykład: viewform.xml z FilterPanel
Plik: `Adres.form.xml` Widok listy z panelem filtrów powyżej grida. `<Flow>` jako `FilterPanel` to standardowy wzorzec.
```xml
<?xml version="1.0" encoding="utf-8"?>
<DataForm xmlns="http://www.enova.pl/schema/form.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd">
<Flow Name="FilterPanel">
<Field CaptionHtml="Status" Width="15" EditValue="{ViewInfo+Params.Status}" Important="true" />
<Field CaptionHtml="Typ" Width="12" EditValue="{ViewInfo+Params.Typ}" Important="true" />
<Field CaptionHtml="Data od" Width="14" EditValue="{ViewInfo+Params.DataOd}" />
</Flow>
<Grid Name="List" OrderBy="Nazwa" FilterPanelWidth="136"
IsToolbarVisible="true" IsFilterRowVisible="false">
<Appearance Condition="{?[Status] = 'nieaktywny'}" ForeColor="#808080" />
<Field CaptionHtml="Kod" Width="20" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="30" EditValue="{Nazwa}" />
<Field CaptionHtml="Status" Width="15" EditValue="{Status}" />
<UserFilter Value="Status='Aktywny'" />
</Grid>
</DataForm>
```
**Uwaga:** Pliki `viewform.xml` zawierają Grid bezpośrednio w `DataForm` (bez `Page`). Atrybuty `ViewType` i `Mode` na `DataForm` są opcjonalne — dodaj je tylko gdy rejestrujesz widok przez `FolderViewAttribute`.
## Współdzielony fragment (form.xml)
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
@@ -728,7 +371,12 @@ Plik: `Adres.form.xml`
</DataForm> </DataForm>
``` ```
Dołączanie: `<Include Source="Adres.form.xml" DataContext="{Adres}" />`
## Referencje ## Referencje
- Pełna specyfikacja elementów: [references/ELEMENTS.md](references/ELEMENTS.md) - Pełna specyfikacja elementów: [references/ELEMENTS.md](references/ELEMENTS.md)
- Schemat XSD: [references/Form.xsd](references/Form.xsd) - Schemat XSD: [references/Form.xsd](references/Form.xsd)
- Przykład pageform.xml: [assets/MojObiekt.Ogolne.pageform.xml](assets/MojObiekt.Ogolne.pageform.xml)
- Przykład pageform.xml (warunki handlowe): [assets/Kontrahent.WarunkiHandlowe.pageform.xml](assets/Kontrahent.WarunkiHandlowe.pageform.xml)
- Przykład form.xml (adres): [assets/Adres.form.xml](assets/Adres.form.xml)
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Szablon: Widok listy (viewform.xml)
Format nazwy pliku: {NazwaWidoku}.viewform.xml
Przykłady:
- Towary.viewform.xml
- Kontrahenci.viewform.xml
- DokumentyHandlowe.viewform.xml
Struktura:
- <Flow Name="FilterPanel"> — panel filtrów nad listą (opcjonalny)
- <Grid Name="List"> — główna lista
- Brak elementu <Page> — Grid jest bezpośrednio w DataForm
Uwaga: ViewType i Mode na DataForm są opcjonalne — dodawaj je tylko
gdy viewform jest rejestrowany przez FolderViewAttribute.
-->
<DataForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.enova.pl/schema/form.xsd"
xsi:schemaLocation="http://www.enova.pl/schema/ http://www.enova.pl/schema/form.xsd">
<!-- Panel filtrów - Flow z polami filtrującymi nad gridem -->
<!-- Important="true" oznacza pole jako główne kryterium filtrowania -->
<!-- EditValue używa operatora + do nawigacji przez obiekt ViewInfo+Params -->
<Flow Name="FilterPanel">
<Field CaptionHtml="Typ" Width="12"
EditValue="{TowaryViewInfo+TowaryParams.Typ}" Important="true" />
<Field CaptionHtml="Magazyn" Width="16"
EditValue="{TowaryViewInfo+TowaryParams.Magazyn}" Important="true" />
<Field CaptionHtml="Kategoria" Width="18"
EditValue="{TowaryViewInfo+TowaryParams.Kategoria}" />
</Flow>
<!-- Główna lista -->
<Grid Name="List"
OrderBy="Nazwa"
FilterPanelWidth="120"
IsToolbarVisible="true"
IsFilterRowVisible="false"
SumType="All"
IsSmartOpen="true"
VisibleFeatures="Asortyment,Producent">
<!-- Formatowanie warunkowe wierszy -->
<Appearance Condition="{?[Typ] = 'usługa'}" ForeColor="#800080" />
<Appearance Condition="{?[Typ] = 'produkt'}" ForeColor="#0000FF" />
<!-- Kolumny listy -->
<Field CaptionHtml="Kod" Width="22" EditValue="{Kod}" />
<Field CaptionHtml="Nazwa" Width="30" EditValue="{Nazwa}" />
<Field CaptionHtml="Typ" Width="12" EditValue="{Typ}" />
<Field CaptionHtml="Stan magazynu" Width="14"
EditValue="{Workers.StanMagazynu.StanRazem}" Footer="Sum" />
<Field CaptionHtml="Cena podstawowa" Width="15"
EditValue="{Workers.TowarCeny.Podstawowa.Netto}" Footer="Sum" />
<!-- Predefiniowany filtr użytkownika -->
<UserFilter Value="Aktywny='True'" />
</Grid>
</DataForm>
+49
View File
@@ -0,0 +1,49 @@
{
"skill_name": "soneta-form-xml",
"evals": [
{
"id": 1,
"prompt": "Utwórz plik Zamowienie.Szczegoly.pageform.xml dla platformy enova365. Zakładka powinna zawierać:\n- Grupę 'Dane podstawowe' z polami: Numer (szerokość 20), DataZlozenia (szerokość 15), Kontrahent (szerokość *), Status (szerokość 15)\n- Grupę 'Warunki' z układem dwukolumnowym (Row > Stack): lewa kolumna ma SposobDostawy (20) i TerminDostawy (15), prawa kolumna ma SposobZaplaty (20) i TerminZaplaty (15)\n- Grupę 'Pozycje' z Grid (IsToolbarVisible, EditInPlace, NewInPlace) i kolumnami: Lp (5), Towar (*), Ilosc (10) z Footer=Sum, CenaJednostkowa (18), Wartosc (15) z Footer=Sum\nPriority zakładki: 10.",
"expected_output": "Poprawny plik XML pageform.xml z deklaracją XML, elementem DataForm z atrybutami xmlns i Priority=10, elementem Page z DataContext={DataSource}, trzema grupami z odpowiednimi polami i gridem. Plik powinien być gotowy do użycia w projekcie enova365.",
"files": [],
"assertions": [
"Plik zaczyna się od <?xml version=\"1.0\" encoding=\"utf-8\"?>",
"Element DataForm ma atrybut Priority=\"10\"",
"Element Page ma atrybut DataContext=\"{DataSource}\"",
"Są trzy elementy Group: 'Dane podstawowe', 'Warunki', 'Pozycje'",
"Układ dwukolumnowy w grupie Warunki używa Row zawierającego Stack",
"Element Grid ma atrybuty IsToolbarVisible=\"true\", EditInPlace=\"true\", NewInPlace=\"true\"",
"Pola Ilosc i Wartosc w Grid mają atrybut Footer=\"Sum\"",
"Binding pól używa składni {NazwaPola} w cudzysłowie"
]
},
{
"id": 2,
"prompt": "Stwórz plik Pracownicy.viewform.xml dla widoku listy pracowników w enova365. Widok listy powinien zawierać kolumny: Kod (8), NazwiskoImie (30), NumerPracownika (20), Dzial (*), Stanowisko (20), DataZatrudnienia (15). Domyślne sortowanie po NazwiskoImie. Dodaj IsToolbarVisible i IsFilterRowVisible. Zachowaj właściwą strukturę pliku viewform.xml.",
"expected_output": "Poprawny plik viewform.xml z elementem DataForm (bez Page), elementem Grid z kolumnami i sortowaniem OrderBy=\"NazwiskoImie\". Plik zgodny ze standardem enova365.",
"files": [],
"assertions": [
"Plik ma poprawną deklarację XML",
"Element DataForm ma xmlns=\"http://www.enova.pl/schema/form.xsd\"",
"Jest element Grid z EditValue lub bez (dla widoku listy)",
"Grid ma atrybut OrderBy=\"NazwiskoImie\"",
"Grid ma IsToolbarVisible=\"true\" i IsFilterRowVisible=\"true\"",
"Są kolumny Field dla: Kod, NazwiskoImie, NumerPracownika, Dzial, Stanowisko, DataZatrudnienia",
"Pole Dzial ma Width=\"*\""
]
},
{
"id": 3,
"prompt": "Pokaż jak w pageform.xml enova365 zastosować warunkową widoczność pól używając wyrażeń RowCondition. Stwórz przykładowy plik Kontrahent.Kredyt.pageform.xml z następującymi wzorcami:\n1. Pole 'LimitKredytu' widoczne tylko gdy TypKlienta='Korporacyjny'\n2. Pole 'WarunkiSpecjalne' widoczne gdy Status='Premium' LUB Status='VIP'\n3. Pole 'OstrzezenieBranze' widoczne gdy NIE Status='Aktywny'\n4. Przycisk Command widoczny gdy ObrotyRoczne > 0 (użyj WorkCondition lub własność bool)\n5. Cała Grupa 'Dane zaawansowane' zwijalna (Collapsable) z Renderable uzależnionym od licencji",
"expected_output": "Plik pageform.xml demonstrujący różne wzorce warunkowej widoczności: Visibility=\"{?TypKlienta=Korporacyjny}\", Visibility=\"{?Status=Premium or Status=VIP}\", Visibility=\"{?!Status=Aktywny}\", użycie klasy Collapsable dla grupy.",
"files": [],
"assertions": [
"Użyto składni Visibility=\"{?Pole=Wartość}\" dla warunku równości",
"Użyto składni OR dla wielu wartości: {?Status=Premium or Status=VIP}",
"Użyto negacji: {?!Status=Aktywny}",
"Klasa Collapsable jest zastosowana do grupy",
"Atrybut Renderable jest użyty dla warunku licencji"
]
}
]
}
+25
View File
@@ -771,6 +771,31 @@ Wszystkie elementy UI dziedziczą następujące atrybuty z `uiElement`:
| `FontBold` | boolean | Pogrubienie | | `FontBold` | boolean | Pogrubienie |
| `FontItalic` | boolean | Kursywa | | `FontItalic` | boolean | Kursywa |
**Składnia warunku Appearance** — dwie formy:
```xml
<!-- Forma 1: krótka, bez spacji (dla enumów i wartości bez spacji) -->
<Appearance Condition="{?Typ=usługa}" ForeColor="#800080" />
<!-- Forma 2: z nawiasami kwadratowymi i cudzysłowami (dla stringów, gdy pole ma spacje) -->
<Appearance Condition="{?[Typ] = 'usługa'}" ForeColor="#800080" />
```
---
## Składnia wyrażeń bindowania
### Operator `+` — nawigacja przez powiązane obiekty
Stosowany gdy widok listy (`viewform.xml`) korzysta z obiektu ViewInfo który agreguje parametry:
```xml
<!-- ViewInfo+Params.Właściwość — dostęp do parametrów widoku -->
<Field EditValue="{CennikViewInfo+CennikParams.Magazyn}" />
<Field EditValue="{ZamowieniaViewInfo+ZamowieniaParams.Status}" />
```
Wzorzec `{ObiektViewInfo+TypParams.Właściwość}` jest typowy dla paneli filtrów w viewform.xml — gdzie `+` łączy obiekt ViewInfo z typem jego pola będącego obiektem parametrów.
--- ---
## Wartości Class (enumSingleClass) ## Wartości Class (enumSingleClass)