The #2 most requested feature in Company Communicator!

Company Communicator #1 most requested feature is improved reporting (yeah, we all need that) and I know some colleagues are already working on that :).

But what about #2? That is the ability to have groups of authors targeting only a limited set of users. That is, think about installing multiple instances of the message composition app for specific authors and then controlling which groups are allowed for those authors.

By default CC allows any users listed on the AuthorizedCreatorUpns configuration variable to send communications for any Active Directory groups, any teams with the bot installed, any user in your organization. I’ve seen dozens of customers asking if there is a way to restrict the groups, so authors can’t send a communication “by mistake” to every person in your company.

Well. You can now do that… actually you can help us to test a new Company Communicator variant that has the ability to segment composition by authors and target specific authorized groups.

The new administration level (Master Admins)

To create that feature we implemented a new administration level. The master admins group.

Master admins install Company Communicator for different business units (in their specific Teams channels), they also configure CC for that specific business unit, customizing the card and listing all groups that are authorized for authors with access to a specific instance of the composition interface.

Azure admins need to list all master admins on a new configuration variable for the CC App Service named MasterAdminUpns. The Azure administrator also enable the targeting mode by setting up a new boolean configuration variable named TargetingEnabled.

That is, after re-sync your deployment against the variation repo/branch, you need to go ahead and configure those two variables to enable the targeting functionality.

  • TargetingEnabled: [true|false] – Enables/disables the CC targeting feature.
  • MasterAdminUpns: UPN – List all upns for the master admins.

You also need to list the master admins in the AuthorizedCreatorUpns so they can use the composition interface to customize the application for a specific business unit.

Installing the Authors Interface with Targeting mode enabled

When you enable the targeting mode and list your user as master admin, you can go ahead and install the authors interface in any channel. We are using a paradigm where you represent a specific business unit using a Teams team and channel.

Let’s suppose you are configuring Company Communicator to allow communication for the Sales and Marketing Department. First step is to go to the Sales and Marketing team and create a new channel, let’s call it Sales News.

I included just Megan Bowen as an authorized author for the Sales News channel (she is already listed on the AuthorizedCreatorUpns configuration variable in Azure).

Now we can setup Company Communicator on the new channel. Click on (+) at the top of the screen and install the CC authors interface. You will see the first change we implemented right on the configuration page.

If you have a private channel, the system will mention the name of the channel twice, if you have a public channel, the name of the team followed by the name of the channel will appear. The system also recognizes you as a master admin and show your UPN.

If a non admin user attempts to install the app, an error message will be shown asking the person to contact a master admin.

Business Unit Configuration

In our example, the Sales and Marketing / Sales News is a business unit. You may have as many as you want, and the idea behind this variant is to ensure you will have a set of messages that are exclusive for that business unit. Exclusive in terms that you have a controlled set of authors that have access to the composition interface and you can also control and allow those authors to choose just a specific set of groups to target and send the message.

Now that you have the authors interface installed for the Sales News, go ahead and click on the new button that you will see on the top right corner. Manage Groups.

When you click on Manage Groups you get access to the personalization interface for this business unit. You can upload an image and a BU title that will be used to personalize the messages originated from this instance of the authors interface.

That is the place where you define the authorized target groups. Those will be the only groups available for Megan Bowen (the non admin author) when she creates and send new messages using the app.

On the above screen you see that a small logo was uploaded, the title was defined as Sales and Marketing News and three target groups were defined. Click close to save those configurations back to the database.

The app is ready to create new messages. Ask Megan to access the app and create messages, she will be restricted to the three groups you defined when sending the notification. She will also send all messages branded with your business unit logo and title.

Creating New Messages

If you create new messages using a master admin account, you will have flexibility to select any targets for the message. See below.

Now let’s use teams as Megan Bowen. Note that she doesn’t have the Manage Groups button. She can only create messages.

She can also create messages using the interface, but she can’t send to everyone. Only the defined set of groups defined by the master admin is available for her.

Another cool thing is that master admins can create messages, select the send to all and then allow Megan just send the message. She can’t select the everyone option, but a master admin can pre-select and leave the message to be sent by Megan (or other author).

How to Update your Company Communicator Deployment

Please be aware that this variation is under development and may not be 100% stable. I invite you to test and provide feedback. Follow the steps below to update your Company Communicator 4.1 deployment.

  1. Open your Azure Portal and authenticate using admin credentials.
  2. Open the resource group where you installed Company Communicator.
  3. Select the App Service being used by CC and click on Deployment Center, under Deployment.
  4. In Settings, click Disconnect under External Git.
  1. Click OK to disconnect your deployment.
  2. Under Source, select External Git.
  1. In Repository, type https://github.com/cristianoag/microsoft-teams-apps-company-communicator.git
  2. In Branch, type dev
  3. Leave the Repository Type as Public, and click Save.
  4. Click Sync.
  5. The whole update process will take a few minutes. Make sure you see Success (Active) on the logs tab.
  6. Now repeat that for each one of the Azure Functions you have on the same resource group. Those are the resources listed as:
    • <ccname>-data-function
    • <ccname>-function
    • <ccname>-prep-function

Enjoy… Cristiano.

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

More Company Communicator Features

