Power Appseja tehdessä tulee usein eteen erilaiset hierarkiat. Organisaatio, tuote, palvelu, jne. Hierakkinen tieto tulee ensinnäkin tallentaa käyttökelpoisessa muodossa. Se on yleensä helppoa. Haasteet tulevat hierarkian hyödyntämisessä varsinaisessa sovelluksessa. Eli miten hierarkia esitetään, jotta siitä voi käyttäjä tehdä valintoja.
Tällä kertaa käydään läpi hierarkkisen tiedon kanssa työskentelyä. Esimerkkinä käytetään useiden kaupunkien verkkosivuilta löytyvää palveluhakemistoa.

Aloitetaan!
Hierarkkisen tiedon tallentaminen
Tallennetaan palvelut yhteen tauluun (Services Demo), jonka kentät ovat
- Palvelun nimi (Name)
- Palvelu, jonka alle palvelu kuuluu (Parent Service)
- Millä palveluhierarkian tasolla palvelu on (Hierarchy level)
- Palvelun järjestysnumero mikäli palvelut esitetään yhdessä listassa (OrderId)
- Palvelun otsikko, kun palvelut esitetään yhdessä listassa (Title for dropdpown)
Kaksi ensimmäistä kenttää kuvaavat hierarkian. Muut ovat apukenttiä sovellusta varten.

Tallennettu palveluhierarkia näyttää käytännössä tältä.

Palvelujen väliset suhteet on tiedossa, mutta valitettavasti se ei sovelluksellemme aina sellaisenaan riitä.
Valinnan tekeminen hierarkiasta usean alasvetovalikon avulla
Aloitetaan sillä helpolla.
Käyttäjän tulisi valita Power Appsissa palvelu. Voimme toteuttaa helposti käyttöliittymän, jossa käyttäjä valitsee ensin palveluhierarkian päätason ja sen jälkeen seuraavasta kontrollista seuraavan tason jne.

Löydät tarkemman kuvauksen toteutustavasta vanhasta jutustani.
Toteutus on suoraviivainen, mutta siinä on muutama ongelma. Ensinnäkin hierarkian syvyys joudutaan päättämään etukäteen. Yllä se on kolme. Toisekseen ratkaisu on toimii, mikäli käyttäjä valitsee vain yhden palvelun. Entä jos käyttäjän pitäisi valita useita palveluja ja vieläpä eri tasoilta?
Valinnan tekeminen vapaasti palveluhierarkiasta
Haluaisimme seuraavaksi tarjota käyttäjälle mahdollisuuden valita vapaasti n kappaletta rivejä palveluhierarkian eri tasoilta. Eli yhdeltä listalta / alasvetovalikosta useita riviä.
Tähän tyyliin.

Esitystapa on kaikille tuttu, mutta miten ihmeessä saamme palvelut listattua oikeassa järjestyksessä ja oikein sisennettynä? Palvelut kun on tallennettu yhteen tauluun täysin sattumanvaraisessa järjestyksessä
Meidän tuleekin järjestää palveluhierarkian rivit uudelleen siten, että palvelut ovat loogisessa järjestyksessä. Järjestys voidaan rakentaa usealla tapaa.
Palvelujen järjestäminen Power Appsissa
Luodaan uusi kokoelma ja tämän jälkeen käydään palveluhierarkian tasot läpi ja lisätään tasot oikeassa järjestyksessä kokoelmaan.
Suurinpiirtein näin.

Muodostettua kokoelmaa voi hyödyntää eri kontrolleissa.

Lista on aina ajantasainen, sillä järjestys rakennetaan sovelluksessa jokaisella käyttökerralla. Mutta hierarkian syvyys on rajallinen (esimerkkikoodissamme 3 tasoa).
Ihan kiva, mutta olisihan se yksinkertaisempaa jos palvelut saisi suoraan oikeaan järjestykseen. Tällöin niillä pitäisi olla järjestysnumero jo valmiina.
Palvelujen järjestäminen flow’n avulla
Rakennetaan seuraavaksi flow, joka käy läpi palveluhierarkian ja tallentaa jokaiselle riville järjestysnumeron siten että palvelut voi listata oikeassa järjestyksessä esim. alasvetovalikkoon sovelluksessamme.
Luodaan järjestysnumeroa varten muuttuja (Order Id) ja haetaan hierarkian päätasot, eli ne joille ei ole määritelty minkä tason alle ne kuuluvat (Parent).

Kunkin palvelun kohdalla päivitetään sen järjestysnumero, sekä kontrollissa esitettävä nimi (Title for dropdown). Tämän jälkeen kasvatetaan järjestysnumeroa.

Jokaisen rivin kohdalla haetaan seuraavaksi sen alla olevat palvelut (Level2). Ne käydään samalla lailla läpi ja päivitetään järjestysnumero. Tällä kertaa kontrollissa esitettävän nimeen lisätään alkuun ”-” merkki.

