Finding All Scripts of Type X

Is there a way to find all scripts of a certain type?

Use case:
I made and used a No Data script and I have put it in so many places, I now need to update it everywhere I put it but seams like the only way is to go into each project and open every Dashboard. I will most Likely skip one or two doing it this way. If there is a list I can change the name of the script (add V2 to it) to know that I touched it and then go to the next one in the list (if such list exist).
BTW I have hidden elements that have this too, so this is going to be REAL fun.
Does this need to change to a Feature Request?

1 Like

HI James

I do have a way to loop through all scripts within a dashboard, but haven’t yet written something to loop through all projects and dashboards, check them out etc.

Going forward, I suggest you put the script in the script override on your server and then all dashboards can call it. Then you only have 1 place to make the change.

@david.glickman
Good Suggestion. I not gone into scripts over ride yet. I will research it and test it out.

Thanks

James, I have a script that can work for you with some minor modifications to suit your specific needs. You’ll want to change it so it picks up multiple projects and looks for the No Data scripts (it currently picks up Loading and Ready).

Hope this helps,
Ken

/*
  • This looks at all files in the project for scripts and prints their contents.
    */
    console.log(‘Start Script Finder’);

var PROJECT_NAME = ‘’;
var TO_FIND_TYPE = ‘Dashboard’;

var projectService = dundas.context.getService(‘ProjectService’);
var fileSystemService = dundas.context.getService(‘FileSystemService’);
var dashboardService = dundas.context.getService(‘DashboardService’);

var fileIds = []; //we need these later during duplication to check in files as well as to locate the data connector file in the project.
var dashboardPromiseArr = [];
// Declare all the functions we use in processing and return them in a
// “then” chain within a function which we’ll execute below in a queue.
var processPlan = function (sourceProject) {

// We need to recursively get all the files in the project
var queryFiles = function (sourceProject) {
var queryOptions = {
entryId: sourceProject.id,
queryOptions: dundas.filesystem.FileSystemQueryOptions.RECURSIVE_QUERY,
};
//console.log('queryEntries ', PROJECT_NAME);
return fileSystemService.queryEntries(queryOptions);
}

// After we’ve got files for a project, we want to filter based on the type of file being a ScriptAction
var processFileEntries = function (entries) {
//console.log(‘processFileEntries’, PROJECT_NAME);
var promise = $.Deferred();
entries.forEach(function (entry) {
if (entry.objectType === TO_FIND_TYPE) {
fileIds.push(entry.id);
//console.log('Found - type: ’ + entry.objectType + ', name: ’ + entry.friendlyName + ', id: ’ + entry.id);
}else{
//console.log('Skipping - type: ’ + entry.objectType + ', name: ’ + entry.friendlyName + ‘, id: ’ + entry.id);
}
});
//console.log(’*processFileEntries ', PROJECT_NAME);
return promise.resolve();
}

var getDashboards = function () {
//console.log(‘getDashboards’);
var promise = $.Deferred();

fileIds.forEach(function(entryId){
    //console.log('Promising to get Dashboard :'+entryId);
    var dashboardPromise = dashboardService.getDashboardById(entryId);
    //dashboardPromise.done(function(dash){
    dashboardPromiseArr.push(dashboardPromise);
    //});      
});
//debugger;

return promise.resolve();

}

var processDashboards = function (){
var promise = $.Deferred();
//console.log('processDashboards '+dashboardPromiseArr.length);
dashboardPromiseArr.forEach(function(dashPromise){
dashPromise.done(function(dashboardObj){
console.log('Dashboard : '+dashboardObj.friendlyName);

	//beforeExportActions, resizeActions
	
    dashboardObj.loadingActions.forEach(function(script){
      if(script.script){
		console.log(dashboardObj.friendlyName+':Loading:Script:');
        console.log(''+script.script);
      }
		
	});
    dashboardObj.readyActions.forEach(function(script){
      if(script.script){
		console.log(dashboardObj.friendlyName+':Ready:Script:');
        console.log(''+script.script);
      }
		
	});
	dashboardObj.adapters.forEach(function(adapter){
		//
		//onSelectChange etc.
		if(adapter.clickActions){
			//console.log('Adapter '+adapter.friendlyName+' ClickActions:');
			adapter.clickActions.forEach(function(clickActionScript){
				if(clickActionScript.actionType === 'Script' && clickActionScript.script){
					console.log(dashboardObj.friendlyName+':'+adapter.friendlyName+':Click Action:Script('+clickActionScript.name+'):');
					console.log(clickActionScript.script);
				}
			});
		}
	});
	console.log('--------------------------------------------------');
   // debugger;
  });
});
return promise.resolve();

}

// Return a function to call later that has a chain of
// functions which must execute in sequence
return function () {
return queryFiles(sourceProject)
.then(processFileEntries)
.then(getDashboards)
.then(processDashboards)

  //.then(getScriptsPerDashboard)
  .done(function () {
    console.log('Finished processing ');
  });

}
};

/// Execution Block ///

//Go through all the projects.
projectService.getAllProjects()
.done(function (projects) {

// Declare this finder function which takes the friendly name given it, to be used in the plan loop below.
function getProjectByName(friendlyName) {
var result;
projects.some(function (project) {
if (project.friendlyName === friendlyName) {
result = project;
return true;
}
});
return result;
};

// Get the source project or bail out since we can’t do any processing without it.
var sourceProject = getProjectByName(PROJECT_NAME);
if (!sourceProject || !sourceProject.id) {
return $.Deferred().reject(‘Unable to find master project:’);
}

// Push processing jobs into a queue for each plan we’re going to duplicate from the source project.
// We’re going to safely perform this kind of process synchronously as a safety measure and since
// we don’t require speed as much as a reliable copying process.
var queue = [];

queue.push( processPlan( sourceProject) );

// After the function calls are queued, we actually execute them here
queue.reduce(
function (promise, fn) {
return promise.then(fn);
},
$.Deferred().resolve()
).then( function () {
console.log(‘End Project Script Finder’);
});

});//getallprojects.done

@ken.benjamin That is quite a script! :exploding_head:

Gotta say - I really agree with the suggestion made by @david.glickman. Use an overrides file to keep your common JS Scripts in a single place for re-use.

The script provided by @ken.benjamin is fine to read dashboard object parameters.
I need to loop through and change things on the dashboard. I know what to do, but I’m doing it to the dashboard object returned by the promise rather than the dashboard itself.

What’s the best way to make permanent changes to the dashboard in such a loop?

Hi David,

Usually, making permanent changes to the dashboard should be done one by one as when you are trying to save multiple copies simultaneously, finding out which dashboard is saved last is not possible. Users should check out the dashboard via File System Service and then using the dashboard service, a user should get dashboard. Then update the copy of the entity with whatever intended and call update on the dashboard service to save it.

Thanks.

I worked it out in the end. Basically it was the dashboardService.updateDashboard method that i was missing.

I have now successfully run my script to modify every dashboard in every project without any issues