I’m writing this post just after my participation on a series of events created by the Microsoft Brazilian subsidiary on collaboration with Teams. I had the pleasure to speak about how Company Communicator, our #1 app in Teams is changing the way companies from different sizes communicate with their employees. If you speak Portuguese, I invite you to watch my session and demo clicking here.

But I’m here today to share with you all a few additional Company Communicator contributions. I say additional because I’m sure you all remember about the upload images and message scheduler I posted last month (click here).

A few weeks ago I got a request from a big customer in Europe to allow the use of formatting elements when creating communications, including the ability to have hyperlinks and multiple buttons on the adaptive cards used by company communicator.

I also got a request, this time from a customer in the US, to include something to call user attention when sending very important messages. Something like an importance alert that could be associated to specific messages.

Here I am providing more details on those features so you all can also improve the way you use Microsoft Teams in your companies.

Summary Formatting

You can now leverage MarkDown when creating the summary of your messages. Due to a limitation when using adaptive cards inside Microsoft Teams, it is basically restricted to bold, italic, hyperlinks, ordered and unordered lists. You just need to go ahead and use appropriate markdown tags when composing your CC messages, the resultant formatted text will be presented real time on the adaptive cards shown on the right hand side of the authors interface.

Multiple Action Buttons

By default CC is restricted to a single action button. We got requests from multiple customers asking to increase the amount of buttons and allow users to pick and choose. That is delivered, you can now include up to four buttons on the adaptive card. Just click on the (+) sign located on the side of the buttons area title and provide values for the title and Url.

Important Messages

This variant of CC now provides a way to flag specific messages as important. When you select that option, users will not only receive the message but will be alerted with a notification shown under Teams activity section. When sending 1:1 messages, users will basically receive two notifications, one from the message per se and another inside the alert feed.

You should use this option when creating important messages for your employees and as a way to really call attention when you need.

The Update Process

If you are interested in those new features, keep in mind that you need to update your current CC implementation. First of all, make sure you have the 4.1 version deployed, then follow the steps below to update the App Service and the three Azure Functions used by Company Communicator.

  1. Open your Azure Portal and authenticate using admin credentials.
  2. Open the resource group where you installed Company Communicator.
  3. Select the App Service being used by CC and click on Deployment Center, under Deployment.
  4. In Settings, click Disconnect under External Git.
  1. Click OK to disconnect your deployment.
  2. Under Source, select External Git.
  1. In Repository, type https://github.com/cristianoag/microsoft-teams-apps-company-communicator.git
  2. In Branch, type dev
  3. Leave the Repository Type as Public, and click Save.
  4. Click Sync.
  5. The whole update process will take a few minutes. Make sure you see Success (Active) on the logs tab.
  6. Now repeat that for each one of the Azure Functions you have on the same resource group. Those are the resources listed as:
    • <ccname>-data-function
    • <ccname>-function
    • <ccname>-prep-function

Common Problems

I updated my CC deployment and all my messages are being sent without the buttons I defined!

Please, make sure you updated not only the App Service but all Azure Functions. If you just update the app service, the interface will allow you to include new buttons but the preparation and sending functions will not be aware of the updates you’ve done.

I updated my CC deployment, created a message with the importance flag enabled and messages are not being sent as important.

Please, make sure you updated not only the App Service but all Azure Functions. If you just update the app service, the interface will allow you to include new buttons but the preparation and sending functions will not be aware of the updates you’ve done.

After the update changes are not available on my CC authors interface.

First make sure you clicked on the Sync button. If you clicked there, make sure you already have Success (Active) flagged on the logs tab. If you have both, try to access the authors interface from a different client just to make sure you are not facing any cache issue. If you manage to get the updates, clear the teams client cache or your browser cache.

Enjoy… Cristiano.

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

Teams Speaker Queue now in 44 languages

A few weeks ago we released Speaker Queue Teams Speaker Queue | techpeanuts (tech-peanuts.com) a Teams meetings extensibility app template created to improve your meetings by defining and controlling time designated for each speaker/topic.

We are now releasing version 1.1 with bug fixes and support for 44 languages! Please try it, give your feedback and contribute to improve it.

Release Version 1.1 · OfficeDev/microsoft-teams-apps-speaker-queue (github.com)

Enjoy!

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

Teams Company Communicator Improvements

What is Company Communicator?

Company Communicator or just CC is one of the most used Teams app templates. It enables corporate teams to create and send messages intended for multiple teams or large number of employees over chat, allowing organization to reach employees right where they collaborate. 

Thousands of customers use Company Communicator every day for scenarios like new initiative announcements, employee onboarding, modern learning and organization-wide broadcasts.

CC is backed by an Azure app service with a React app providing an interface for designated content users to create, preview, collaborate and send messages. It is a great example of how Azure can be used to extend teams, leveraging multiple cloud concepts and Azure services like functions, storage, bots and the service bus.

Being so widely used, Company Communicator is also the number one app in feature requests. Some of our smartest partners are currently working with multiple customers defining new scenarios, implementing extensions and other customizations. Those engagements generate CC variations and bring more and more customers to know and use the template.

Overview

Motivation

We all know that a diverse company is always better positioned to retain talent, and ultimately win on the competitive market.

A few weeks ago my colleague @Pradeep Bethi came up with the result of an effort to create a solution to congregate people around Employee Resource Groups (ERGs), have an efficient way to communicate messages and provide an intelligent way to clarify and ask questions, contributing to the overall company diversity.

