How to use Neutralinojs os.runCommand in multiple platforms - javascript

I was trying to get network information on Windows using Nuetralinojs. How can I make my app cross platform? I want to run ifconfig command when users execute this on Linux.
I have posted my HTML and JS codes below.
let work = () => {
Neutralino.os.runCommand('ipconfig',
(data) => {
document.getElementById('neutralinoapp').innerHTML = data.stdout.replace(/\n/g, '</br>');
},
() => {
console.error('error');
}
);
}
Neutralino.init({
load: () => {
work();
},
pingSuccessCallback : () => {
},
pingFailCallback : () => {
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>NeutralinoJs</title>
<link rel="stylesheet" href="/assets/app.css">
</head>
<body>
<div id="neutralinoapp">
</div>
<script src="/neutralino.js"></script>
<script src="/assets/app.js"></script>
</body>
</html>

You can check os simply using NL_OS global variable of Neutralinojs.
If you are running cloud mode on a server window.navigator is not a solution.
Here is the modified JS function.
let work = () => {
let command = NL_OS == 'Windows' ? 'ipconfig' : 'ifconfig';
Neutralino.os.runCommand(command,
(data) => {
document.getElementById('neutralinoapp').innerHTML = data.stdout.replace(/\n/g, '</br>');
},
() => {
console.error('error');
}
);
}

Related

How to getElementById to parse ros status correctly

I want to parse the ROS status inside my webpage, but I can't get my element by Id correctly.
Can you please tell me how can I parse my ROS status inside my HTML page correctly? thanks in advance.
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Something</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="favicon.ico"><script defer src="main.js"></script></head>
<body>
<div id="container"></div>
<div id="ros_status"></div>
</body>
</html>
main.js
import { Ros, Message, Topic, } from "roslib";
class ROSInterface {
constructor(container_id) {
this.container = document.getElementById(container_id, true);
console.log(this.container);
this.ros = new Ros({
url : 'ws://localhost:9090'
});
}
init() {
if (this.container in document) {
console.log(this.container);
this.ros.on('connection', function () {
this.container.innerHTML = "Connected";
});
this.ros.on('error', function (error) {
this.container.innerHTML = "Error";
});
this.ros.on('close', function () {
this.container.innerHTML = "Closed";
});
}
else {
console.log(document);
this.ros.on('connection', function () {
console.log("Connected");
});
this.ros.on('error', function (error) {
console.log("Error");
});
this.ros.on('close', function () {
console.log("Closed");
});
}
}
}
const ros_iface_ = new ROSInterface('ros_status');
ros_iface_.init();

javascript promise operation to update HTML

I think I understand promises, but I can't seem to get my head around it correctly. I have an application built in SharePoint 2013 that does a REST call via sprLib to populate an object. The object can be manipulated on the page, either entries added/deleted/updated, basically full CRUD. Then the changes are pushed back to the list. So far, this is all working smoothly. What I am trying to do now is on the update, empty the div tag, then call the initial load function again to populate the div with the new current list. Right now, either I get an error on the promise syntax or race condition where the initial load function runs again before the update finishes, so the populated list is the old list. I created a basic version to simulate the idea, minus the REST updates since I couldn't find a way to replicate that in a sandbox.
https://jsfiddle.net/36muca0g/
Long story short, 3 things should happen: 1) initial load 2) changes made 3) re-load data and empty/append html accordingly.
const fullList = [ //In real environment, this is populate via REST operation.
{ id: "12", title: "A", code: "110" },
{ id: "23", title: "B", code: "120" },
{ id: "13", title: "C", code: "130" },
{ id: "43", title: "D", code: "140" },
{ id: "52", title: "E", code: "150" },
]
$(document).ready(function () {
initialLoad(fullList);
$('#updateList').click(function() {
let item = $('#txtValue').val();
addToList(item).then(function(result){
console.log('add complete');
initialLoad(fullList);
console.log('reloaded');
})
.catch(function(){
console.log('fail');
})
});
})
function initialLoad(list) {
//In real environment, this is a getItem operation using sprLib.
$('#itemList').empty();
let listHTML = ''
for (i = 0; i < list.length; i++) {
listHTML += '<p>'+list[i].title+' ' +list[i].code+'</p>'
}
$('#itemList').append(listHTML);
}
function addToList(entry) {
return new Promise(function(resolve, reject) {
console.log('I go first');
fullList.push({ 'id': "", 'title': entry, 'code': ""}); //In real environment, this is an CRUD operation using sprLib.
setTimeout(() => resolve("done"), 5000);
});
}
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise</title>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript"></script>
<script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script src="/scripts/promise.js"></script>
<link href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/select/1.4.0/css/select.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body><br><br>
<div class="container text-center row">
<div class="card col-2 bg-primary text-light" id="itemList">
</div>
<div class="card col-2 bg-secondary"><input type="text" class="form" id="txtValue">
<button type="button" class="btn btn-success" id="updateList">Submit</button></div>
</div>
</body>
</html>
The way i see it, you need a proper "trigger" to replace that ugly setTimeout() in a way that you allow to refresh the view only when the new data is accessible.
If you're working your application around a MCV pattern, what you could do is attach the state of your data onto an element inside the DOM, and listen for this element's state changes and use that to trigger the reload your fresh data.
I handled the case recently by building a drag-&-drop functionality where i wanted to display the content of the file only and only when the reader terminated the load task.
controller.js
const loadState = async function (type, input) {
return new Promise((resolve, reject) => {
try {
const reader = new FileReader();
if (type === "drop") {
const data = state.fileItem[0];
for (let i = 0; i < data.length; i++) {
if (data[i].kind === "file") {
const file = data[i].getAsFile();
reader.onload = async function (e) {
resolve((state.partNumber = createArr(e.target.result)));
};
reader.readAsText(file);
}
}
}
} catch (err) {
console.log(err);
}
});
};
eventHandlers.dropZone.addEventListener("drop", handleDropImport, false);
async function handleDropImport(e) {
try {
e.preventDefault();
if (!e.dataTransfer.items) return;
state.fileItem.push(e.dataTransfer.items);
await loadState("drop");
eventHandlers.queryPreview.classList.add("uploaded");
} catch (err) {
console.log(err);
}
}
As soon as the handleDropImport() is managed and only after the data is loaded inside the state (thanks to async/await), we add this class to the element of your choice...
eventHandlers.queryPreview.classList.add("uploaded");
You can then scan the DOM for that classList.add in your view.js using a mutation observer, and make it reachable using a publisher/subscriber pattern.
view.js
_addHandlerRender(handler) {
const options = { attributes: true, childList: true, subtree: true };
const observer = new MutationObserver((mutations) =>
mutations.forEach((mut) => {
if (mut.type === "attributes" && mut.attributeName === "class") {
handler();
}
})
);
observer.observe(this._parentElement, options);
}
model.js
const controlPreview = async function () {
try {
previewViews._clearPreview();
previewViews.render(model.state.partNumber);
} catch (err) {
console.log(err);
}
};
const init = function () {
previewViews._addHandlerRender(controlPreview);
};
init();