Lopuksi sama temppu tehdään vielä hierarkian kolmannelle tasolle. Tällöin kontrollissa esitettävän otsikon eteen lisätään ”–”.
Flow näyttää kokonaisuudessaan tältä.

Flow’n suorituksen jälkeen taulu näyttää tältä.

Power Appsissa voimme käyttää kontrollissa tietojoukkona suoraan taulua. Kunhan rivit järjestetään luomamme järjestysnumeron perusteella.
Items: Sort('Services Demos', OrderId, Ascending)
Esimerkiksi combobox näyttääkin nyt tältä.

Ratkaisu on helposti ymmärrettävä, mutta se toimii nyt vain 3-tasoisella hierarkialla. Jokaista uutta tasoa varten pitäisi flow’hun lisätä uusi sisäinen silmukka. Sisäisiä toimintoja flow’ssa voi olla maksimissaan 8 kappaletta.
Järjestysnumerot tulee myös luoda kun hierarkia muuttuu.
Palvelujen järjestäminen rekursiivisen flow’n avulla
Tehdään lopuksi flow, joka rakentaa palveluhierakialle oikeat järjestysnumerot riippumatta palveluhierarkian syvyydestä. Tämä onnistuu rekursiivisen flow’n avulla. Rekursioksi kutsutaan ohjelmaa, joka kutsuu itse itseään. Se on omiaan juuri tällaiseen tilanteeseen. Samalla se on kuitenkin aloittelijalle hyvin hankalasti ymmärrettävä.
Kokeillaan silti.
Luodaan flow, joka käynnistyy http-triggerillä (Child flow’t olisivat näppärämpiä tehdä, mutta ne eivät voi kutsua itse itseään).
Flow saa paramterinaan
- Sen palvelun tunnisteen, jonka alla olevia palveluja käymme nyt läpi (ParentGuid)
- Ensimmäisen vapaan järjestysnumerom (CurrentOrderId)
- Hierakiatason jolla olemme (HierachyLevel)
Alustetaan OrderId-muuttuja saadulla järjestysnumerolla ja haetaan kaikki saadun palvelun alla olevat palvelut.

Käydään tulokset läpi ja päivittään palvelulle järjestysnumero sekä hierarkiataso.
Kontrollissa näytettävään kenttään (Title for dropdown) asetetaan hierarkiatasoa vastaava määrä ”-” merkkejä.
substring('-----------------------------',1,triggerBody()?['HierarchyLevel'])
Ja kasvatetaan järjestysnumeroa yhdellä.

Huomaa että silmukkaa (Apply to each) ei voida ajaa rinnakkain, eli käydään asettamassa rinnakkaisuuden asteeksi 1.

Ja sitten se villi osuus. Kutsutaan samaa flow’ta, mutta käsiteltävän palvelun tiedoilla. Flow palauttaa aikanaan seuraavan vapaan järjestynumeron, joka asetetaan muuttujaan.

Viimeisenä vaiheena flow palauttaa kutsujalleen seuraavan vapaan järjestysnumeron, sekä tiedon millä tasolla mennään.

Koko flow on kokonaisuudessaan tässä.

Se käy yhden hierarkiatason läpi ja jokaisen palvelun kohdalla kutsuu itseään hoitamaan seuraavan tason.
Nerokasta ja sekavaa. Se on minun määritelmäni rekursiolle.
Tarvitsemme vielä toisen flow’n, jolla prosessi käynnistyy. Se käy läpi palveluhierarkian ensimmäisen tason ja kutsuu kunkin kohdalla tekemäämme flow’ta. Myös tässä tulee huolehtia ettei Apply to each -silmukkaa suoriteta rinnakkain.

Vaikka rekursion avulla voimme käydä läpi n-tasoisen hierarkian, on lähestymisessä omat rajoituksensa. Tekemämme flow pitää kutsujaansa yhteyden 120 sekuntia. Käytännössä flow’n rouhiessa kunkin päätason alla olevaa hierarkiaa, sillä on siihen 120 sekuntia aikaa. Tämän jälkeen kaikki on pilalla.
Yhteenveto
Kävimme läpi kolme hyvin erilaista tapaa valmistella palvelulistaus näytettäväksi Power Appsin kontrollilla. Mitä näistä itse käyttäisin?
- Mikäli hierarkia elää kokoajan, rakentaisin todennäköisesti kokoelman Power Appsissa (mikäli hierarkiassa on tasoja alle 2000). Toteuttaisin kaavan siten, että jos tulevaisuudessa hierarkiaan tulee muutama taso lisää, se toimii edelleen.
- Mikäli hierarkia on melko pysyvä, muodostaisin sen valmiiksi flow’lla mutta ilman rekursiota. Tekisin läpikäynnin joka kykenee käymään sallitut 8 tasoa läpi. Flow käynnistyisi käsin tai kun hierarkiaan tehdään muutoksia.
Rekursiivisen ratkaisun unohtaisin. Vaikka se päheä onkin, sen toimintalogiikka ei välttämättä aukea seuraavalle kansalaiskehittäjälle joka ratkaisua aikanaan päivittää.