The diverse team lead by Pradeep was able to combine Company Communicator, FAQ Plus and a brand new React application to create a new Teams app template with the major goal to foster diversity and inclusion in enterprises.

Customers loved that template, but some of the limitations of Company Communicator came to light. They were complaining of basically two things:

  1. The “feature” that basically mandate that images used in communications need to be posted in a public website. Authors in Company Communicator just reference, using an URL the image that is going to be used in the cards sent to users.
  2. Inability to schedule messages. Customers would like to schedule a few communication messages to be sent in the future. For example they could pre-configure the app to send customized messages on specific D&I dates of interest like the ones listed by the United Nations International Days and Weeks | United Nations or other websites like 2021 Workplace Diversity and Inclusivity D&I Calendar | Kazoo (kazoohr.com).

Great chance to engage and support!

New Features

Two new features were incorporated into a fork of Company Communicator 4.1 and also ported to the D&I Connect App template. Github repositories with both solutions are available for your reference:

Upload Image

The upload image feature is basically a button to allow authors to upload images to be used in Company Communicator communications. It is a front-end modification made in a single page of the CC React client application that uses a few react components and a custom function to convert an image on its base64 representation.

The same column used to store the image URL is used to store the base64 string. That allowed no changes in the Azure back-end components and a simple deployment. Azure storage tables have a limitation of 64kb and Teams can only support adaptive cards with 32kb in total. So the change we made controls the size of uploaded images to ensure we will not violate those limitations.

The result allows customers to use company communicator without the requirement to keep internal images in publicly accessible websites.

The new upload button when creating new company communicator messages

Message Scheduler

The message scheduler is a more complex change. New columns were incorporated to the Azure storage table to control the scheduled date and the status of the messages. A new background task was also implemented using IHostedService and the BackgroundService class.

The background service checks every 5 minutes if there are pending scheduled messages to send and execute the steps required to send the notifications appropriately.

We also made a few changes on the interface to allow authors to define when messages will be sent.

The new scheduler interface

When scheduled, messages become available in a third section created in the main messages interface. The Scheduled Message section allows authors to send notifications right away, make edits, copy the message, etc.

The new Scheduled messages section

Deployment

Sold to the new Company Communicator improvements? The deployment is super easy. If you already have Company Communicator 4.1 deployed, just open your Azure portal, select the App Service you are using to host the application and click Deployment Center.

Disconnect the source you are using and create a new External Git connection pointing to the repo where the changes were incorporated.

After disconnecting the previous GitHub source, under manual deployment (push), select External Git.

Then on Repository, type the https://github.com/cristianoag/microsoft-teams-apps-company-communicator.git, under Branch type master.

Now click Save and then Sync.

Wait until the deployment finish. You will have your Company Communicator with the new scheduler and the ability to upload files.

Now repeat that for each one of the Azure Functions you have on the same resource group. Those are the resources listed as:

<ccname>-data-function

<ccname>-function

<ccname>-prep-function

Comment if you have questions or need help! Have fun, Cristiano.

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

Teams Speaker Queue

Hi there! We’re all participating in a ridiculous amount of online meetings lately. Some very organized, some fun, some rewarding, but some just disorganized and a waste of time. How can we help to improve your online meetings?

A few months ago I started playing with meetings extensibility and Power Apps. The very first example I created was just a clock application to kind of measure the amount of time spent by speakers during a meeting. That was subject of the Power Apps with Teams Meetings Extensibility | techpeanuts (tech-peanuts.com) article I posted here.

Since then a lot happened. We now have Power Apps design tools inside Teams, we have a Teams object in Power Apps to collect specific information about the various contexts and we have Microsoft Dataverse.

Well… why not combine all those things and expand the clock idea into a Speaker Queue application for Teams? That happened!

With the awesome support, guidance, sample code, and extensive contribution from @Dajian Dong, @Aditya Challapally, @Shuo Chen, @Pawan Gulati and others, I have the pleasure to announce the pre-release of the Speaker Queue App template.

Speaker Queue is a Teams meetings extensibility app template created to improve your meetings. It can be used to define topics and control the time assigned to each speaker during online meetings.

Once deployed, Speaker Queue can be configured in meeting invites, offering experiences before and during online meetings. Before your meeting, you can use the app to define a person who will be responsible to control the list of topics/speakers and during meetings, the app offers a synchronized countdown view to all participants, so they can be aware of speaker turns.

The Speaker Queue app template is currently in pre-release and will be published in the official Teams App Templates page soon.

I would like to invite you to deploy the pre-release version and contribute to the project using our official GitHub project page. Please if you find any issues use GitHub to let us know and improve the application.

Check the following resources available today for you:

UPDATED ON 5/4/2021 – New version published Release Version 1.1 · OfficeDev/microsoft-teams-apps-speaker-queue (github.com)

Have fun! and improve your online meetings… 🙂

Cristiano

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

A Simple Teams Meetings Extensibility App – Part 1

A few weeks ago I published an article here explaining how to use Power Apps to extend meetings in Teams. Power Apps is super easy and powerful, but so far it doesn’t provide access to all Teams meetings extensibility APIs. The only thing we can basically do with Power Apps currently is place the app in a panel that runs during meetings or work with the pre/post tabs to deliver experiences.

