Projektové úpravy administračního GUI
Administrační editory EdeeShopu jsou definované v knihovních modulech (především
lib_eshop_edee). Na projektu se do nich nezasahuje přímo — místo toho se přidá
XML soubor s modifikacemi, který cílovou stránku upraví za běhu.
Tento dokument popisuje, kam soubor patří, jaké operace jsou k dispozici a jaké jsou ověřené postupy pro typické požadavky. Doplňujte sem další recepty, jak budou vznikat.
Kam soubor patří
Do adresáře, který je v konfiguraci modulu uvedený jako liveConfigStorage:
config/module-edeeshop/gui-admin/{entita}Admin.xmlAdresář je zaregistrovaný v config/module-edeeshop/module-edeeshop.xml:
<gui ramJetModuleName="edeeui" admin="true" parentSection="edee" baseStorage="storage:f.cfg:/module-edeeshop/template-admin" liveConfigStorage="storage:f.cfg:/module-edeeshop/gui-admin" liveConfigParentNode="edee/edeeShop">Celý obsah adresáře se načte automaticky jako plnohodnotná GUI konfigurace
(RamJetModule#loadGuiConfig) — nový soubor se nikam neregistruje, stačí ho tam
položit. Vedle XML v témže adresáři bydlí i .properties s lokalizací popisků.
Pokud blok <gui admin="true"> v konfiguraci projektu chybí, je potřeba ho nejdřív
doplnit — bez něj se modifikace nenačtou.
Pozor na
module-edeeui/gui-admin/. Ten adresář máliveConfigParentNode="edee"a patří do něj modifikace stránek EdeeCMS, ne EdeeShopu. Modifikace administrace e-shopu držte vmodule-edeeshop, kde je zaručeno, že cílové stránky už existují.
Monitoring změn je zapnutý (setMonitorForChanges(true)), takže úprava souboru se
projeví bez restartu aplikace.
Pojmenování souboru se řídí konvencí {nazevArtiklu}Admin.xml — viz
Jmenné konvence.
Tvar souboru
<?xml version="1.0" encoding="utf-8"?><gui> <modifications> <modify target="/edee/edeeShop/categoryFeature/categoryEditPage"> <!-- operace --> </modify> </modifications></gui>Cesta targetu odpovídá struktuře uzlů popsané v Definici GUI pro feature:
/edee/edeeShop/{featureId}/{entita}{TypEditoru}Page, kde featureId je název třídy
feature s malým počátečním písmenem a typ editoru je Listing / Create / Edit.
Atribut target přijímá i více cílů oddělených čárkou.
Jeden soubor může obsahovat libovolný počet elementů <modify>.
Jak najít target a ID widgetu
- Stránka — najděte definici v knihovně, např.
categoryAdmin.xml. Absolutní cestu lze ověřit i v odkazech administračního menu (mainLayoutAdmin.xml, atributyurlToIdentify). - Widget — modifikace cílí na runtime ID widgetu, ne na název elementu ve
slovníku. Element
<nameInput>má ve slovníkugui-edeeui-dictionary.xmldefinici<nameInput extends="textInput" id="name">, takže se na něj cílíwidget="name". Ustálená ID widgetů shrnují Konvence editorů Edee UI.
Pokud si nejste jistí, že widget na stránce existuje (např. ho přidává feature, která
nemusí být zapnutá), přidejte na operaci optional="true" — jinak se konfigurace
při startu neúspěšně načte.
Přehled operací
| Požadavek | Operace |
|---|---|
| Odebrat pole | <removeWidget widget="x" optional="true"/> |
| Nahradit pole needitovatelným výpisem | <location widget="x"><replaceWith><formDisplay/></replaceWith></location> |
| Přidat pole za existující | <insertAfterWidget widget="x"> … </insertAfterWidget> |
| Přidat pole na konec sekce | <appendWidget widget="mainContentFS"> … </appendWidget> |
| Změnit metadata widgetu | <location widget="x"><setMetadata> … </setMetadata></location> |
| Změnit properties widgetu (filtr, řazení) | <location widget="x"><setProperties> … </setProperties></location> |
| Odebrat validátor | <location widget="x"><removeValidator selector="eq(shortName,required)"/></location> |
| Zobrazit pole jen za podmínky | <location widget="x"><setMetadata><enableOn>…</enableOn></setMetadata></location> |
setMetadata jednotlivé položky slučuje, nepřepisuje celý kontejner — ostatní
metadata widgetu (<localizable/>, priority…) zůstávají zachovaná.
Kompletní referenci operací (včetně move*, wrap*, práce s interceptory, commandy,
data providery a modificationRules) najdete v dokumentaci Ramjetu — viz
Odkazy na konci.
Časté omyly
<disableOn> / <enableOn> widget nezobrazí vůbec. Nejde o „zašednutí" pole:
neaktivní widget se přeskočí při renderu (WidgetRender.java, větev
widgetState.isActive()). Pro needitovatelné, ale viditelné pole použijte
formDisplay.
<displayAsLabel/> na inputu nedělá nic. Toto metadatum čtou jen šablony
display widgetů a sloupců listingu (display.ftl, columnDisplay.ftl). Na
textInput je bez efektu — pole zůstane editovatelné a uživatel dostane falešný
dojem, že se změna uložila.
<disabled> uvnitř <dataset> je něco jiného. Je to volba JS komponenty
(dekorátoru) u widgetů typu tagsSelect, ne stav widgetu na serveru.
pojo.readOnly nechrání lokalizované hodnoty. Metadatum pojo.readOnly
zabrání zápisu do entity (AbstractExtractDataWidgetVisitor extrakci přeskočí),
ale lokalizované texty ukládá samostatná větev — StoreEntityLocalizationCommand
přes ExtractLocalizationWidgetVisitor, který jede podle metadata <localizable/>
a o pojo lokátorech nic neví. Pole s <localizable/> je tedy po přepnutí na cizí
jazyk pořád uložitelné.
Recept: zákaz editace názvu kategorie
Požadavek: název kategorie má být v administraci vidět, ale nesmí jít změnit — ani ve výchozím jazyce, ani v lokalizaci.
config/module-edeeshop/gui-admin/categoryAdmin.xml:
<?xml version="1.0" encoding="utf-8"?><gui> <modifications> <modify target="/edee/edeeShop/categoryFeature/categoryEditPage"> <location widget="name"> <replaceWith> <formDisplay> <metadata> <localizable/> </metadata> </formDisplay> </replaceWith> </location> </modify> </modifications></gui>Proč to drží:
- Operace
replaceWithse zapisuje uvnitř<location widget="…">—locationzaměří widget na stránce a teprve v jeho kontextu se operace provede. - Náhradní
<formDisplay>se píše bezid— přebírá ID nahrazovaného widgetu (name) a s ním i vazbu na hodnotu. Stejný vzor už na téže stránce používá<formDisplay id="code"/>pro kód kategorie. formDisplayhodnotu jen vykreslí, žádný input se neodesílá — a s původním widgetem zmizel i zděděný validátor<required/>, takže uložení projde.<localizable/>v metadatech ponechte u polí, která lokalizovaná jsou: zajistí, že se vypíše hodnota v právě zvoleném jazyce. U nelokalizovaných polí stačí prázdné<formDisplay/>.
Modifikace míří jen na categoryEditPage. Zakládací stránka categoryCreatePage
zůstává nedotčená, název tedy jde zadat při vzniku kategorie — což je obvykle
žádoucí. Zakázat ho i tam nestačí stejnou operací: name tam má podmíněný
<required/> a u typu SHORTCUT se plní interceptorem podle vybrané cílové
kategorie.
Ověření v administraci: v detailu kategorie je název jen text bez inputu, uložení projde bez validační chyby a hodnota se nezmění; totéž po přepnutí na cizí jazyk.
Odkazy
- Definice GUI pro feature — pořadí zpracování slovníků a setup-GUI, struktura uzlů, dev režim
- Editory Edee UI — konvence a řazení komponent — ustálená ID widgetů, priority, řazení sekcí
- Editor produktu — příklad editoru postaveného vzorem „dictionary + modifications"
- Kompletní reference XML modifikací — všechny operace, selektory,
modificationRules - Dědičnost stránek (
extends) - Modifikace v dokumentaci Ramjet inspektoru
