Słów kilka na temat przypuszczalnej śmierci zasobów sieciowych w aplikacjach Power Apps sterowanych modelem

Cześć. W dzisiejszym artykule zajmę się tematem tworzenia niestandardowego interfejsu użytkownika w aplikacjach sterowanych modelem i działających na platformie Power Apps. Jak zwykle, dla uproszczenia będę je określał po prostu jako: „aplikacje Power Apps”. W związku z powyższym osoby poszukujące informacji na temat aplikacji Canvas nie znajdą w tym miejscu zapewne wielu przydatnych dla siebie informacji.

Do czego zazwyczaj potrzebny jest nam niestandardowy UI w aplikacjach Power Apps? Już ich pełna nazwa („aplikacje sterowane modelem”) wskazuje, że nowoczesny, ujednolicony interfejs użytkownika jest mocno powiązany z zaimplementowanym modelem danych. Przykładowo, jeżeli wspomniany model opisujący proces biznesowy oparty jest na kilkunastu encjach – wielce prawdopodobne jest to, że wprowadzenie danych wymaganych do jego obsługi – wymagało będzie w systemie przeklikania się przez taką samą liczbę ekranów aplikacji. Oczywiście, użytkownicy biznesowi tego nie lubią, ponieważ jest to proces skomplikowany, błędogenny i na ogół mało intuicyjny. O wiele lepszą metodą jest stworzenie takiego widoku na dane, który prezentowałyby większość niezbędnych informacji oraz dawał możliwość ich wprowadzenia bądź uzupełnienia z poziomu pojedynczej formatki. Standardowym przykładem tego typu aplikacji są wszelakie kalkulatory ofertowe zagnieżdżone lub zintegrowane ze standardowym obiektem oferty będącym częścią aplikacji Dynamics 365 Sales. Niestandardowy interfejs przydaje się więc wszędzie tam, gdzie standardowy UI „wymięka” i nie jest w stanie zapewnić użytkownikowi odpowiedniej ergonomii w pracy z danymi.  

Na początku przyjrzyjmy się poszczególnym możliwościom, które daje nam platforma Microsoftu w omawianym temacie.

Zasoby sieciowe

Jest to najstarszy sposób tworzenia niestandardowego interfejsu użytkownika dostępny w systemie od prawie 10 lat (a konkretnie – od wersji Dynamics CRM 2011). Oparty jest on o niestandardowe pliki HTML oraz JavaScript. W przeszłości dostępne były również zasoby sieciowe w formie aplikacji Silverlight, ale… wszyscy wiemy, jako skończyła ta technologia. Zasoby sieciowe są świadome kontekstu uruchomieniowego aplikacji, pozwalają również na odwoływanie się oraz interakcję z formatką „rodzica”, na której są zagnieżdżone. Dzięki możliwości korzystania z dedykowanego API oraz usług sieciowych mają one praktycznie nieograniczone możliwości interakcji z danymi i funkcjami systemu. Ważną kwestią jest to, że nie muszą być one powiązane w żaden sposób z danymi na formatce, w której zostały osadzone. Ich jedyną wadą, która przychodzi mi do głowy, jest natomiast to, że do ich stworzenia wymagana jest umiejętność programowania oraz przynajmniej podstawowa znajomość technologii HTML i CSS. Z drugiej strony zapewnia to praktycznie nieograniczone możliwości, jeżeli chodzi o możliwą do zaimplementowania funkcjonalność.

Komponenty Power Apps

PowerApp Component Framework jest dość nową technologią pozwalającą na tworzenie kontrolek do wizualizacji danych w aplikacjach Canvas oraz tych sterowanych modelem. Podobnie jak poprzednik oparty jest on o technologię sieciowe takie jak HTML oraz JavaScript, tym razem jednak w nieco bardziej nowoczesnym wydaniu. W przypadku zasobów sieciowych – pracę nad interfejsem rozpoczynamy zazwyczaj z przysłowiową „białą kartką”. Tymczasem PCF od samego początku wymusza stosowanie narzędzi takich jak NPM, MSBuild, język TypeScript, czy framework ReactJS, co z kolei nie każdemu może przypaść do gustu. Budowa kontrolek bardziej przypomina w tym przypadku tworzenie nowoczesnych aplikacji SPA wykorzystujących serwer Node niż klasycznych aplikacji HTML5. Ważną kwestią w przypadku omawianej technologii jest fakt, że zostały one stworzone do wizualnej reprezentacji danych osadzonych na formatce. Przykładowo, jeżeli na ekranie systemu występuje pole zawierające liczbę, PCF daje nam możliwość zastąpienia go dedykowaną, bajerancką kontrolką. Niestety w momencie pisania artykułu nie wszystkie typy danych były obsługiwane przez framework. Za pomocą kontrolek PCF możemy również zastępować widoki zagnieżdżone na formatkach.