This time I want to provide a simple step by step approach to create meetings extensibility experiences on its full potential. For that we will need traditional web development. I’ll try to keep things simple and at the same time bring new cloud concepts so you can learn new things reading the article.

First a few concepts

If you search for meetings extensibility APIs documentation you will find that currently we can create apps to interact with teams meetings in many ways. We can call the Graph API and create meetings, we can get meeting information also using Graph API, and we can also create apps that interact with meetings in pre/during/post moments.

Meetings extensibility apps (the ones that run pre/during/post meetings) can basically call three APIs to get information about the meeting, its participants and to create pop-up notifications.

Pre and post meetings experiences are implemented by your app running in a tab configured in the meeting invite.

Pre-Meeting Application running in an invite tab

pre-meeting tab view

Post-Meeting Application running in an invite tab

post meeting view

During meetings, apps can run on a side panel or create pop-up notifications to interface with users.

In-Meeting Side Panel AppIn-meeting-dialog view

In-Meeting Pop-Up notification

in-meeting experience

How to create my first meetings extensibility app

As I said, let’s keep things simple. Let’s focus on creating a pre-meeting tab and learn how to call the APIs so we can get your first meeting extensibility app running inside teams.

Requirements

Uploading the Aample App

  • Create a folder where you will place all your app files. We will create three files:
    • main.css will have the styles that we will use in the html single page application we are creating.
    • index.html will have the single page application (html and JavaScript) that we will use for the main app.
    • config.html will have the configuration page for the app.
  • Open a command prompt, navigate to the folder you created and type “code .”
  • Click File, New File.
  • Paste the following code:
body {
    font-family: monospace;
}

ul {
    font-family: helvetica;
}

li {
    list-style: circle;
  }
  
.list {
    list-style: square;
  }
  
#msg {
    font-family: monospace;
}
  • Save the file as main.css.
  • Click File, New File.
  • Paste the following code:
<!DOCTYPE html>
<html>
<head>
    <script src= 'https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js'></script>
    <meta charset="UTF-8">
    <title>Teams - Really Simple Meetings Extensibility SPA - Config Page</title>
    <link rel="stylesheet" href="main.css">
</head>

<body>
    <h1>Config Page</h1>
    <h2>Present some configuration options here and let the person who is configuring the app change settings.</h2>
    <h2>Icons, colors, differente content pages, etc</h2>

    <script>

    microsoftTeams.initialize();
    microsoftTeams.settings.setSettings({
        contentUrl: "https://m365x257948blogpost1.z22.web.core.windows.net/index.html",
        entityId: "123456",
        suggestedDisplayName: "Meeting Panel",
        websiteUrl: "https://m365x257948blogpost1.z22.web.core.windows.net/index.html"
    });
    microsoftTeams.settings.setValidityState(true);
    
    </script>
</html>
  • Save the file as config.html. Note that we will return to this file later to update the contentUrl and websiteUrl with the URL of the index.html file.
  • Click File, New File.
  • Paste the following code:
<!DOCTYPE html>
<html>
<head>
    <script src= 'https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js'></script>
    <meta charset="UTF-8">
    <title>Teams - Really Simple Meetings Extensibility SPA</title>
    <link rel="stylesheet" href="main.css">
</head>

<body>

    <!-- html -->
    <h1 id='h1title'></h1>
    <table>
        <tr><td>User: </td><td><div id='userid'></div></td></tr>
        <tr><td>Theme: </td><td><div id='theme'></div></td></tr>
        <tr><td>MeetingId: </td><td><div id='meetingid'></div></td></tr>
        <tr><td>FrameContext: </td><td><div id='framecontext'></div></td></tr>
    </table>
    <!-- html -->

    <script>
    let h1 = document.getElementById('h1title');
    
    //initializes Teams SDK
    microsoftTeams.initialize();
    
    //gets the user context using Teams SDK
    microsoftTeams.getContext((context) =>{
        let userId = document.getElementById('userid');
        let theme = document.getElementById('theme');
        let meetingId = document.getElementById('meetingid');
        let frame = document.getElementById('framecontext');

        //updates the divs in the table with the context variables
        userId.innerHTML = context.userPrincipalName;
        theme.innerHTML = context.theme;
        meetingId.innerHTML = context.meetingId;
        frame.innerHTML = context.frameContext;

        //checks if the tab is running on the panel or in pre-meeting
        if (context.frameContext == 'content') {
            h1.innerHTML = 'This is the pre-meeting experience';
        } else {
            h1.innerHTML = 'This is the side panel content';
        }
    });
    </script>
</html>
  • Save the file as index.html.
  • Click the Azure icon on the left rail in VS Code. Expand Storage and then your Azure subscription. Right click the subscription and select Create Storage Account.
image_thumb.png
  • Provide a name for your storage and click Enter. Wait until the storage account is created in your subscription. When the storage account is created, right click it and select the “Configure Static Website…”.
