Sovelluksissa todella usein tarvittava ominaisuus on henkilön valinta (People picker). Poimitaan listalta hyväksyjä, omistaja, seuraava käsittelijä tms. Mikäli tietovarastona käytetään SharePoint-listaa, on tämä suoraviivaista. Käytetään Henkilö-tyyppistä kenttää, johon voi helposti valita tenantin käyttäjistä oikean. Kenttään voi valita jopa useita käyttäjiä.

Kaikki toimii Canvas Power Appsissa suoraan ilman sen kummempaa ihmettelyä.

Mutta entäs kun käytämme tietovarastona Dataverseä? Onko kaikki yhtä suoraviivaista?

On ja ei ole.

Dataversen käyttäjien hyödyntäminen

Käytetään yksinkertaisena esimerkkinä tapaamisia (meetings), joiden tietoja tallennetaan dataverseen. Yksi tallennetavista tiedoista on kokouksen puheenjohtaja (chairman).

Puheenjohtaja on luontevaa lisätä LookUp-kenttänä, joka osoittaa käyttäjät (Users) -tauluun.

Näin puheenjohtaja voidaan kätevästi poimia käyttäjien joukosta model-driven appsissa.

Sama toimii myös canvas appsissa.

Mitä jos haluaisimme kirjata myös kokouksen osallistujat? SharePointissa tämä onnistuu henkilö-kenttää hyödyntäen, sillä se tukee monivalintaa. Dataversessä tätä varten tehdään n:n relaatio kokouksen ja käyttäjien välille. Käytännössä osallistujat-taulu (participant).

Mutta ei mennä sinne. Meillä on tässä muitakin ongelmia.

Nimittäin nämä Dataversen käyttäjät.

Tenantin käyttäjästä tulee Dataversen käyttäjä kun

  • Käyttäjä kuuluu ympäristöön liitettyyn AAD ryhmään
  • Käyttäjällä on Dataversen käyttöön oikeuttava lisenssi

Eli Dataversen käyttäjien joukosta ei tyypillisesti löydy kaikkia tenantin käyttäjiä. Sinne päätyminen edellyttää lisenssiä. Kiusallista. Haluaisimme vain tallentaa kokoukselle sen läsnäolijat.

Läsnäolijat eivät millään tapaa (suoraan tai välillisesti) käytä itse järjestelmää. Eli he eivät tarvitse lisenssiä.

Keksitään jotain muuta.

Dataversen yhteystietojen hyödyntäminen

Entä jos käyttäisimme dataversen yhteystietoja (Contact)? Luodaan kokoukselle puheenjohtaja-kenttä, joka on LookUp yhteystieto-tauluun.

Käyttäjän tavoin homma toimii molemmissa sovellustyypeissä.

Kiva. Mutta nyt meidän pitäisi kopioida kaikki tenantin käyttäjät ympäristömme yhteystiedoiksi. Ja huolehtia siitä että käyttäjiä luodaan ja päivitetään sitä mukaa kun tenantin käyttäjät muuttuvat.

Kuulostaa aivan älyvapaalta touhulta.

Virtuaalitaulu

Entäpä jos loisimme virtuaalitaulun, joka jollain mystisellä tavalla mäpättäisiin AAD käyttäjiin?

Edelleen. Yksinkertainen ongelma ja ratkaisut kuulostavat toinen toistaan hankalimmilta.

Henkilöiden tallennus tekstikenttään

Tehdään lopulta jotain todella yksinkertaista. Tallennetaan puheenjohtaja(t) tekstikenttään. Tarjotaan kuitenkin käyttäjälle se perinteinen tapa poimia henkilö tenantin käyttäjien joukosta.

Luodaan puheenjohtajaa varten tekstikenttä.

Kokous-lomake näyttää canvas appsissa tältä.

Lisätään Office365Users-yhdistin tietolähteeksi.

Tämän jälkeen lisätään puheenjohtaja-kortille combobox, jonka valintajoukkona on haku Office 365 -käyttäjiin.

Office365Users.SearchUserV2({searchTerm:Self.SearchText}).value

Näin voimme valita puheenjohtajan tenantin käyttäjien joukosta.

Puheenjohtajan/puheenjohtajien sähköpostiosoitteet tallennetaan puheenjohtaja-kenttään puolipisteellä erotettuina.

Concat(cmbPeoplePicker.SelectedItems,Mail, ";")