Podobnie jak w przypadku zasobów sieciowych – tworzenie kontrolek Power Apps wymaga znajomości programowania. Warto również wspomnieć, że framework PCF był wykorzystywany przez programistów Microsoft do budowy komponentów wchodzących w skład najnowszych wersji aplikacji Dynamics 365 wykorzystujących ujednolicony interfejs użytkownika. 

Zagnieżdżone aplikacje Canvas

Ostatnia możliwość warta wymienienia w tym miejscu polega na zastąpieniu pola lub widoku na formatce ekranem aplikacji Canvas. W przypadku tego typu rozszerzeń jakakolwiek wiedza na temat programowania jest nam zbędna. Cały proces polega w tym przypadku na wyborze pola lub tabeli, które chcemy zastąpić i przystąpieniu do projektowania nowego interfejsu w wizualnym kreatorze (WYSWYG) aplikacji Canvas.

Spośród wymienionych powyżej technologii tylko zasoby sieciowe pamiętają czasy przed ujednoliconym interfejsem użytkownika, systemem dostępnym w modelu SaaS (Software as a Service) oraz szeroko pojętą współczesnością*. W rozmowach z wieloma programistami oraz konsultantami pracującymi z platformą Power Apps lub aplikacjami Dynamics 365 często spotykałem się z opiniami, że prawdopodobnie w najbliższych latach wspomniane zasoby sieciowe odejdą do lamusa i zostaną usunięte z systemu przez Microsoft. Otóż moi drodzy – tak się nie stanie. Przynajmniej nie w najbliższych kilku latach. Ani framework PCF, ani zagnieżdżone aplikacje Canvas nie dają bowiem specjalistom tych samych możliwości, co „klasyczne” zasoby sieciowe. Wynika to z prostego faktu, że przeznaczone są one po prostu do nieco innych zastosowań. Do jakich – o tym napiszę w dalszej części artykułu.

Na potrzeby testów ww. technologii wymyśliłem sobie następujące ćwiczenie. Na formatce encji CDS w aplikacji Power App postanowiłem umieścić tabelę z danymi. Ponieważ wspominana tabela powinna zawierać zebrane dane z kilku encji, a także kilka kolumn wyliczeniowych – nie byłem w stanie ich uzyskać za pomocą widoku Power App lub zapytania w języku FetchXml. Dodatkowo w stopce tabeli powinien znajdować się przycisk, służący do wykonania kilku operacji na encjach w systemie na podstawie wyedytowanych w tabeli informacji (utworzenie nowego rekordu, przeliczenie wartości jego atrybutów oraz dezaktywacja bieżącego rekordu). Opisywaną funkcjonalność postanowiłem zbudować za pomocą 3 ww. technologii.

Zasoby sieciowe – nie mogło być prościej

W przypadku zasobu sieciowego całą funkcjonalność zbudowałem, wykorzystując 2 pliki (HTML, JS) oraz zewnętrzny framework VueJS jako mechanizm do bindowania danych. Posiadając ID bieżącego rekordu pobrałem wszelkie niezbędne dane za pomocą usług sieciowych REST.  Algorytmy do wyliczania nieistniejących w systemie kolumn zostały zapisane w kodzie (VueJS bardzo ułatwia ich implementację za pomocą właściwości „computed”). Obsługa przycisku została z kolei zaimplementowana  za pomocą niestandardowej akcji (requestu), która była uruchamiana ponownie za pomocą end-pointa REST. Całość prac nad ww. funkcjonalnością zajęła mi jakieś 2-3 godziny.

PCF – ale… czemu się nie da?