image.png
  • Press Enter to confirm index.html as the index document name (you will need to upload the file as index.html). And press Enter to confirm the default value for the 404 error message. Wait until the storage is configured to host static websites.
  • Go back to the VS Code Explorer and right click the index.html file (the file you created/edited). Select “Upload to Azure Storage…”. Select your subscription and the storage account you created and configured. Select Blob Containers, then $Web, then /.
  • Your files will be uploaded to the Azure Storage.
  • Click the Azure icon on the left rail in VS Code. Expand Storage and then your Azure subscription. Right click the Storage you created and select Browse Static Website. In your browser, copy the URL of the website.
  • Now edit the config.html file and paste the value you copied on contentUrl and websiteUrl
  • Upload the config.html and the main.css files to the Azure Storage. You need to right click the files and select the option to Upload to Azure Storage. Select your subscription and the storage account you created and configured. Select Blob Containers, then $Web, then /.

Creating the Teams Manifest

Now that you have the sample application already uploaded to the Azure Storage, we need to configure a teams manifest to make it available inside Teams. 

  • Download the sample manifest file here. 
  • Unzip the file and edit the manifest.json file.
  • Change the value of configurationUrl to point to the URL of your config.html file. Remember that it is the base URL of your Azure Storage + /config.html.
  • Replace the value you will find in validDomain by the base URL you have for your Azure Storage. Please note that validDomain doesn’t need the https:// on the beginning of the value.
  • Save the json file. 
  • Zip the manifest.json file together with the two icons you have on the original zip package. Make sure all files are in the root of the zip file.
  • Now open your teams client and load the zip file as an app. You need to click apps, then Upload a Custom App.
  • Remember this is a meetings extensibility app, so it will be available to be included in calendar items when you invite someone for a meeting.

When creating the meeting, inviting someone and adding the app, you will get the configuration message and need to click Save. As soon as you do that, the application will be incorporated into the meeting invite and you will see the screen below.

Screenshot 2021-02-23 170858

Note that if you join the meeting, the app will be available to run as soon as you click on the icon that is available on the top right corner.

Screenshot 2021-02-23 171132

What I’ve Done?

Well. Now some context on what you just finished. Your app is a simple HTML page (a single page application) that uses JavaScript to call the Teams Client SDK. The latest version of the SDK has one of the APIs that we use for Teams meetings extensibility apps.

That is the API to get the user context. 

Screenshot 2021-02-23 171527

The user context provides some properties you use for your application. For example you know using the FrameContext property if the application is running in the pre/post meeting tab or in the in-meeting side panel. That is important so you can make your application behave appropriately depending on where your users are using it.

Another important property is the MeetingID. When you have the meeting identification you can call other APIs and get data about the invite or other properties of the meeting. You also have access to the theme used in Teams as well as the user name running your app.

The list of properties returned by the microsoftTeams.getContext API is available at Get context for your tab – Teams | Microsoft Docs

Now I invite you to check the code and discover where in the index.html we are calling the getContext API. You will see that it is a simple JavaScript call to the Teams Client SDK.

The other APIs available to get the role of the user in the meeting and to create notification popups will be object of the part 2 of this article.

Have fun and thanks for reading!

Cristiano

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

How to run any website as a Teams app!

The Request and Initial Learnings

So you have been asked to make your company website or your company intranet website available in Teams… directly
from the left rail. That is, together with the Activity, Chat, Teams, Calendar, and other default Teams icons, you
want a button to allow your users access the Intranet directly from the main Teams window (figure below on the left).

image  image

You take the first step and research how to do it. You find out that using an app called App Studio you can create something called manifest and also a Teams App, that combines the manifest and the icons you want to display on Teams. Nice!

You go ahead and install App Studio. Run it and click on the Create a new app in the Manifest editor tab.

You fill out the basic information for the app and then click Tabs under capabilities. That is the place where you will add your Personal Tab. The personal tab is the entity that will be used to link your website to the button/icon that will be displayed on the Microsoft Teams interface.

You call the personal tab Intranet, use an unique entity id and use both Content URL and Website URL fields to point to the website you want to link. For the purpose of this article, let’s use the ubiquitous https://www.microsoft.com web site (figure above on the right).

Nice!!! We’re getting there. Now we need to install the app in Teams and test (before go through the whole process to publish the app to all company users). You save your tab, go to Test and Distribute under Finish and hit Install. Voilá… you now have the nice Intranet button on your Teams client. Ready to test!

But as any good feeling in IT is followed by a deception, it didn’t work.  You click your button and you just see a blank page. Nothing from the known microsoft.com website.

The Problem

So why https://www.microsoft.com website is not displaying on Teams (please replace www.microsoft.com by any website you are using and keep in mind that some websites work and some don’t).

But why am I getting a blank page? That is because www.microsoft.com and many other websites have a security feature that blocks them to be loaded inside an iFrame, and Teams personal tabs are implemented using an iFrame.

You can easily prove that is the issue with a simple html with an iFrame. Just save the content below as iframetest.html and open it in your browser.

Click here to download the iframetest.html file (code below).

image

You will see the following result:

image

Going a little further on the technical details, the reason behind is associated to a specific http header that is sent by the webserver hosting the website that doesn’t display ok. The header is called X-Frame-Options and with the value SAMEORIGIN, instructs your browser to block the display of the website in iFrames hosted outside websites with the same domain name of the website you want to display. So the iFrame would only work if hosted in any *.microsoft.com website.

If you are curious you can use POSTMAN or Fiddler to check on the returned headers and verify by your own means.

