I'm trying to make a trigger to fetch data based on cell value automatically.
the custom formula that I create and use in a sheet (or cell) successfully fetches the data, for example :
=ListPlugins("https://example1.wpengine.com")
the function looks like this :
function ListPlugins(url) {
let sheet_name = 'apps and plugins'
var options = {
"async": true,
"crossDomain": true,
"method" : "GET",
"headers" : {
"Token" : TOKEN_HERE,
"cache-control": "no-cache"
}
};
var urlEncoded = encodeURI(url)
let api_url = urlEncoded + "/wp-json/bd/v1/public/plugin-list/"
var jsondata = UrlFetchApp.fetch(api_url,options)
var object = JSON.parse(jsondata.getContentText())
return object;
}
but when I try to automate it by using the trigger, an error happens
Exception: You do not have permission to call ScriptApp.newTrigger. Required permissions: https://www.googleapis.com/auth/script.scriptapp
and this is how my approach to automating:
function onOpen(e) {
return teste()
}
function teste()
{
var all_data = getDataFromPluginList()
/*return all_data
[ { first_cell: 'A2',
last_cell: 'I9',
first_row: 2,
last_row: 9,
total_row: 8,
url: 'https://example1.wpengine.com/' },
{ first_cell: 'A10',
last_cell: 'I15',
first_row: 10,
last_row: 15,
total_row: 6,
url: 'https://example2.wpengine.com/' } ]
*/
for (var i = 0; i < all_data.length; i++) {
trigger_(all_data[i].url);
}
}
function trigger_(url)
{
var new_trigger = ScriptApp.newTrigger(writePluginData).timeBased().everyMinutes(1).create();
var trigger_id = new_trigger.getUniqueId();
PropertiesService.getUserProperties().setProperty(trigger_id, url);
}
function writePluginData(event)
{
var trig = ScriptApp.getProjectTriggers();
let sheet_name = 'trigger_result';
let lowest_row = lowestRow(sheet_name);
for(var i =0; i<trig.length; i++)
{
if(trig[i].getUniqueId()== event.triggerUid )
{
var urlParam = PropertiesService.getUserProperties().getProperty(event.triggerUid);
urlParam = urlParam.split(",");
var url = urlParam[0];
var ss = SpreadsheetApp.getActive().getSheetByName(sheet_name); // change accordingly
var data = ListPlugins(URL);
/*return listPlugins
[
[
"Escape Room",
"https://example.com/",
"Advanced Custom Fields PRO",
"advanced-custom-fields-pro",
"5.12.3",
"6.0.7",
false,
6,
"2023-01-30 10:57 AM"
],
[
"",
"",
"Classic Editor",
"classic-editor",
"1.6.2",
"1.6.2",
true,
""
],
...,
]
*/
var target = "A"+ (lowest_row + 1)
Logger.log(data);
ss.getRange(target).setValue(data);
}
}
}
why does this error happen? is there any relation to my API security?
Related
I have an array of objects (pre_finalTab_new below) like this:
My goal is to group them by "schema", and then by "tip" and insert into new array, something like this:
var celotnaTabela = {};
for (var nov in pre_finalTab_new)
{
var shema = pre_finalTab_new[nov].schema.trim();
var objekt_tip = pre_finalTab_new[nov].type.trim();
var objekt_name = pre_finalTab_new[nov].name.trim();
var tip = pre_finalTab_new[nov].tip.trim();
if (celotnaTabela[shema] === undefined)
{
celotnaTabela[shema] = [];
if (celotnaTabela[shema][tip] === undefined)
{
celotnaTabela[shema][tip] = [];
if (celotnaTabela[shema][tip][objekt_tip] === undefined)
{
celotnaTabela[shema][tip][objekt_tip] = [];
celotnaTabela[shema][tip][objekt_tip] = [objekt_name];
} else
celotnaTabela[shema][tip][objekt_tip].push(objekt_name);
}
} else
{
if (celotnaTabela[shema][tip] === undefined)
{
celotnaTabela[shema][tip] = [];
}
if (celotnaTabela[shema][tip][objekt_tip] === undefined)
{
celotnaTabela[shema][tip][objekt_tip] = [];
celotnaTabela[shema][tip][objekt_tip] = [objekt_name];
} else
{
if (!celotnaTabela[shema][tip][objekt_tip].includes(objekt_name))
celotnaTabela[shema][tip][objekt_tip].push(objekt_name);
}
}
}
Then if i output celotnaTabela, i got this:
Expanded:
Even more:
But the problem is, when i try to use JSON.stringify(celotnaTabela), i got this:
{"HR":[],"ZOKI":[]}
But i need it to be in a right format, so i can pass this object into AJAX call..
Can anyone help me with this, what am i doing wrong?
i hope i understood everything right you asked for.
Next time provide the testdata and the wished result in textform pls.
var obj = [
{ schema: "HR", type: " PACKAGE", name: "PAKET1", tip: "new_objects" },
{ schema: "HR", type: " PACKAGE", name: "PAKET2", tip: "new_objects" },
{ schema: "HR", type: " PROCEDURE", name: "ADD_JOB_HISTORY", tip: "new_objects" },
{ schema: "ZOKI", type: " TABLE", name: "TABELA2", tip: "new_objects" },
{ schema: "ZOKI", type: " TABLE", name: "TABELA3", tip: "new_objects" },
];
var out = {};
for (var i = 0, v; v = obj[i]; i++) {
var a = v.schema.trim();
var b = v.type.trim();
var c = v.tip.trim();
var d = v.name.trim();
if (!out.hasOwnProperty(a)) {
out[a] = {};
}
if (!out[a].hasOwnProperty(b)) {
out[a][b] = {};
}
if (!out[a][b].hasOwnProperty(c)) {
out[a][b][c] = []
}
out[a][b][c].push(d);
}
console.log(JSON.stringify(out, null, 2));
I'm trying to build an xml file from 2 JSON objects through 2 cascading loops. In the second loop, I can't find how to pass a value from the previous loop:
In the example below, I would like to pass the "docnumber" value to my second loop (through GroupsACLJSON) in order to build the "acl" node from the second JSON object, but using "this.docnumber" from the parent object property returns "undefined", thus leading to an empty "acl" node.
var documentsJSON = [{
"folder": "Enterprise1",
"extension": "DOCX",
"docnumber": "3912271",
"version": "1"
},
{
"folder": "Enterprise2",
"extension": "MSG",
"docnumber": "3912298",
"version": "1"
},
{
"folder": "Enterprise3",
"extension": "DOCX",
"docnumber": "3912692",
"version": "1"
}
]
var GroupsACLJSON = [{
"docNumber": "3912271",
"groupName": "group1"
},
{
"docNumber": "3912271",
"groupName": "group2"
},
{
"docNumber": "3912298",
"groupName": "group3"
},
{
"docNumber": "3912298",
"groupName": "group4"
}
]
// importing and declaring xmlbuilder variable:
var builder = require('xmlbuilder');
var xmlObjectImporter = builder.create('import', {
version: '1.0',
encoding: 'UTF-8',
standalone: true
}, {
headless: false,
stringify: {}
});
var nodeArray = [];
var xmlObjectElement = {
node: function() {
for (var i = 0; i < documentsJSON.length; i++) {
// populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
var nodeObject = {
location: documentsJSON[i].folder,
category: {
attribute: [{
'#text': documentsJSON[i].docnumber,
'#name': "Document Number"
}],
'#name': "ACME",
},
docnumber: documentsJSON[i].docnumber,
// loop through GroupsACLJSON to find if we have specific ACL groups for this document:
acl: function() {
var documentNumber = this.docnumber
console.log(this.docnumber);
var acl = [];
var aclObject = {};
for (var j = 0; j < GroupsACLJSON.length; j++) {
if (GroupsACLJSON[j].docNumber == documentNumber) {
aclObject = {
'#group': GroupsACLJSON[j].groupName,
'#permissions': '111111100'
};
acl.push(aclObject);
};
};
return acl;
},
'#type': "document",
'#action': "create",
};
nodeArray.push(nodeObject);
};
return nodeArray;
}
};
// writing our elements in the xml file using the XML object:
var ele = xmlObjectImporter.ele(xmlObjectElement);
console.log(xmlObjectImporter.toString({
pretty: true
}));
Here is an output I would expect from this:
<import>
<node type="document" action="create">
<location>Enterprise1</location>
<category name="ACME">
<attribute name="Document Number">3912271</attribute>
</category>
<docnumber>3912271</docnumber>
<acl group="group1" permissions="111111100" />
<acl group="group2" permissions="111111100" />
</node>
<node type="document" action="create">
<location>Enterprise2</location>
<category name="ACME">
<attribute name="Document Number">3912298</attribute>
</category>
<docnumber>3912298</docnumber>
<acl group="group3" permissions="111111100" />
<acl group="group4" permissions="111111100" />
</node>
<node type="document" action="create">
<location>Enterprise3</location>
<category name="ACME">
<attribute name="Document Number">3912692</attribute>
</category>
<docnumber>3912692</docnumber>
<acl/>
</node>
</import>
Following nxSolari's suggestion, I re-wrote the code using 2 functions instead of a big object and methods and got the desired result. I still don't understand how the code gets through the objects and methods, but here is the new working code:
'use strict';
var documentsJSON = [{
"folder":"Enterprise1" ,
"extension":"DOCX" ,
"docnumber":"3912271" ,
"version":"1"
},
{
"folder":"Enterprise2" ,
"extension":"MSG" ,
"docnumber":"3912298" ,
"version":"1"
},
{
"folder":"Enterprise3" ,
"extension":"DOCX" ,
"docnumber":"3912692" ,
"version":"1"
}
]
var GroupsACLJSON = [{
"docNumber":"3912271" ,
"groupName":"group1"
},
{
"docNumber":"3912271" ,
"groupName":"group2"
},
{
"docNumber":"3912298" ,
"groupName":"group3"
},
{
"docNumber":"3912298" ,
"groupName":"group4"
},
{
"docNumber":"3912692" ,
"groupName":"group5"
}
]
// importing and declaring xmlbuilder variable:
var builder = require('xmlbuilder');
var xmlObjectImporter = builder.create('import', {
version: '1.0',
encoding: 'UTF-8',
standalone: true
}, {
headless: false,
stringify: {}
});
var xmlObjectElement = {};
function buildACLnode(passedDoc, acls) {
var acl= [];
for (var jDoc = 0 ; jDoc < acls.length ; jDoc++) {
if (acls[jDoc].docNumber == passedDoc) {
var aclObject = {
'#group': acls[jDoc].groupName,
'#permissions': '111111100'
};
acl.push(aclObject);
};
};
return acl;
}
function buildXML(documents) {
var nodeArray = [];
for (var iDoc = 0; iDoc < documents.length; iDoc++) {
var nodeObject = {
node: {
location: documentsJSON[iDoc].folder,
category: {
attribute: [
{ '#text': documentsJSON[iDoc].docnumber, '#name': "Document Number" }
],
'#name': "ACME",
},
acl: buildACLnode(documentsJSON[iDoc].docnumber, GroupsACLJSON),
'#type': "document",
'#action': "create",
}
};
nodeArray.push(nodeObject);
};
return nodeArray;
}
xmlObjectElement = buildXML(documentsJSON);
// writing our elements in the xml file using the XML object:
var ele = xmlObjectImporter.ele(xmlObjectElement);
console.log(xmlObjectImporter.toString({
pretty: true
}));
You have several undeclared variables that will cause your code to break when running in strict mode.
i and j in your for loops both need declared. e.g. let i = 0.
The aclObject is not declared. You need to add a var declaration, e.g. const aclObject = { ... }.
After fixing those, I had no trouble running your code, at least, I had no trouble building the xmlObjectElement and executing the node() and acl() functions, which worked.
UPDATED
This will not fix the way that xml-builder is traversing your object and building the xml, but your functions could be improved by using Array methods instead of for loops. You'd have no need to use i or j and decrease the chances of introducing a bug for that reason.
For instance, you could easily replace both loops with a use of .map(). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map.
var xmlObjectElement = {
node: function () {
return documentsJSON.map((document) => {
// populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
return {
location: document.folder,
category: {
attribute: [
{ '#text': document.docnumber, '#name': "Document Number" }
],
'#name': "ACME",
},
....
})
This is my code and it doesn't works. It belong to a combobox. Some items should be disabled in it.
var data = [];
for (i = 0; i < items.length; i++) {
data.push({id: items[i].id, label: "foobaa"});
data.getOptions(items[i].id).disabled = true;
}
var memory = new Memory({
idProperty: "id",
data: data
});
this._widget.set("store", memory);
I found a code snipe at fiddle.net and this works but im not able to converte it to my problem.
http://jsfiddle.net/g00glen00b/akcZy/
Also the otherwise super documentation of dojo doesn't helps me :-(
http://dojotoolkit.org/documentation/tutorials/1.10/selects_using_stores/
I have made some changes try this and let me know is this your need? Use the code below to disable all the select items.
var data = [];
for (i = 0; i < myData.length; i++) {
data.push('{id: myData[i].id, label: "foobaa"}');
registry.byId("mySelect").getOptions(myData[i].id).disabled = true;
}
http://jsfiddle.net/f3snxrrd/
http://jsfiddle.net/5pgkkf0z/
items: {
mutators: {
value: [],
type: verify.ARRAY
},
widget: {
updateI18n: true,
mapping: function (widget, items) {
if (this._widget) {
var i;
var data = [];
for (i = 0; i < items.length; i++) {
data.push({id: items[i].id, label: i18n.resolveSequence(items[i].label)});
//register.byId(data).getOptions((items[i].value).disabled = true);
}
var memory = new Memory({
idProperty: "id",
data: data
});
this._widget.set("store", memory);
this._widget.closeDropDown(true);
this._widget.reset();
if (items.length === 0) {
this._enabledItems = false;
}
else if (items.length === 1) {
this.set("selectedId", items[0].id);
this._enabledItems = (this.get("selectedId") !== items[0].id);
}
else {
this._enabledItems = true;
}
this._widget.set("disabled", !(this._enabledState && this._enabledItems ));
}
}
}
},
_createWidget: function () {
var ret;
ret = new Select({id: this.uniqueId, disabled: true, labelAttr: "label", labelType: "Text", required: false, store: new Memory({data: []})});
var that = this;
ret.own(on(ret, "change", function (value) {that._onChange(value); }));
return ret;
},
This is the items array:
The code from jsfiddle.net
http://jsfiddle.net/8m52n81u/11/
I can't change the items array :-/
items = [{
id: "0",
label: key[{0: "foo", 1: "baa"}]
}, {
id: "1",
label: key[{0: "foo", 1: "baa"}]
}];
require([
"dojo/ready",
"dijit/registry",
"dijit/form/Select",
"dojo/store/Memory",
"dojo/parser"
], function(ready, registry) {
ready(function() {
var data = [];
for (i = 0; i < items.length; i++) {
data.push('{id: items[i].id, label: items[i].label}');
registry.byId("uniqueId").getOptions(items[i].id).disabled = true;
}
});
});
In my loop i have a group id like this
****variable i value****
groupid 0 199
groupid 1 200
groupid 2 201
but in for loop its always take group 201 in first iteration why this happend. here is my code.
for (var i = 0; i < groupdata.length; i++) {
console.log('groupid', i, groupdata[i].id);
var groupname = groupdata[i].name;
var groupid = groupdata[i].id;
var groupType = groupdata[i].groupType;
var getuserdata = {
"groupID": groupdata[i].id,
"groupType": groupdata[i].groupType,
"token": req.usersession.token
};
var digest = BASE.utils.hmac("sha1", "A12AA418-1F28-4464-8B67-29CBD02BC45C-F048B14F-F3E3-4F97-A522-F2275A364A0E", JSON.stringify(getuserdata));
var postData = {
"groupID": groupdata[i].id,
"groupType": groupdata[i].groupType,
"digest": digest,
"token": req.usersession.token
};
var groupUserData = BASE.utils.base64encode(BASE.utils.base64encode(JSON.stringify(postData)));
BASE.request({
url: "http://example.com/getGroupUsers/",
method: "POST",
headers: {
"content-type": "application/json",
},
body: groupUserData
},
function(err, result, groupUserdata) {
var groupuserdata = JSON.parse(groupUserdata);
console.log('first groupusers.....', i, groupuserdata);
var groupids = groupuserdata.groupUsers.filter(function(group) {
if (group.userID != contactid) {
userbody.groups.map(function(usr) {
if (usr.id == groupid) {
console.log('maingroupid....', usr.id);
console.log('current loop groupid..', groupid);
group.groupData = usr;
}
return usr;
})
return group;
}
});
//console.log(groupids);
newgroupdta.push(groupids);
//res.send(groupids);
// console.log(groupids);
//console.log('.............',newgroupdta);
});
}
/* end for loop */
});
groupdata have below values
groupdata.... [ { groupType: '1',
id: '199',
unreadMessages: '0',
ownerId: '339',
name: 'xyz' }, { groupType: '1',
id: '200',
unreadMessages: '0',
ownerId: '339',
name: 'second group' }, { groupType: '1',
id: '201',
unreadMessages: '0',
ownerId: '339',
name: 'new one' } ]
groupusers data is like below
{ groupUsers: [ { userID: '0' }, { userID: '31' }, { userID: '326' } ] }
Basically i want to check contactid which is 326 exist in groupusers
if no then return that particular groupdata in array like
{groupdata:[{groupname:,groupid:}]}
/*********************edit***********************/
var count = 0;
var i =0;
function outer(data){
if(count==groupdata.length)break;
var groupname = groupdata[i].name;
var groupid = groupdata[i].id;
var groupType =groupdata[i].groupType;
var getuserdata = {
"groupID" :groupdata[i].id,
"groupType" : groupdata[i].groupType,
"token":req.usersession.token
};
var digest = BASE.utils.hmac("sha1", "A12AA418-1F28-4464-8B67-29CBD02BC45C-F048B14F-F3E3-4F97-A522-F2275A364A0E", JSON.stringify(getuserdata));
var postData = {
"groupID" :groupdata[i].id,
"groupType" : groupdata[i].groupType,
"digest" : digest,
"token" : req.usersession.token
};
var groupUserData = BASE.utils.base64encode(BASE.utils.base64encode(JSON.stringify(postData)));
BASE.request({
url : "http://201.206.158.254:8080/BACKSTAFF/service/getGroupUsers/",
method :"POST",
headers : {
"content-type": "application/json",
},
body :groupUserData
},
function (err,result,groupUserdata) {
console.log(groupUserdata);
});
i++;
outer(groupdata[count++]);
}
/***************end edit *************************/
You have written asynchronous callback function inside for loop .
As per your code above BASE.request({},function(){}) method will be called asynchronously , it will not wait for result and for loop will move to next .
There are multiple ways to handle this :
1) Async.js
2) Recursion ( Remove for and call next method from inside callback and at last break and come out of loop)
var count = 0;
function outer(data){
BASE.request({},function(){
if(count==groupdata.length)return;
//whatever logic
outer(groupdata[count++]);
})
}
3) Eventemitter can also be used
I am implementing a Jira gadget. I have an problem about retrieve data.
I am retrieving data from DB to gadget. There are lots of columns so the gadget cannot show all columns. I guess I have to resize data. There is one more thing; how can I stop the retrieving data to go end of pages?
Here is my gadget.xml
#requireResource("com.atlassian.gadgets.publisher:ajs-gadgets")
#requireResource("sqlGadget:Web-resources")
#requireResource("com.atlassian.jira.gadgets:common")
#requireResource("com.atlassian.jira.gadgets:autocomplete")
#includeResources()
<script type="text/javascript">
(function () {
var gadget = AJS.Gadget({
baseUrl: "__ATLASSIAN_BASE_URL__",
useOauth: "/rest/gadget/1.0/currentUser",
config: {
descriptor: function(args) {
var gadget = this;
gadgets.window.setTitle("SQL Gadget Config");
var projectPicker = AJS.gadget.fields.projectPicker(gadget, "projectId", args.projectOptions);
return {
fields: [
projectPicker,
{
id: "configNumber-id",
userpref: "configNumber",
label: "Config number",
description: "",
type: "select",
selected: gadget.getPref("configNumber"),
options: [
{
label:"1",
value:"1"
},
{
label:"2",
value:"2"
},
{
label:"3",
value:"3"
}
]
},
AJS.gadget.fields.nowConfigured()
]
};
},
args: function()
{
return [
{
key: "projectOptions",
ajaxOptions: "/rest/gadget/1.0/filtersAndProjects?showFilters=false"
}
];
}()
},
view: {
/* HTML PART*/
onResizeAdjustHeight: true,
enableReload: true,
template: function (args)
{
var gadget = this;
var response = args.projects.value;
AJS.$.each(AJS.$.parseJSON(response), function(idx, obj) {
console.log(obj);
});
var myList=AJS.$.parseJSON(response);
var test="<body onLoad=buildHtmlTable()><table id=excelDataTable border=1> </table></body>";
document.getElementById("myDiv").innerHTML = test;
var columns = addAllColumnHeaders(myList);
for (var i = 0 ; i < myList.length ; i++) {
var row$ = AJS.$('<tr/>');
for (var colIndex = 0 ; colIndex < columns.length ; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) { cellValue = ""; }
row$.append(AJS.$('<td/>').html(cellValue));
}
AJS.$("#excelDataTable").append(row$);
}
function addAllColumnHeaders(myList)
{
var columnSet = [];
var headerTr$ = AJS.$('<tr/>');
for (var i = 0 ; i < myList.length ; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if (AJS.$.inArray(key, columnSet) == -1){
columnSet.push(key);
headerTr$.append(AJS.$('<th/>').html(key));
}
}
}
AJS.$("#excelDataTable").append(headerTr$);
return columnSet;
}
},
args: [
{
key: "projects",
ajaxOptions: function ()
{
var projectName;
var confOrder;
var projectField = document.getElementById("projectId");
var confNumbElement = document.getElementById("configNumber-id");
if(projectField != null){
projectName = projectField.options[projectField.selectedIndex].text;
console.log(projectName);
}
if(confNumbElement != null){
confOrder = confNumbElement.options[confNumbElement.selectedIndex].text;
console.log(confOrder);
this.configNumber = confOrder;
}
return {
url: "/rest/sqlrestsource/latest/execute",
data: {
projectId : gadgets.util.unescapeString(this.getPref("projectId")),
configNumber : gadgets.util.unescapeString(this.getPref("configNumber")),
}
};
}
}
]
}
});
})();