How to execute script file before another script in layout page?

Inside my layout page i wanna run a script for translate the text of some enumumerators.
My layout looks like this:
<html>
<head>
...
<script src="~/js/ViewModels/Helpers/Translation.js"></script>
<script src="~/js/ViewModels/Helpers/Enumerators.js"></script>
...
</head>
<body>
...
</body>
</html>
My translation script:
'use strict';
var jsonTranstation = null;
$(function () {
getjson();
});
const getjson = () => {
$.getJSON('/lib/translation/en-EN.json', function (data) {
jsonTranstation = data;
});
}
const Translation = (value, ViewModel) => {
let a = null;
if (jsonTranstation ) {
a = jsonTranstation[ViewModel][value];
return a;
}
return '--';
}
My Enumerators script:
'use strict'
const EnumToolBar = {
NEW: { text: Translation('New', 'EnumToolBar'), prefixIcon: 'e-add', id: 'NEW' }
}
My JSON file (en-EN.json):
{
"EnumToolBar": {
"New": "New Value"
}
}
Using EnumToolBar.NEW.text in HomePage returns '--' instead of 'New Value'.
There are any way to read first script and the respective json file before any other script?

Azure Devops(vsts) expension - How to create task attachment content

I am working on creating an extension for azure devops, which creates a custom tab and displays the result.
I uploaded the file using "##vso[task.addattachment]".
Eg: console.log('##vso[task.addattachment type=TestReport;name=MyReport;]c:/user/index.html');
I am having problem in consuming that file and displaying it on new tab, I went through the sample code provided by MS - build_release_enhancer
but still unable to display the file.
js file::
import Controls = require("VSS/Controls");
import VSS_Service = require("VSS/Service");
import TFS_Build_Contracts = require("TFS/Build/Contracts");
import TFS_Build_Extension_Contracts = require("TFS/Build/ExtensionContracts");
import DT_Client = require("TFS/DistributedTask/TaskRestClient");
import { error } from "azure-pipelines-task-lib";
export class InfoTab extends Controls.BaseControl {
constructor() {
super();
}
public initialize(): void {
super.initialize();
// Get configuration that's shared between extension and the extension host
var sharedConfig: TFS_Build_Extension_Contracts.IBuildResultsViewExtensionConfig = VSS.getConfiguration();
var vsoContext = VSS.getWebContext();
if(sharedConfig) {
// register your extension with host through callback
sharedConfig.onBuildChanged((build: TFS_Build_Contracts.Build) => {
this._initBuildInfo(build);
var taskClient = DT_Client.getClient();
taskClient.getPlanAttachments(vsoContext.project.id, "build", build.orchestrationPlan.planId,"ATTACHMENT_TYPE_HERE").then((taskAttachments) => {
$.each(taskAttachments, (index, taskAttachment) => {
if (taskAttachment._links && taskAttachment._links.self && taskAttachment._links.self.href) {
var recId = taskAttachment.recordId;
var timelineId = taskAttachment.timelineId;
taskClient.getAttachmentContent(vsoContext.project.id, "build", build.orchestrationPlan.planId,timelineId,recId,"ATTACHMENT_TYPE_HERE",taskAttachment.name).then((attachementContent)=> {
function arrayBufferToString(buffer){
var arr = new Uint8Array(buffer);
var str = String.fromCharCode.apply(String, arr);
return str;
}
var data = arrayBufferToString(attachementContent);
});
}
});
});
});
}
}
private _initBuildInfo(build: TFS_Build_Contracts.Build) {
}
}
InfoTab.enhance(InfoTab, $(".build-info"), {});
// Notify the parent frame that the host has been loaded
VSS.notifyLoadSucceeded();
Html file:
<!DOCTYPE html>
<head>
<script src="../lib/VSS.SDK.min.js"></script>
<script type="text/javascript">
VSS.init( {
usePlatformScripts: true,
// moduleLoaderConfig: {
// paths: { "sample": "sample" }
// }
});
VSS.ready(function() {
require(["sample/tab2"], function () { });
});
</script>
<style>
.build-info {
padding: 10px;
}
</style>
</head>
<body>
<div class="build-info"> </div>
</body>
</html>
The issue is resolved, actually the issue was with my vss-extension.json file. I had to declare scope:
"scopes": [
"vso.build_execute"
]