OK. Problem understood, how can we still run the intranet (or www.microsoft.com) inside Teams and have a button on the left rail pointing to the website?

Solution

First you need to understand that tabs in channels are not leveraging iFrames. Those tabs load websites just like your browser, so a site loaded by the Website app in a tab on a Teams channel is not subject to the X-Frame-Options restrictions.

Step 1 – Run your website on a tab in a channel inside a company wide team

So the first step in our solution is to create a company-wide team in Teams and create a tab in a channel using the Website app.

image image

You will end up with the www.microsoft.com (or your website that is unable to run inside an iFrame, running on a tab inside a channel of your Teams team). In the case below I have the microsoft.com website running in a tab of the General channel in my team.

image

Step 2 – Copy the link to your tab

Now that you have your tab running the “protected” website, click on the … on the upper right and select the Copy link to tab option. Save the value that was stored in your clipboard in a notepad, you will need it for the next step.

image

Step 3 – Create the Deeplink Execution html

Now we will create a html file with a javascript code that will instruct teams to execute a deeplink to the tab where you have your website running. It is a pretty simple html that loads the Teams client SDK and execute a single instruction to navigate to the tab. You need to get the content below, edit it and replace the value indicated as [LINK TO THE TAB]with the value you saved on step 2.

Click here to download the index.html file (code below)

image

Step 4 – Make the file accessible

Now you need to make your file accessible from Teams. You app will call the html file and you need a way to serve the https request for that. There are many options. You can host the file in an Azure Blob (free for the first 12 months and then USD 0.01 per month for 1GB – list price on 1/7/2021), you can use AWS S3, Google Cloud storage, a webserver that you have on-prem… you choose.

In this tutorial I’m using an Azure Blob Storage. I loaded my html file into Visual Studio Code and installed the Azure Storage extension. With the extension I can do everything from Visual Studio Code.

Click the Azure icon on the left rail in VS Code. Expand Storage and then your Azure subscription. Right click the subscription and select Create Storage Account.

image

Provide a name for your storage and click Enter. Wait until the storage account is created in your subscription. When the storage account is created, right click it and select the “Configure Static Website…”.

image

Press Enter to confirm index.html as the index document name (you will need to upload the file as index.html). And press Enter to confirm the default value for the 404 error message.

Now go back to the VS Code Explorer and right click the index.html file (the file you created/edited). Select “Upload to Azure Storage…”. Select your subscription and the storage account you created and configured. Select Blob Containers, then $Web, then /.

image

Click again on the Azure icon, expand storage, your subscription, right click the storage account and select Browse Static Website. You must see a blank page with the title “Teams Deep Link Example”.

image

Note that similar result can be achieved with any cloud storage service or even a on-premises web server that is capable to host a single static html page via HTTPS protocol.

Step 5 – Update your Teams App

Now you’re ready to go back to App Studio and replace the direct website URL you used by the one you browsed from Azure Blob storage.

Open the Teams client and run the App Studio. Click Manifest Editor and click the App you created previously. Click Tabs and edit the tab you created. In my case I’m replacing https://www.microsoft.com by https://teamstest1.z22.web.core.windows.net which is the URL that points to my static web website hosted on Azure Blob storage.

image

Click Save. Click Test and distribute under Finish and re-install the app for test purposes. Now every time you click on the Intranet icon available on the left rail, the Teams client will execute the code in your html page and navigate to the tab where the website is loaded.

Thanks for reading this!

Cristiano

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

Power Apps with Teams Meetings Extensibility

Microsoft Teams has brand new extensibility points that will enable developers to expand the meeting experience. With this new capability, developers are able to build apps or integrate existing ones within the meeting surface and provide richer collaboration experiences for users across the entire meeting lifecycle – covering events and actions from before, during, and after a meeting.

The whole concept was created to have standard web solutions incorporating the ability to interface with Teams meetings through configurable tabs and the Teams client JavaScript SDK, but what about Power Apps?

What if we can combine Power Apps with the new meetings extensibility features and quickly create applications to interface with the meeting surface. It can be done, well… currently with some limitations, but what is currently available is at least enough to get our hands dirty and create some cool stuff.

Here is what I’m trying to achieve:

“I want to create a very simple application that can be incorporated and used by any meeting participant to track time  during a meeting. It will present a clock in stop watch mode (regressive timer) that can be adjusted and used to ensure you will use the meeting time in the most efficient way.”

Untitled

Step 1 – Create the Power App

The power app will have two screens. The first one will be presented just after the configuration of the app in the meeting, just to provide more information on the purpose of the application. The second one will have the stopwatch logic, as well as a time picker and a button to set/reset the regressive counter.

Screenshot 2020-12-10 180919

Screen Intro is the first app screen. It has just three labels to present a text message to all users configuring the application on the meeting invite.

Screen Timer has a group of components formed by TextInput2 and Icon1 to allow users to set the stopwatch. The icon was used just to create a good looking text box with a small watch. The Button1 is used to set the Timer1 object with the start value and the cmp_TimePicker_1 is a custom time picker that allows users to select hours, minutes and seconds that will be configured as the start value for the stopwatch.

The cmp_TimePicker component was created and documented by Matthew Devaney here (Make A Time Picker In Power Apps – Matthew Devaney) if you are interested.

