azure devops vsts extensions dynamic context-menu with child menu not loading properly - tfs

I'm trying to develop an extension which allow me to open a work item context menu and see new menu item/control "view test result" and when I hover on the "view test result" a sub menu will open containing configuration available. just like the way 'Move to iteration' menu in context menu.
the contributions section of my vss-extension.json is
"contributions": [
{
"id": "change-status.contextmenu",
"type": "ms.vss-web.action-provider",
"description": "Change state selected items",
"targets": [
"ms.vss-work-web.work-item-context-menu",
"ms.vss-work-web.backlog-item-menu"
],
"properties": {
"group": "contributed",
"uri": "configMenu.html"
}
}
]
Html page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="lib/VSS.SDK.min.js"></script>
</head>
<body>
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformScripts: true,
configureModuleLoader: true
});
// Load main entry point for extension
VSS.require(["src/app"], function () {
// Loading succeeded
VSS.notifyLoadSucceeded();
});
</script>
</body>
app.ts file
import {MenuHandler} from "./logic/menuHandler";
VSS.register(VSS.getContribution().id, new MenuHandler().menuHandler);
and finally the menuHandler function
menuHandler= (context: any) : IContributedMenuSource => {
return <IContributedMenuSource> {
getMenuItems: (actionContext: any) => {
return this.buildConfigurationMenu(actionContext).then(
subMenus => {return this.buildMainMenuWithPromise(subMenus);}
);}
};}
The buildConfigurationMenu function call the azure devops TestManagement api and get Suites by TestCaseId and then foreach Suites we fetch points and from points we get configuration name and return an array of names to build menu item and buildConfigurationMenu return a promise then buildMainMenuWithPromise called that return main menu with child menu returned by buildConfigurationMenu function.
buildConfigurationMenu and buildMainMenuWithPromise working fine and return desired result as i can see in console while debugging.
The issue is when i click the context-menu (... button) first time i can't see new added menu "view test result" but when i click on context-menu 2nd time i see the "view test result" menu and on hover it shows related configuration item in sub menu. I want it to show on first click.
I assume its something related to delay in api call and promise return. How i can solve this issue or any work around to avoid this issue ?
Thanks

I have solved the issue by replacing foreach loop with for loop. I wans calling promise from within foreach loop which causing issue. Thanks

Related

navigator.sendBeacon not called from unload

According to MDN and the specs, navigator.sendBeacon is intended to be called from window unload.
Now, it does not seem to work anymore if you close the last tab of your browser, or your entire browser window.
Can anyone confirm if this is by design? If so, is there a workaround to send lastminute data on unload?
I tested with this sample file, in Firefox 74 and Chrome 81, looking for calls with Fiddler.
<html>
<head>
<title>unload test page</title>
<script>
window.addEventListener("unload", function () {
navigator.sendBeacon('https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon');
});
</script>
</head>
<body>
<p><div>unload test page</div></p>
</body>
</html>
MDN states (as of 1/12/2021):
It’s intended to be used in combination with the visibilitychange
event (but not with the unload and beforeunload events)
When visibilitychange transitions to hidden, you can treat that as when the tab/browser is closing and use sendBeacon then.
Example code from MDN:
document.addEventListener('visibilitychange', function logData() {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/log', analyticsData);
}
});

Webview not rendering when Electron's sandbox is set to true