Vuex getters + dev tools

I started working on a large project that uses extensive number of vuex getters. The problem is, that large amount of them rely to be called in specific order or at specific time to have correct data from other getters. Looks like vue dev tools is trying to access those values, calling the getters not in expected order so some values are not correct and the app is throwing errors. Because of this I cannot use the dev tools and cannot find a simple way around it.
Here is simple snippet reproducing the issue.
This code will run just fine, but once you open dev tools, it tries to access the getter selselectedPrice which returns error until we have some data.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vuex#3.1.1/dist/vuex.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in goodThings" :key="item.title">{{ item.title }}</li>
</ul>
{{totalPrice}}
</div>
<script>
const getSomeRandomData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{
title: 'fasfasf',
price: 20
},
{
title: 'asgfasgasg',
price: 30
},
{
title: 'asgasgasg',
price: 40
}
])
}, 1000)
})
}
const store = new Vuex.Store({
state: {
selectedItem: undefined,
warehouse: []
},
actions: {
fetchData: async function ({ commit }) {
const response = await getSomeRandomData()
commit("SET_WAREHOUSE", response)
}
},
mutations: {
SET_WAREHOUSE: (state, payload) => {
state.warehouse = [...payload]
}
},
getters: {
selselectedPrice: (state) => {
return state.warehouse[state.selectedItem].price
},
goodThings: (state) => {
return state.warehouse
},
totalPrice: (state) => {
return state.warehouse.reduce((a, item) => a+item.price, 0)
}
}
})
Vue.use(Vuex)
let app = new Vue({
el: '#app',
store,
created() {
this.$store.dispatch('fetchData')
},
computed: {
goodThings() {
return this.$store.getters.goodThings
},
totalPrice() {
return this.$store.getters.totalPrice
}
}
})
</script>
</body>
</html>

Categories

Resources