As I’m using the component to select hours, minutes and seconds I made a few changes to remove the AM/PM selection and include the ability to select seconds. 

Here are the two screens in the initial state.

Screenshot 2020-12-10 181732

Screenshot 2020-12-10 181816

One important thing is the logic required to decide which screen present when. When the Power App is called from Teams, we need to detect if it is being executed from the tab pre-meeting or during the meeting. To create the detection logic I’m using a context variable that is incorporated by Teams when calling the Power App.

The logic was incorporated to the initial execution of the app and based on the context we decide if we will navigate to Intro or Timer screens. Here is the relevant code:

Set(varSubEntityId, Param(“subEntityId”));


If(
     varSubEntityId = “{subEntityId}”,
     Set(
         varInMeeting,
         true
         ),
     Set(
         varInMeeting,
         false
         )
);


If (varInMeeting, Navigate(‘Screen Timer’), Navigate(‘Screen Intro’));

If you are not familiar with Power Apps and just want to have access to the sample package with the clock, please click here and download the zip file with the app. You will need to import it in your Power Apps environment. After the import, please save and share the app with all the users that will use it… and remember, this is not a production ready app, it is a prototype just to prove a concept.

Step 2 – Teams App

Now that you have your Power App up and running, let’s work on the Teams App. A Teams app package is a.zip file containing the following: A manifest file named “manifest.json”, which specifies attributes of your app and points to required resources for your experience, a transparent “outline” icon and a full “color” icon.

The manifest file is the key file of the app and the one we need to dedicate time to configure the meeting experience based on the Power App.

Before we start, go to the Power Apps editor and get the URL of your Power App. You can do that opening powerapps.com, and selecting details on your app under Apps. The url will be listed under Web link.

Screenshot 2020-12-10 183521

We will need the value for App ID. Copy that value as you will need it to create your manifest file.

You will also need a random UUID for your Teams App. Please go to Online UUID Generator Tool and click “Generate a version 4 UUID”. Copy the value as you will need it in to create your manifest file.

Now you have the two values you need, go ahead and download the sample manifest from here. Unzip the file and open the manifest.json.

Replace <RANDOMUUID> with the value you generated for the random UUID.

Screenshot 2020-12-10 184319

Replace <APPID> with the value you copied from your Power App.

Screenshot 2020-12-10 184413

Save the manifest.json file and zip it again, together with the two icons. Make sure you are creating a file with all the files in the root of the zip file (very important).

Step 3 – Using your App

Now that you have your Teams App package (the zip file with the manifest and the two required icons) you will need to load it to Teams. You can load the app using the Teams Admin console (if you want to distribute the application in a more robust way) or you can just upload the file using your Teams client.

Here we will use the Teams client to upload the app. Open your Teams client and click in the Apps icon located in the lower left. Click on the Upload a custom app option and select Upload for <Your Company>.

Screenshot 2020-12-10 185004

Select the zip package and click Open. The app will be installed into Teams and will be available to be incorporated to meeting invites.

Now schedule a meeting with your colleagues, open the invite and click + on the top of the screen. You will see your app listed in the Optimized for meetings section. Click Meetings Timer and you will see a new tab in the invite.

Screenshot 2020-12-10 185233

Clicking on the Meetings Timer tab you will see the first Power App Screen (intro). Click join to enter the meeting. You will now see a new clock icon on the top of the screen. Click it and the second screen (timer) will be available on the right hand panel. You can select a time from the time picker, click set and start the stopwatch clicking on the big button.

Untitled

Limitations

I’m sure our dev team is still working to improve the experience with Power Apps in this new meetings extensibility scenario. Currently there are some limitations:

  • The meeting context (user role, meeting id, meeting members, etc) is only available via Teams Client SDK (based on JavaScript). As you may know, Power Apps doesn’t allow the use of custom JavaScript code in applications, so you’re unable to detect the user role, get the meeting id, and obtain other information from the context.
  • I also couldn’t find a way to use the application from the Teams web interface. The application is available, can be installed from the web interface but the button to activate it during the meeting is not presented.

If you followed those instructions and found additional limitations, please reach out. We will make sure to communicate to the right product groups and contribute to improve the product.

Have fun, Cristiano.

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.

COVID19 Building Access App: Community Led Improvements

Desk Reservations, Floor Maps, Impersonation,  Improved Notifications, and much more…

Hello there, since the launch of the BAR App (Building Access App) the community has been very active and we have many variations being created and shared. Our customers always have specific (sometimes crazy) requirements to unblock the app usage and it is unfortunate when I see the standard package not offering the ones required.

I have been dedicating some time lately to contribute and implement some of the most requested features.

In the spirit of the community I would like to share the latest enhancements with you all. I hope those can help your company during those difficult times. Remember, this application is free for any Office 365 subscriber.

Please reach out if you have questions.

Updated Package (v1.15)
http://aka.ms/bar115

20200909_195048000_iOS20200909_195123000_iOS20200909_195150000_iOS20200909_195211000_iOS

COVID19 Building Access App: Questions per Building

Part two of the Building Access App improvements article. This time I’m documenting steps to incorporate questions per building. With this new version you will not only be able to have different approvers per space but you will be able to configure different sets of questions per building.