Pierwszy facepalm nastąpił już w momencie rozpoczęcia prac w frameworkiem. Otóż każda kontrolka PCF zintegrowana z aplikacją Power App musi reprezentować wartość w wybranym polu lub tabeli. Owa wartość jest parametrem wejściowym dla kontrolki, a także jest przekazywana formatce poprzez standardowe „wyjście” w momencie zmiany. Niestety twórcy frameworka nie dali nam możliwości przekazania do kontrolki ID bieżącego obiektu, z którego formatki jest ona uruchamiana. Oczywiście – ograniczenie to da się łatwo obejść za pomocą niestandardowego pola tekstowego, w które wpisujemy GUIDa danego rekordu. Przyznacie jednak, że metoda ta budzi pewien niesmak 😉. Przeszukując fora dyskusyjne, udało mi się dotrzeć do informacji o tym, że informacje o identyfikatorze oraz typie obiektu, na którego formatce została umieszczona kontrolka, możemy uzyskać z kontekstu kontrolki (jeden z jego parametrów wejściowych metody init). Jest to jednak nieudokumentowana przez twórców i oficjalnie niewspierana metoda, o której ludzie z Microsoftu mówią, że prawdopodobnie zmieni się w najbliżej przyszłości.

Kolejną kiepską w moim przekonaniu kwestią jest konieczność budowy warstwy prezentacji kontrolki bezpośrednio w kodzie JS/TS. Jak to wygląda? Otóż tak, jak na poniższym przykładzie:

        var myDiv = document.createElement("div");
        myDiv.id = 'app';
         
        //Add your content to the DIV
        myDiv.innerHTML = "<div id=\"id\">" 
            + "ID:  " + this._value 
            + "<div>"
            + ""<h1>This is my view</h1>"
            + "</div>"
            + "</div>";

        container.appendChild(myDiv); 

Nie wiem, co o tym myślicie, ale jak dla mnie przypomina to najgorsze czasy początków JavaScript i mieszania w jednym pliki warstwy logiki, prezentacji i dostępu do danych aplikacji. PCF pozwala ponoć na wykorzystywanie szablonów JSX biblioteki ReactJS, ale…

  • Po pierwsze – ponownie nie jest to nigdzie udokumentowane lub opisane
  • Po drugie – do budowy mojej kontrolki nie chciałem używać dedykowanych komponentów ReactJS, co więcej nie chciałem używać Reacta w ogóle, zwłaszcza że do implementacji mojego ekranu użyłem już komponentów pochodzących z biblioteki VueJS. W moim przekonaniu PCF nie powinien zmuszać programisty do używania konkretnego front-endowego frameworka.  

Na kolejną niewygodę napotkałem, próbując skorzystać z API Common Data Service’u. PCF dostarcza do tego dedykowane API (powstań!), ale o zgrozo… daje one jedynie możliwość wykonywania operacji typu CRUD (spocznij!). Zapomnicie więc o wywoływaniu funkcji lub niestandardowych akcji za pomocą end-pointa REST. Oczywiście – cały czas możemy skorzystać z JavaScriptowego obiektu XmlHttpRequest, ale dochodzą nam w tym przypadku kolejne utrudnienia, jak chociażby przekazanie do kontrolki informacji nt. adresu serwera, z którym chcemy się komunikować. Jej kontekst uruchomieniowy nie zawiera tej informacji.

Kiedy już udało mi się wygrać walkę z opisanymi powyżej problemami – napotkałem na kolejną niedogodność. Otóż kontrolki PCF importowane są do systemu jako elementy zarządzanego rozwiązania (managed solution). Każda próba zmian w kodzie kontrolki wymusza więc usuniecie z systemu jej poprzedniej wersji (wraz z zależnościami!) oraz wgranie ponownie nowej, co zajmuje zazwyczaj kilka dobrych minut. O tym, że twórcy frameworka zapomnieli o możliwości nadawania solucji zawierającej kontrolkę własnej nazwy, litościwie już nie wspomnę.

Podsumowując – za pomocą frameworka PCF udało mi się zbudować pożądaną funkcjonalność. Niestety trwało to dużo dłużej, było o wiele mniej wygodne z punktu widzenia developera i na dodatek wymagało zastosowania kilku „hacków” oraz rozwiązań uznawanych powszechnie za hmm… nieeleganckie.

