Własne moduły
System Ready_™ umożliwia tworzenie własnych modułów, które są oparte na definicji XML, widoku (raport) oraz przyciskach akcji (toolbar).
Aby moduł był poprawny, musi zawierać przynajmniej jedną zakładkę.
W niniejszej dokumentacji wykorzystany zostanie przykład plik o nazwie EmployeeBriefcase.xml
w folderze edokumenty/var/cfg/CustomModules/
, gdzie nazwa pliku (EmployeeBriefcase
) to identyfikator modułu.
Następnie do pliku wklejamy poniższy kod.
<?xml version="1.0" encoding="UTF-8"?>
<modules>
<module id="EmployeeBriefcase"
name="Teczka pracownika"
label="Teczka pracownika"
icon="briefcase-with-eye.svg"
color="#e67e22"
right="bswfms.custom_modules.employee_briefcase">
<tabs>
<tab>
<tabs>
<tab label="Lista pracowników" rep_id="2163" >
<buttons>
<button>
<id>refresh</id>
<label>Odśwież</label>
<dscrpt>Odśwież</dscrpt>
<onclick>{AFTER_SUBMIT}</onclick>
<icon>sync-24.png</icon>
</button>
</buttons>
</tab>
</tabs>
</tab>
</tabs>
</module>
</modules>
SELECT usr_id,
lasnam,
firnam,
'<img src="var/img/Employees/.thumb/' || foto__ || '" style="width: 50px;">' AS foto__
FROM users
WHERE NOT is_del
Wskazówka
Pierwszy poziom zakładek (jeżeli jest ich więcej niż jedna) /modules/module/tabs/tab/tabs/tab
zostaną wyświetlane w pionie.
Jest to zalecany przez guideline sposób prezentacji zakładek dla aplikacji i custom modułów.
Parametry definicji modułu
label - tytuł zakładki. Sugeruje się ograniczenie do 1 słowa.
rep_id - (zastępowane przez phpRender) id raportu, który ma się wyświetlić. Więcej informacji w raportach.
phpRender - (zastępowane przez rep_id) przyjmuje nazwę klasy z widokiem. Informacje o phpRender.
grp_id - identyfikatory grup użytkowników, dla których zakładka będzie widoczna, np.
grp_id="2,5,10"
.def_tab - znacznik wskazujący, czy zakładka domyślnie ma się pokazywać na pasku zakładek, czy też ma być widoczna dopiero po kliknięciu linku
więcej
.Uwaga!
Atrybut def_tab dla zakładki działa wyłącznie dla własnych modułów. Nie działa on dla dodatkowych zakładek na kartotekach.
forceOpen - wymusza otwarcie zakładki jako pierwszej. Przyjmuje wartość 0 lub 1. Atrybut ten można ustawić tylko dla 1 zakładki.
prior - ustawienie na odpowiedniej kolejności zakładek. Parametr przyjmuje wartość od 0 do n gdzie n <= liczbie zakładek. Atrybut ten w połączeniu z forceOpen umożliwia nam dodanie nowej domyślnie otwartej zakładki na pierwszej pozycji w kartotece.
showFilters - zwijanie panelu z filtrami, domyślnie panel jest zwinięty.
Przyjmuje wartość 0 lub 1.iframe - url do strony poza systemem, którą chcemy wyświetlić w zakładce. alwaysVisible - czy zakładka ma być zawsze widoczna. Przyjmuje wartość 0 lub 1.
right - prawa systemowe do wyświetlenia zakładki. Informacje jak dodać swoje prawa znajdziesz tutaj
filtersMode - za pomocą tego atrybutu można zmieniać położenie panela filtrów. Standardowo panel filtrów widoczny jest po lewej stronie (wartość atrybutu filtersMode = "left"). Dla wartości "right_abs" panel filtrów pojawi się z prawej strony i będzie on nachodził na listę umieszczoną w module.
visible - wskazuje, czy dany moduł ma być widoczny. Nie w każdym przypadku moduł powinien być widoczny. Czasami celem istnienia modułu jest bycie uruchomionym poprzez kliknięcie z innego miejsca w aplikacji, np. z Ustawień Aplikacji.
Uwaga!
Atrybut visible dla zakładki działa wyłącznie dla własnych modułów. Nie działa on dla dodatkowych zakładek na kartotekach.
Przykład ukrytego modułu:
<module id="ERPExchangeConfigurationTokens" name="Tokeny definicji" label="Tokeny definicji" icon="service.svg" color="#327DE6" visible="false" right="">...</module>
lub inaczej:
<module id="ERPExchangeConfigurationTokens" name="Tokeny definicji" label="Tokeny definicji" icon="service.svg" color="#327DE6" visible="0" right="">...</module>
Obie postaci są prawidłowe.
W przypadku, gdy widoczność zakładki modułu ma być uzależniona od ustawienia globalnego (w tabeli
global_sys_conf
), można wykorzystać funkcjęgetGlobalSystemConfig
, która pobierze wartość logiczną (0,1). Zmienna wykorzystywana w tej funkcji musi mieć wartości 0 (FAŁSZ) lub 1 (PRAWDA) Parametrami tej funkcji są pola z ww. tabeli:- objnam - symbol aplikacji w
global_sys_conf
, np#FK#
- varnam - nazwa zmiennej
global_sys_conf
, np#SHOW.OLD.COST.ANALYSIS.TAB#
- objnam - symbol aplikacji w
<tab id="cost_analysis" visible="{getGlobalSystemConfig(#FK#,#SHOW.OLD.COST.ANALYSIS.TAB#)}" label="{translate(#ANALIZA KOSZTÓW#)}" licenceTypeAccessRule="Allow:REGULAR" rep_id="1802" groupName="{translate(#ANALIZY#)}" showFilters="0">
- groupName - pozwala na grupowanie zakładek. Przykładowy kod takiego atrybutu (z funkcją tłumaczenia):
<tab label="{translate(#Szyna#)} Azure" showFilters="0" groupName="{translate(#ADMINISTRACJA#)}"
phpRender="ReadyApp\KSEF\View\Module\EventLog" right="bswfms.settings.level2">...</tab>
licenceTypeAccessRule - wskazuje, jakiego rodzaju użytkownicy mają możliwość zobaczenia zakładki modułu. Wyróżnia się następujące rodzaje:
- REGULAR - Użytkownicy standardowi systemu,
- PORTAL - Użytkownicy portalu
Przykład definicji typu licencji:
<tab label="{translate(#Moje#)}" rep_id="2042" licenceTypeAccessRule="Allow:REGULAR,PORTAL">...</tab>
Dodanie prawa systemowego dostępu do modułu
Kolejnym etapem jest dodanie prawa systemowego.
Prawa systemowe
Dostęp do pewnej części aplikacji lub wykonanie jakieś akcji możemy ograniczyć użytkownikowi, za pomocą prawa systemowego.
Przykład tworzenia prawa dla własnego modułu
Aby utworzyć nowe prawo:
- Wchodzimy w
Panel Sterowania
>Definicje uprawnień
.
- Zaznaczamy element drzewa
CustomModules
i klikamy przyciskNowe
.
- Wypełniamy formatkę. Należy zwrócić uwagę na pole
identyfikator
, które powinno być zapisane jednym ciągiem bez białych znaków.
Po kliknięciu przycisku zapisz mamy do dyspozycji nowe prawo bswfms.custom_modules.employee_briefcase
, które następnie wpisujemy jako wartość atrybutu right
w tagu module
naszego pliku konfiguracyjnego customowego modułu.
...
<module ... right="bswfms.custom_modules.employee_briefcase">
...
Bez ustawionego prawa moduł nie będzie widoczny w systemie. Nowo utworzone prawo należy wprowadzić jako wartość atrybutu right
tagu module
, np. right="bswfms.custom_modules.employee_briefcase"
Generowanie widoku modułu.
W celu wygenerowania widoku modułu istnieją dwie możliwości:
- podpięcie raportu,
- użycie phpRender-a do generowania treści.
Poniżej opisano każdą z tych opcji:
Użycie raportu jako treści zakładki modułu
Następnie należy wprowadzić klucz raportu. Jeżeli nie jest znany identyfikator raportu, który odpowiada za listę na poniższym przykładzie, należy przejść do definicji raportu.
Natomiast jeżeli już znany jest identyfikator raportu id
, to należy wpisać go jako wartość atrybutu rep_id
w tagu tab
.
Filtrowanie danych w zakłądce modułu
W przypadku wykorzystania raportu do generowania treści można wykorzystać ten sam raport jako źródło dla więcej niż jednej zakładki modułu. Aby każda z zakładek nie pokazywała tych samych danych, należy dodać filtrowanie. Filtrowanie można dodać w definicji XML zakładki modułu np. (definicje z aplikacji Wnioski zakupowe):
<modules><module id="Request" name="{translate(#Wnioski zakupowe#)}" label="{translate(#Wnioski zakupowe#)}" icon="Shopping_Cart.svg" color="#e67e22" licenceTypeAccessRule="Allow:REGULAR,PORTAL" right="bswfms.apps.request">
<tabs>
<tab label="Wnioski">
<tabs compactView="1">
<tab label="{translate(#Moje#)}" rep_id="2042" licenceTypeAccessRule="Allow:REGULAR,PORTAL">
<filters>
<filter name="FiltrZakładki" type="StaticFilter" token="{FILTER_TAB}" >
(d.adduid = {LOGGED_USR_ID}
OR
{LOGGED_USR_ID} IN (SELECT DISTINCT (o3.usr_id)
FROM stages s
INNER JOIN procedures pr2 USING (procid)
LEFT JOIN orgtree_view o3 ON o3.orunid = ANY (s.orgarr)
WHERE (QQ
(s.is_act AND NOT s.is_fix)
OR
(s.ptsttp = 'END' AND s.is_fix IS TRUE)
) AND (s.ptsttp != 'SUBPROCESS') AND (pr2.rootpr = d.procid))
)
</filter>
</filters>
<buttons>
<button>
<custom_widget>1243</custom_widget>
</button>
<button>
<id>xls</id>
<label/>
<dscrpt>XLS</dscrpt>
<onclick>{EXPORT_TO_XLS}</onclick>
<icon>xls.png</icon>
</button>
<button>
<id>refresh1</id>
<label>{translate(#Odśwież#)}</label>
<dscrpt>{translate(#Odśwież#)}</dscrpt>
<onclick>
{AFTER_SUBMIT}
</onclick>
<icon>refresh.png</icon>
</button>
</buttons>
</tab>
<tab label="{translate(#Zakończone#)}" rep_id="2042" licenceTypeAccessRule="Allow:REGULAR,PORTAL">
<filters>
<filter name="FiltrZakładki" type="StaticFilter" token="{FILTER_TAB}">
((etap IS NULL ) AND state_ > 6 )
</filter>
</filters>
<buttons>
<button>
<id>xls</id>
<label/>
<dscrpt>XLS</dscrpt>
<onclick>{EXPORT_TO_XLS}</onclick>
<icon>xls.png</icon>
</button>
<button>
<id>refresh2</id>
<label>{translate(#Odśwież#)}</label>
<dscrpt>{translate(#Odśwież#)}</dscrpt>
<onclick>
{AFTER_SUBMIT}
</onclick>
<icon>refresh.png</icon>
</button>
</buttons>
</tab>
<tab label="{translate(#Wszystkie#)}" rep_id="2042" licenceTypeAccessRule="Allow:REGULAR,PORTAL">
<filters>
<filter name="FiltrZakładki" type="StaticFilter" token="{FILTER_TAB}">
true
</filter>
</filters>
<buttons>
<button>
<id>xls</id>
<label/>
<dscrpt>XLS</dscrpt>
<onclick>{EXPORT_TO_XLS}</onclick>
<icon>xls.png</icon>
</button>
<button>
<id>refresh3</id>
<label>{translate(#Odśwież#)}</label>
<dscrpt>{translate(#Odśwież#)}</dscrpt>
<onclick>
{AFTER_SUBMIT}
</onclick>
<icon>refresh.png</icon>
</button>
</buttons>
</tab>
</tabs>
</tab>
</tabs>
</module></modules>
W powyższym przykładzie pierwsza zakładka opisuje "Moje wnioski", następna "Zakończone", a ostatnia wszystkie. Istotą tego filtrowania jest to, że zawartość taga <filter>
musi być prawidłowym warunkiem WHERE głównej kwerendy raportu. W kwerendzie zaś musi być użyty tag {FILTER_STRING}
Wykorzystanie phpRender-a do generowania treści modułu
PhpRender
PhpRender jest używany w definicji zakładek, w systemowych plikach xml-owych, custom modules.
Implementuje ICustomView gdzie musimy utworzyć metode toHtml, w której utworzymy Panel z listą.
class ExampleView implements ICustomView {
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $refreshToken = 'return false;';
public function __construct(string $name, ?Panel $parent = NULL) {
$this->name = $name;
$this->refreshToken = 'App.'.$this->name.'asyncRefresh();';
}
public function toHtml(): string {
$html = '<div class="custom-projects gbs sbg b-s-b" style="overflow-y: scroll; height: 100%">
<div class="ready-bootstrap">
<div class="row" style="margin-left: 5px; margin-right: 0;">
<button class="rbos-btn rbos-btn-secondary no-print" title="'.Translator::translate('Odśwież').'"
onclick="'.$this->refreshToken.' return false;">
<i style="vertical-align: middle; font-size: 14px; line-height: 30px; margin-right: 3px;"
class="eic eic-refresh"></i>'.Translator::translate('Odśwież').'
</button>
</div>
</div>
</div>';
return $html;
}
public function setParams(array $params): void {
}
}
Przykład implementacji
W przykładzie prezentowany jest widok z przyciskiem, który potrafi odświeżyć sam siebie poprzez wywołanie funkcji asynchronicznej z atrybutu onClick przycisku "odśwież"
Analogicznie została dodana obsługa na zakładkach spraw poprzez dodanie atrybutu phpRender="{klasa widoku z namespace}"
do elementu tab.
Przykład definiowania zakładki
<tab label="Przykład widoku ICustomView" phpRender="ReadyApp\ExampleApp\View\ExampleView"></tab>
Uwagi końcowe.
Aby zobaczyć nowo utworzony moduł, należy wylogować się z systemu, a następnie zalogować się. Moduł powinien być widoczny w menu aplikacji.