You can use this version for scenarios where a specific building needs to have additional screening to make employees eligible to make reservations.

20200812_165218000_iOS20200812_165226000_iOS20200812_165239000_iOS20200812_165342000_iOS20200812_165349000_iOS

All the steps required to perform the required changes into the v1.1/v1.11 version are documented below. You can also access the modified package on GitHub using the link below:

https://github.com/cristianoag/BuildingAccess/releases/tag/v1.12

SharePoint

We will create two additional columns on the questions list stored SharePoint to create the relationship between buildings and questions. Additionally we will also create a column on the AppSettings list to store a flag that will control how if we will present questions per building or not.

  • Open SharePoint Online as administrator, access the site used to store data.
  • Include two additional columns (Building and Building:ID) in BAR_KeyQuestions.
    • Click Add Column, then select More…
    • In column name type Building. Select column type Lookup. Get information from the BAR_Buildings list and select Title from the “In this column” drop down. Select ID in “Add a column to show each of these additional fields”.
  • Include an additional Yes/No column (KeyQuestionsPerBuilding) in BAR_AppSettings. Select Yes/No Type. Default Value No.

Building Admin

The Building Admin app needs to be changed to include an additional configuration option to enable/disable the ability to present questions per building. We will also configure the forms to allow the relationship between buildings and questions.

  • Open PowerApps as administrator. Edit the Building Admin app.
  • Go to Data and refresh the BAR_KeyQuestions and BAR_AppSettings connections.
  • Go to Tree View and expand the Screen Key Questions Detail screen.
  • Click Edit fields and add the Building field.
  • Go to Tree View and expand the Screen App Settings screen. Select FormAppSettings. Click Edit fields and add the KeyQuestionsPerBuilding field.
  • Move the field up to be between Require Key Qestion completion before creating reservations and Key Questions failure message.
  • Select the field, select Advanced in properties. And Unlock it to change properties.
  • Change DisplayName to “Present Questions per Building”
  • Save and Publish the app

Building Access

Below are the steps to modify the Building Access app to change the screen flow. We need to perform those changes to ensure the building selection before present health questions. Users will need to pick a building so we can filter and present just questions for the specific building.

  • On Tree View, select App, go to OnStart event. Search for the colNav definition and change the first part of the JSON to navigate to the ScreenBuilding by default.

From:

Id: 0,
ScreenName: varString.NewRequest,
Description: varString.NewRequestDesc,
Screen: If(varAppSettings.KeyQuestions,’Screen Key Questions’ ,’Screen Building’),
Image: ic_fluent_building_24_regular

To:

Id: 0,
ScreenName: varString.NewRequest,
Description: varString.NewRequestDesc,
Screen: ‘Screen Building’,
Image: ic_fluent_building_24_regular
  • Expand Screen Building, select HeaderControlBuilding and change the NavigateScreen data field.

From:

If(varAppSettings.KeyQuestions,’Screen Key Questions’ ,’Screen Home’)

To:

‘Screen Home’
  • Still on Screen Building. Select ButtonCheckAvailability and change the OnSelect event to:
Set(varSelectedBuilding , First(colSelectedBuilding) );
If(varAppSettings.KeyQuestions,Navigate(‘Screen Key Questions’,ScreenTransition.None),
Navigate(‘Screen Availability’,ScreenTransition.None));
  • Expand Screen Key Questions, select ButtonSubmitKeyQuestions and change the OnSelect event as documented below.

From:

If( CountRows(Filter(colQuestionAnswersResponse,Answer =1)) >0, Set(varKeyQuestionsPass,false) , Set(varKeyQuestionsPass,true));
If(varKeyQuestionsPass,Navigate(‘Screen Building’),Navigate(‘Screen Key Question Confirmation’))

To:

If( CountRows(Filter(colQuestionAnswersResponse,Answer =1)) >0, Set(varKeyQuestionsPass,false) , Set(varKeyQuestionsPass,true));
If(varKeyQuestionsPass,Navigate(‘Screen Availability’),Navigate(‘Screen Key Question Confirmation’))
  • Still on Screen Key Questions, select the HeaderControl and change the NavigateScreen to:
If(varAppSettings.KeyQuestions,’Screen Key Questions’, ‘Screen Building’)
  • Click again in Screen Key Questions, on the OnVisible event, perform the changes below:

Replace:

If(IsEmpty(colKeyQuestions),ClearCollect(colKeyQuestions, Filter(BAR_KeyQuestions ,State.Value =”Published”)));

By:

If(varAppSettings.KeyQuestionsPerBuilding, ClearCollect(colKeyQuestions, Filter(BAR_KeyQuestions , State.Value =”Published” && Text(varSelectedBuilding.ID) = ‘Building:ID’.Value)), ClearCollect(colKeyQuestions, Filter(BAR_KeyQuestions ,State.Value =”Published”)));
  • Expand Screen Availability, change to the OnVisible event and paste the code below after the existent code:
Set(varBuildingControlsVisible,false);
// Get all floors/spaces for current buildind
ClearCollect(colFloors,Filter(BAR_Spaces,BuildingID = varSelectedBuilding.ID ));
Clear(colChosenRequests);
Set(varAvilabilityDatePickerDefault, Blank());
Set(varAvilabilityDatePickerDefault,Today());
Reset(DatePicker);