Canvas App – jak to k… wygląda?

Integracja aplikacji Canvas z formatką aplikacji sterowanej modelem wygląda podobnie jak w przypadku kontrolki PCF. Wybieramy w edytorze nasz atrybut lub widok i określamy, że do prezentacji danych wykorzystywana będzie nowe lub istniejące „płótno”.

W przypadku aplikacji Canvas problemem, którego nie udało mi się obejść, był… wygląd ekranu. Stosowane w wewnątrz niej style różnią się od tych z aplikacji sterowanej modelem. Wielkości czcionek są różne (Segoe UI, 14 w aplikacji Canvas i Segoe UI 14 w Unified Interface wyglądają zupełnie inaczej :O) na dodatek automatyczne skalowanie ekranu powoduje, że na naszym płótnie zaczynają dziać się dość dziwne rzeczy.

Innym problemem jest mocno ograniczone możliwości przetwarzania danych w aplikacji i  korzystania z end-pointa REST. Tak naprawdę jedyną opcją w tym przypadku jest skorzystanie z procesu Power Automate (niestety asynchronicznie i bez możliwości callbacku do formatki) lub budowa warstwy pośredniej w Common Data Service prezentującej dane gotowe do wyświetlenia. Na dodatek makra Power App w moim przypadku nie zawsze działały zgodnie z oczekiwaniami i dokumentacją. Być może wynikało to z faktu, że kontrolka, której postanowiłem użyć do prezentacji danych (Data Table), cały czas jest dostarczana jako „Preview”, ale wszystko to nie powinno się zdarzyć w systemie, który w założeniach miał służyć użytkownikom nietechnicznym.

Finalnie zrezygnowałem z budowania opisywanej na początku funkcjonalności za pomocą formatki Canvas App. Dostarczenie jej wymagałoby konieczności stworzenia dodatkowych komponentów fasadowych, a końcowe doświadczenie użytkownika byłoby i tak dalekie od oczekiwanego.

Wnioski

Opisane powyżej przypadki pokazują, że w pewnych scenariuszach stare dobre zasoby sieciowe bywają niezastąpione. W omawianym powyżej przypadku użycia wykorzystanie pozostałych 2 technologii okazało się albo drogą przez mękę, albo nie sprawdziło się wcale. Nie zrozumcie mnie źle – PCF oraz zagnieżdżone aplikacje Canvas to ciekawe i rozwojowe rozwiązania, ale przeznaczone do mocno specyficznych zastosowań i na tym etapie rozwoju niebędące w stanie zastąpić zasobów sieciowych.

W tym momencie scenariusze użycia poszczególnych technologii wyglądają w moim przekonaniu następująco:

  • Jeżeli zależy Ci na stworzeniu skomplikowanego, niestandardowego elementu UI, zawierającego dane z wielu powiązanych encji  zasób sieciowy jest w dalszym ciągu najlepszą opcją.
  • Jeżeli zależy Ci na wizualnej reprezentacji danych w polu danego typu (uwaga, nie wszystkie typy danych są w tym momencie wspierane) lub tabeli i chesz, żeby stworzony kod działał zarówno w aplikacjach Canvas oraz aplikacjach sterowanych modelem,  zagnieżdżony komponent Power App może być dobrym wyborem.
  • Jeżeli nie masz pojęcia o programowaniu i chcesz w prosty sposób zaprezentować nietekstowe dane znajdujące się w źródłach innych niż CDS (np. zdjęcia umieszczone na portalu SharePoint lub dysku OneDrive) i nie musisz wykonywać skomplikowanych operacji przekształceń danych wejściowych zagnieżdżony Canvas App może być opcją wartą rozważenia.

Obrazek wyróżniający pochodzi jak zwykle z serwisu Unsplash.com

* Błyskawiczny rozwój chmury oraz rozmaitych technologii związanych z tworzeniem i utrzymywaniem aplikacji spowodował, że praca z każdym systemem mającym więcej niż 3 lata określana zaczyna obecnie być określana jako: „IT Archeology” 😉

Total Views: 242 ,
Be the first to comment

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *