Microsoft Teams App - showLoadingIndicator : true resulting in breaking config tab - microsoft-teams

I am trying to use showLoadingIndicator : true in my manifest file and as soon as I load the MicrosoftTeams.js file in my _host.cshtml file I call the javascript to notify success. But this breaks the config Tab. When I search for the item and select the result and click on save it throws error saying tabsettings can not be saved. But if I click on save second time , it works.:
_host.cshtml
<script src="https://res.cdn.office.net/teams-js/2.5.0/js/MicrosoftTeams.min.js"
integrity="sha384-0lOzlvRkoNWAcLkbUTuao6TaDa7zI7v+q2PUAm3lrMxUp43PFwf2kaQu7FYT9fjS"
crossorigin="anonymous"></script>
<script src="~/js/utils.js"></script>
utils.js:
function AppLoaded() {
microsoftTeams.app.initialize().then(() => {
microsoftTeams.app.notifySuccess();
console.log("app loaded");
});
}
AppLoaded();
config.cshtml have:
private async void SetSelectedResult(SearchModel selectedItem)
{
_selectedItem = selectedItem;
if (_selectedItem != null)
{
var settings = new TeamsInstanceSettings
{
SuggestedDisplayName = _selectedItem.Description,
EntityId = _selectedItem.ID.ToString(),
ContentUrl = contenturl",
WebsiteUrl = websiteurl",
RemoveUrl = removeUrl"
};
await MicrosoftTeams.InitializeAsync();
await MicrosoftTeams.RegisterOnSaveHandlerAsync(settings);
}
} ```

You only need to call microsoftTeams.app.notifySuccess(); in the -actual- tab, not in the config panel. Add a switch in your code somehow (based on page name, or a setting, or however you decide to do it) to only call that from in the main tab.
Update: You are also missing the call to notifyAppLoaded, which is even more important that notifySuccess. See in this document, that you actually need to call notifyAppLoaded to 'hide loading indicator'.

Related

How to create a share button in laravel?

How can I create a share button, and also get count for each post shared?
In your Blade file that outputs the article, you can output a button. this contains a hidden textarea as a child element. With JS you can put a click event listener on it.
So you can copy the URL to the post. I hope I have understood it correctly?
document.addEventListener("click", function(e)
{
const textArea = document.createElement("textarea");
textArea.value = e.target.querySelector('.url-container').innerHTML;
document.body.appendChild(textArea);
textArea.select();
let successful = null;
let msg = '';
try {
successful = document.execCommand('copy');
msg = successful ? 'successful' : 'unsuccessful';
} catch (err) {
console.warning('unable to copy');
console.warning(err);
}
document.body.removeChild(textArea);
if (successful) {
alert('copied');
// make an XHR call to your App Api for counting
}
});
<button id="share" data-test="test"><textarea class="url-container" style="display:none;">www.your-domain.com/your-post-x</textarea>Share Post X</button>

How to get webHookUrl from Microsoft Teams connector

I’m building a connector for Teams and I can get my custom configuration page to load by calling the necessary functions. I have a few <span> tags in my page just to debug and I'm populating the tags with properties from my call to "getSettings()".
<script>
microsoftTeams.initialize();
var teamsSettings = microsoftTeams.settings.getSettings(); //should this not return at least something?
if (teamsSettings == null) {
$(document).ready(function () {
document.getElementById('status').textContent = "Get settings
returned null!"; //i always get null
});
} else {
document.getElementById('entityId').textContent = teamsSettings.entityId;
document.getElementById('configName').textContent = teamsSettings.configName;
document.getElementById('contentUrl').textContent = teamsSettings.contentUrl;
document.getElementById('webhookUrl').textContent = teamsSettings.webhookUrl;
document.getElementById('appType').textContent = teamsSettings.appType;
document.getElementById('userObjectId').textContent = teamsSettings.userObjectId;
}
microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
saveEvent.notifySuccess();
});
function onClick() {
microsoftTeams.settings.setValidityState(true);
}
</script>
So I’m wondering if the getSettings() method is even running as my label element is blank. How can I troubleshoot the JavaScript interactions while configuring my connector in Teams? Is there a better way to view settings obtained from the method?
Here is the code snippet to get the webhookUrl using getSettings().
microsoftTeams.initialize();
microsoftTeams.settings.getSettings(function (settings) {
document.getElementById('webhookUrl').textContent = settings.webhookUrl;
});

Firefox Compile Simple Load Script - browser.xul

I'm trying to add a script tag to every dom page through privileged chrome, so far i'm able to get the first pageload of a tab, but after that, the script does nothing, I'm using Firefox Nightly 44.0. What am i doing wrong???
Documents I'm following:
https://developer.mozilla.org/en-US/Add-ons/Code_snippets/On_page_load
https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Intercepting_Page_Loads
mozilla-central/browser/base/content/browser.xul (line: 74)
<script type="application/x-javascript" src="chrome://browser/content/yyy/x.js" />
chrome://browser/content/yyy/x.js
var myExtension = {
init: function() {
// The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered the event
var win = doc.defaultView; // win is the window for the doc
// test desired conditions and do something
// if (doc.nodeName != "#document") return; // only documents
// if (win != win.top) return; //only top window.
// if (win.frameElement) return; // skip iframes/frames
alert("page is loaded \n" +doc.location.href);
}
}
window.addEventListener("load", function load(event){
window.removeEventListener("load", load, false); //remove listener, no longer needed
myExtension.init();
},false);
mozilla-central/browser/base/jar.mn
content/browser/yyy/x.js (content/yyy/x.js)
You'll want to use loadFrameScript with argument of true to listen to future pages. Here are examples: https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages
globalMM.loadFrameScript("chrome://modify-all-pages/content/frame-script.js", true);
This is documented here: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFrameScriptLoader#loadFrameScript%28%29
To stop it from loading in new tabs, then you have to use removeDelayedFrameScript
That github link also shows an example of how to do it with addon-sdk content-scripts.

Rich Text Editor (WYSIWYG) in CRM 2013

Sometimes it is useful to have the HTML editor in CRM interface. It is possible to implement the editor directly to CRM 2013. As editor we will use ckeditor which allows to use it without installation on the server.
Identify the field where you would like to use the rich text editor.
Create html-webresource which will define ckeditor. Go to Settings-Customizations-Customize the System-Web Resources.
In html editor of web resource, select the Source tab and insert the following code:
<html>
<head>
<title></title>
<script src="//cdn.ckeditor.com/4.4.7/standard/ckeditor.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
function getTextFieldName()
{
var vals = new Array();
if (location.search != "")
{
vals = location.search.substr(1).split("&");
for (var i in vals)
{
vals[i] = vals[i].replace(/\+/g, " ").split("=");
}
//look for the parameter named 'data'
for (var i in vals)
{
if (vals[i][0].toLowerCase() == "data")
{
var datavalue = vals[i][2];
var vals2 = new Array();
var textFieldName = "";
vals2 = decodeURIComponent(datavalue).split("&");
for (var i in vals2)
{
var queryParam = vals2[i].replace(/\+/g, " ").split("=");
if (queryParam[0] != null && queryParam[0].toLowerCase() == "datafieldname")
{
textFieldName = queryParam[1];
}
}
if (textFieldName == "")
{
alert('No "dataFieldName" parameter has been passed to Rich Text Box Editor.');
return null;
}
else
{
return textFieldName;
}
}
else
{
alert('No data parameter has been passed to Rich Text Box Editor.');
}
}
}
else
{
alert('No data parameter has been passed to Rich Text Box Editor.');
}
return null;
}
CKEDITOR.timestamp = null;
​// Maximize the editor window, i.e. it will be stretched to target field
CKEDITOR.on('instanceReady',
function( evt )
{
var editor = evt.editor;
editor.execCommand('maximize');
});
var Xrm;
$(document).ready(function ()
{
​ // Get the target field name from query string
var fieldName = getTextFieldName();
var Xrm = parent.Xrm;
var data = Xrm.Page.getAttribute(fieldName).getValue();
document.getElementById('editor1').value = data;
/*
// Uncomment only if you would like to update original field on lost focus instead of property change in editor
//Update textbox on lost focus
CKEDITOR.instances.editor1.on('blur', function ()
{
var value = CKEDITOR.instances.editor1.getData();
Xrm.Page.getAttribute(fieldName).setValue(value);
});
*/
// Update textbox on change in editor
CKEDITOR.instances.editor1.on('change', function ()
{
var value = CKEDITOR.instances.editor1.getData();
Xrm.Page.getAttribute(fieldName).setValue(value);
});
// Following settings define that the editor allows whole HTML content without removing tags like head, style etc.
CKEDITOR.config.allowedContent = true;
CKEDITOR.config.fullPage = true;
});
</script>
<meta>
</head>
<body style="word-wrap: break-word;">
<textarea class="ckeditor" cols="80" id="editor1" name="editor1" rows="10"></textarea>
</body>
</html>
Note:
As you can see, there are a few important sections
a) The following code loads the ckeditor and jquery from web so that they don't have to be installed on server.
<script src="//cdn.ckeditor.com/4.4.7/standard/ckeditor.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
b) Function getTextFieldName() which gets the name of target field where should be rich text editor placed. This information is obtained from query string. This will allow to use this web resource on multiple forms.
c) Initialization of ckeditor itself - setting the target field and properties of ckeditor. Also binding the editor with predefined textarea on the page.
Open the form designer on the form where you would like to use ​WYSIWYG editor. Create a text field with sufficient length (e.g. 100 000 chars) which will hold the html source code.
Insert the iframe on the form. As a webresource use the resource created in previous steps. Also define Custom Parameter(data) where you should define the name of the text field defined in step 4. In our situation we created new_bodyhtml text field so the parameter holds this value. This value is returned by the getTextFieldName() of the web resource.
Do not forget to save and publish all changes in CRM customization otherwise added webresources and updated form are not available.
That's all, here is example how it looks like:
Yes, you can use CKEditor, but when I implemented the CKEditor on a form, it turns out it is quite limited in the functionality in provides. Also, the HTML it generates leaves much to be desired. So, I tried a similar idea to Pavel's but using a backing field to store the actual HTML using TinyMCE. You can find the code here:
Javascript
HTML
Documentation
I have package my solution as a managed and unmanaged CRM solution that can be imported and utilised on any form. Moreover, it works on both CRM 2013 and CRM 2015

Ajax file upload is not working when used the second time

I'm using this jquery plugin ajaxFileupload in our project. My design is I have a file upload control and set the opacity to 0.01 and then using an anchor link, I trigger the file upload control click event. This works fine until I try to click the anchor link the second time which it doesn't open the file dialog box.
Here is my code.
$(".btnUpload").live("click", function () {
$(".lblUploadError").text("");
$(".fleAttachment").trigger("click");
});
$(".fleAttachment").change(function () {
var reg = /^.*\.(jpg|JPG|gif|GIF|jpeg|JPEG)$/;
var vals = $(this).val(),
val = vals.length ? vals.split("\\").pop() : "";
if (reg.test(vals) == false) {
$(".lblUploadError").text("Invalid Image Type. We only accept .GIF or .JPG");
} else {
ajaxFileUpload();
eval($(".btnRefreshAttachmentList").attr("href"));
}
});
I don't see any error in the console so it makes it difficult to debug it.
Change
$(".fleAttachment").change(function() {
to
$(".fleAttachment").live('change', function() {
$( document ).on( "click", ".fleAttachment", function() {
//--> Logic Here // jQuery 1.7+
});
this.value="";
at the end should work

Resources