I am working off the Electron quickstart using Electron 2.0.9 and am just trying to find a way to get a webview tag to run in Sandbox mode.
However I can't seem to remedy this issue. I have searched for possible solutions but the only thing I came across was here and this issue as shown was closed and there was something merged over a year ago. So clearly that'd be in 2.0.9 and I wouldn't be having this issue.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sandbox Test</title>
<style>
webview {
width: 100%;
height: 500px;
border: solid 1px black;
}
</style>
</head>
<body>
<input id="urlInput" type="url" value="https://www.google.com/" placeholder="Enter Url">
<button onclick="setUrl();">Load Page</button>
<br>
<div id="webviewDiv">
</div>
<script>
// You can also require other files to run in this process
// require('./renderer.js');
function setUrl()
{
url = document.getElementById("urlInput").value;
document.getElementById("webviewDiv").innerHTML = '<webview src="' + url + '"></webview>';
}
</script>
</body>
</html>
main.js
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
webPreferences: {
sandbox: true
},
width: 800,
height: 600
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
package.json
{
"name": "electron-quick-start",
"version": "1.0.0",
"description": "A minimal Electron application",
"main": "main.js",
"scripts": {
"start": "electron . --enable-mixed-sandbox"
},
"repository": "https://github.com/electron/electron-quick-start",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "GitHub",
"license": "CC0-1.0",
"devDependencies": {
"electron": "2.0.9"
}
}
So if anyone has any idea on possible reasons as to this being like this or can point to something I somehow missed on my attempts to fix this please do tell.
OS - Windows Server 2008 R2 (uses the same Kernel as Windows 7) (everything else in electron seems to work like normal so I doubt it's the OS.
It seems that the ability to use tag in sandbox didn't work until the 3.0.0 beta 3 release. Even though as in my previous post there seems to have been a merged change from over a year before the 3.0.0 beta 3 was released. Maybe this is somehow related to semantic versioning in someway so they had to wait until the next major release to add support for it.
https://electronjs.org/releases#3.0.0-beta.3

Listen to Firefox WebExtension sidebar closing

I am working on a WebExtension using the sidebar.
When the sidebar is open, the extension performs some operations on the current tab. When it is closed, I want to revert these operations.
Is this possible? I didn't see methods like browser.sidebarAction.addEventListener.
I adapted GnxR's idea in the following:
extension/page/sidebar.html:
<!DOCTYPE html>
<html>
<body>
<div id="panel"></div>
<script src="static.js"></script>
</body>
</html>
extension/page/static.js:
window.addEventListener('beforeunload', (event) => {
console.log('Sidebar will be closed!');
// Do stuff
});
window.addEventListener('pagehide', (event) => {
console.log('Sidebar is hidden!');
// Do stuff
});
window.addEventListener('unload', (event) => {
console.log('Sidebar is unloaded!');
// Do stuff
});
When closing the extension (both from the cross bar and programmatically), I get the following in the browser console:
Sidebar is hiding! static.js:6:3
Sidebar is unloaded! static.js:10:3
Therefore it seems that both pagehide and unload events can be used,
but that beforeunload is never fired.
The sidebar is an alsmot-regular independent webpage, in which you can listen to usual JS events. In order to know when the sidebar is closing, you can use beforeunload in the sidebar's JavaScript:
window.addEventListener('beforeunload', (event) => {
console.log('Sidebar is closing!');
// Do stuff
});

access custom dom function from firefox add-on

I am working on a Firefox Add, using the newest SDK. The problem I am having, is that when ever I try to run a custom dom function it doesn't work.
Scenario:
The firefox add-on must be able to loop through all tabs, and if the correct one is open based on the title, run a specific function, like: mydom.checkIt();
<!DOCTYPE html>
<html>
<head>
<title>My Web</title>
</head>
<body>
<script>
mydom = {};
mydom.checkIt = function (){
alert('Hi');
};
</script>
</body>
</html>
Then the add-on source code would be something like:
var tabs = require('sdk/tabs');
for (let tab of tabs)
{
if(tab.title=='My Web')
{
tab.activate();
}
}
tabs.on('activate', function(tab) {
tab.attach({
contentScript: "if(typeof(mydom)!=='undefined')mydom.checkIt();else console.log('no defined');"
});
});
But this doesn't work and it says always: "no defined"
Any ideas?
You have to get into the dom js scope with unsafeWindow or wrappedJSObject. So contentWindow.wrappedJSOBject.checkIt() works from bootstrap addon (not sure about sdk)
Warning though, this may not be e10s friendly and we should find a way to support that

jQuery UI tabs: How do I load a specific element from a different page?

I have jQuery UI tabs set up, but a problem that I'm having with links to different pages is that they load all contents of the page into the tab. This includes the footer, header, and other navbars that I don't want in the tab. What if I would only like to load a single ID from that page?
My tabs are set up this way:
<div id="mytabs">
<ul>
<li>Awesome page</li>
<li>Foo</li>
</ul>
</div>
Nothing much going on in the jQuery...
$(function() {
$( "#mytabs" ).tabs();
});
Let's say this is the html of "awesomepage" (that the first link targets):
<html>
<head>
<title>awesome page</title>
</head>
<body>
<div id="header">bla</div>
<div id="awesomeness">awesomeness!</div>
<div id="footer">fdsfd</div>
</body>
</html>
...And I only want the tab to load #awesomeness from the page. How would I go about doing this? I've read into some guides that do that by adding a data-target="#youridhere" attribute to the HTML, but I'm still confused on how to implement the javascript. It seems like this is a convenient solution, as I won't be targeting the same ID in every page. Any clues on how to get the javascript working?
Thanks in advance!
The function that allow to load partial code of the response is the $.load() function.
Unfortunately, the tabs() feature does not use this function but use $.ajax instead.
You can try this solution:
You can try to stop the default processing on the beforeLoad callback and manage your ajax call with the $.load() method.
(base on the 1.9 documentation, you may should adapt)
$('#tabs').tabs({
// Callback run when selecting a tab
beforeLoad: function(event, ui) {
// If the panel is already populated do nothing
if (ui.panel.children().size() > 0)
return false;
// Make your own ajax load (with fragment feature)
ui.panel.load(ui.tab.attr('href') + ' #yourFragment');
// stop the default process (default ajax call should not be launched)
return false;
});
NOTICE: I'm not sure about extracting the URL with ui.tab.attr('href'), check before what object is ui.tab, but it should be easy to retrieve the href parameter.
Good luck
Got the solution :) Using one of the answers as a reference point, the tabs can now load a single element specified in the data-target attribute. Here is the modified version:
$(function() {
$('#tabs').tabs(
{
beforeLoad: function(event, ui) {
if (ui.panel.children().size() > 0)
return false;
ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'));
return false;
}
});
});

Resources