Projektové úpravy administračního GUI

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.

Zkopírovat odkaz na sekciKam soubor patří

Do adresáře, který je v konfiguraci modulu uvedený jako liveConfigStorage:

1 config/module-edeeshop/gui-admin/{entita}Admin.xml

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

xml
1 <gui ramJetModuleName="edeeui" admin="true"2     parentSection="edee"3     baseStorage="storage:f.cfg:/module-edeeshop/template-admin"4     liveConfigStorage="storage:f.cfg:/module-edeeshop/gui-admin"5     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.

Zkopírovat odkaz na sekciTvar souboru

xml
1 <?xml version="1.0" encoding="utf-8"?>2<gui>3    <modifications>4        <modify target="/edee/edeeShop/categoryFeature/categoryEditPage">5            <!-- operace -->6        </modify>7    </modifications>8</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>.

Zkopírovat odkaz na sekciJak 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.

Zkopírovat odkaz na sekciPř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.

Zkopírovat odkaz na sekciČ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é.

Zkopírovat odkaz na sekciRecept: 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
1 <?xml version="1.0" encoding="utf-8"?>2<gui>3    <modifications>4        <modify target="/edee/edeeShop/categoryFeature/categoryEditPage">5            <location widget="name">6                <replaceWith>7                    <formDisplay>8                        <metadata>9                            <localizable/>10                        </metadata>11                    </formDisplay>12                </replaceWith>13            </location>14        </modify>15    </modifications>16</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.

Zkopírovat odkaz na sekciOdkazy