Näin puheenjohtaja(t) tallentuvat siten, että tieto on vielä ymmärrettävää ja muokattavissa myös model-driven appsissa.

Entäpä olemassa olevan kokouksen muokkaaminen?

Jotta henkilövalinta-kontrolli täyttyy tallennetuilla puheenjohtajilla, tulee näistä henkilöistä (tarkemmin sanottuna henkilöistä tallennetuista sähköpostiosoitteista) luoda taulukko jossa on sekä henkilön nimi (DisplayName) että sähköposti (Mail).

Luodaan tallennetusta merkkijonosta taulukko (Split), ja täydennetään (AddColumns) se henkilön nimellä käyttäen Office365Users-yhdistinä. Lopulta nimetään sarakkeet (RenameColumns) siten, että taulukko kelpaa comboboxille.

Eli

RenameColumns(
    AddColumns(
       Split(DataCardValue3.Text,";"),
       "DisplayName",
       Office365Users.UserProfileV2(Result).displayName
    ),
    "Result",
    "Mail"
)

Taulukko asetetaan comboxin oletusarvoksi (DefaultSelectedItems). Alla punaisella esimerkki miltä muotoiltu comboboxillemme kelpaava taulukko näyttää.

Nyt lomake toimii nätisti myös muokkaustilassa.

Tekstikenttä on käyttöliittymän kannalta turha, eli sen voi poistaa.

Henkilöiden nimien selvittäminen kontrollin DefaultSelectedItems-ominaisuudessa generoi helposti turhia virheitä (eivät vaikuta sovelluksen toimintaan). Mikäli niistä haluaa eroon, voi taulukon luoda valmiiksi muokattavan rivin valinnan (tai muokkausnäytön OnVisible tapahtumam) yhteydessä.

Tähän tyyliin.

Set(varPeoplePickerValue,
  RenameColumns(
   AddColumns(
     Split(ThisItem.'Chairman (Custom)',";"),
     "DisplayName",
     Office365Users.UserProfileV2(Result).displayName
     ),
  "Result",
  "Mail"
  )
)

Optimointi

Ratkaisua voi optimoida tallentamalla tekstikenttään puheenjohtajan sähköpostin lisäksi hänen nimensä (puolipisteellä toisistaan erotettuina). Näin päästää eroon puheenjohtajan nimen hakemisesta lomakkeen muokkaustilassa.

Tämä on varsin helppoa, mikäli puheenjohtajaksi valitaan aina vain yksi henkilö.

Puheenjohtaja-kentän update-toiminto canvas appsissa näyttääkin nyt seuraavalta.

cmbPeoplePicker.Selected.Mail & ";" & cmbPeoplePicker.Selected.DisplayName

Arvo näyttää model-driven appsissa tältä. Luettavaa, mutta ei enää järin muokattavaa.

Dataverseen tallennettu puheenjohtaja valitaan kontrolliin (DefaultSelectedItem) seuraavalla kaavalla.

Table({Mail:First(Split(Parent.Default,";")).Result, DisplayName:Last(Split(Parent.Default,";")).Result})

Kaava luo jälleen taulukon, jonka sarakkeina ovat Mail ja DisplayName.

Usean puheenjohtajan valinta

Mikäli puheenjohtajia voidaan valita useita, erotellaan puheenjohtajan tiedot toisistaan puolipisteellä sekä itse puheenjohtajat toisistaan kahdella puolipisteellä.

Update-komento muuttuu seuraavanlaiseksi.

Concat(cmbPeoplePicker.SelectedItems,Concatenate(Mail,";" ,DisplayName), ";;")

Arvo näyttää model-drivenissä tältä. Aina vain sekavamman näköistä.

Olemassa olevaa riviä muokatessa comboboxin täyttäminen on pykälää haastavampaa. Dataverseen tallennetusta merkkijonosta parsitaan taulukko, jossa on lopulta kaksi saraketta (DisplayName ja Mail).

DropColumns(
   AddColumns(
     Split(Parent.Default,";;"),
     "Mail", 
     First(Split(ThisRecord.Result,";")).Result,
     "DisplayName", 
     Last(Split(ThisRecord.Result,";")).Result
   ),
   "Result"
)

Nyt sovelluksessa ei käytetä Office365User-yhdistintä, kuin ainoastaan uusia henkilöitä etsittäessä.

Samalla kuitenkin menetetään model-driven appsissa kentän luettavuus ja helppo ylläpidettävyys.

Elämä on kompromisseja.