EdeeShop · Implementace

Projektové úpravy administračního GUI

Upraveno

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:

kód
config/module-edeeshop/gui-admin/{entita}Admin.xml

Adresář je zaregistrovaný v config/module-edeeshop/module-edeeshop.xml:

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 v module-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
<?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

  1. Stránka — najděte definici v knihovně, např. categoryAdmin.xml. Absolutní cestu lze ověřit i v odkazech administračního menu (mainLayoutAdmin.xml, atributy urlToIdentify).
  2. Widget — modifikace cílí na runtime ID widgetu, ne na název elementu ve slovníku. Element <nameInput> má ve slovníku gui-edeeui-dictionary.xml definici <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žadavekOperace
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
<?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 replaceWith se zapisuje uvnitř <location widget="…"> — location zaměří widget na stránce a teprve v jeho kontextu se operace provede.
  • Náhradní <formDisplay> se píše bez id — 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.
  • formDisplay hodnotu 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