Custom Tab in the Field Service Schedule Board - javascript

I found this blog: http://www.powerobjects.com/2016/08/01/advanced-customizations-for-the-custom-tab-in-the-field-service-schedule-board/#collapse2
In it the author describes using configuration to create a new tab in the Field Services Schedule Board by pointing it to a CRM web resource.
The blog includes the following javascript:
function updateBooking()
{
var entityRecordGuid = "10B8A40B-D499-E611-80E6-A45D36FC5A4C";
// GUID is hardcoded to make the sample code easier to understand.
// We can extend this customization to be able to extract the selected booking IDs
// from the SChedule Board's DOM, but that is out of scope for now
var bookableResourceBooking = new XrmServiceToolkit.Soap.BusinessEntity("bookableresourcebooking", entityRecordGuid);
bookableResourceBooking.attributes["cus_urgency"] = document.getElementById('UrgencyInput').value;
bookableResourceBooking.attributes["cus_notes"] = document.getElementById('NoteInput').value;
var updateResponse = XrmServiceToolkit.Soap.Update(bookableResourceBooking);
if (updateResponse == "") { // clear fields if synced to crm
document.getElementById('UrgencyInput').value = "";
document.getElementById('NoteInput').value = "";
} else {
alert('Data didn't sync to CRM');
}
}
The problem that I've got is that I'm not sure how to get the entityRecordGuid value dynamically.
There doesn't seem to be a way of configuring the web resource to
have the selected Item as part of the querystring
There seem to be undocumented JavaScript libraries for Field
Services; however, I can't access them from the web resource IFrame
and of course, they're undocumented.
Has anyone else tried to do this? I'm using CRM Online

I ended up doing this by scraping the HTML directly rather than trying to use any of the API methods from Field One.
This wasn't really a satisfactory answer for me. It depends on the Unscheduled Orders board being in a certain order and since this is changeable by the end-user my solution is very fragile.
For anyone else looking, I did manage to find these API methods; however, I couldn't find any documentation for them so assume that they are unsupported. I also couldn't tie them together to achieve what I wanted
// get the id of the sub grid
F1SDK.SchedulerPage.UnscheduledOrdersGrid.id
// -> "UnscheduledGrid"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getItemId()
// -> "UnscheduledGrid"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getStore().storeId
// -> "UnscheduledWorkOrders"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getStore().data.items[0].internalId
F1SDK.SchedulerPage.UnscheduledOrdersGrid.selModel.selected.items[0].internalId
// Get a subgrid
FieldOneSkyUtils.Subgrid.GetSubgrid('id')
F1SDK.data.models.WorkOrder.getFields()
F1SDK.data.models.WorkOrder.getIdByWONumber('00106')
// -> {55caa97d-429a-e611-80e6-c4346bc4bef0}

Related

Is there any way using script to delete some stuff in a google doc after google forms fills spreadsheet data?

I have a google doc that I'm using as a template, and it will be filled with the results of google forms data (which populates in a spreadsheet). The user will be checking off items on various lists on the form, and those items will get transferred over to the google doc template. On the doc template I want the script to be able to delete the header/initial bullet point space/blank space associated with any sections that don't end up having any items checked off, just to clean things up.
Is this possible? If so, how would I go about doing it or what kinds of terms should I be googling to figure it out?
Thank you for any help you can provide!
Apps Script, If this helps..
https://developers.google.com/apps-script/guides/docs
https://developers.google.com/apps-script/guides/sheets
As you might have figured it out, that Google Apps Script has vast variety of methods and options to work with, it is almost similar to javascript.
The issue related to this scenario might not be the first one, so, App Script already provided lots of options to cover up many things.
There are built-in functions which can be executed when your sheet loads, and you can schedule the script to run at some specific time of day and/or night by using Triggers in the Script Editor interface under Edit Menu.
It depends on your logic, when the script should be executed.
Sample deleting script is as follow:
function removeBlankRows(docId) {
var document = docId ?
DocumentApp.openById(docId) :
DocumentApp.getActiveDocument();
var body = document.getBody();
var search = null;
var tables = [];
// Extract all the tables inside the Google Document
while (search = body.findElement(DocumentApp.ElementType.TABLE, search)) {
tables.push(search.getElement().asTable());
}
tables.forEach(function (table) {
var rows = table.getNumRows();
// Iterate through each row of the table
for (var r = rows - 1; r >= 0; r--) {
// If the table row contains no text, delete it
if (table.getRow(r).getText().replace(/s/g, "") === "") {
table.removeRow(r);
}
}
});
document.saveAndClose();
}
removeChild method can also be used.

Display dynamic form options in google sheets

I have a Google sheet named 'Data' where a user can enter their own product names and sale numbers associated with it (meant to be a template so the product names may change user to user). I have read in the data and the product names (PRODUCT_NAMES) into some global data objects so I have access to it. I have created a menu item called "Plot Data" which goes to function (for now) testFunction()
I would like to display a form to the user that displays a checkbox grid item of all their product names (and maybe more future options), based on which ones they check I create a graph or calculate some values.
My question is two part:
1) How to create a form with dynamic grid choices, say one user has
PRODUCT_NAMES = {"Shirt", "Pants", "Shoes"}
and another has
PRODUCT_NAMES = {"Cars", "Trucks", "Suvs", "Trailers", "Boats"}
2) How to display the form in a google sheet? I have right now:
function testFunction() {
// Create a new form since the options change
var form = FormApp.create('Test Form');
var item = form.addCheckboxItem();
item.setTitle("This is a Test");
// TODO: Add dynamic options here
var formUrl = form.getPublishedUrl();
var response = UrlFetchApp.fetch(formUrl);
var formHtml = response.GetContextText();
var htmlApp = HtmlService
.createHtmlOutput(formHtml)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('Sales Data')
.setWidth(500)
.setHeight(450);
SpreadsheetApp.getUi().showSidebar(htmlApp);
}
But this does not seem to work, I may be misunderstanding something
Question 2b) How to access the user responses.
I am learning javascript and GAS on the fly, so this is all new to me. I would like to try and keep the user options part as a Google Form, just cause its easier from an API perspective what is going on.
From my comment, expanded a bit, for future users:
It would be better to show a UI Modal Dialog with a basic HTML form. This keeps the code within the script itself.
The issue with what you want to do is once the form is made and the spreadsheet is linked the data will still go to a new sheet per form, not to where you want it to go, and then you'd have to setup a onEdit() trigger to get the values from the new sheet, generate charts, then delete the sheet and, somehow, the form. It is possible, but probably more work than a simple Modal Dialog.
Consider the HTML option as there are numerous simple-to-follow tutorials and examples and resources on the web. If you do end up trying it out, I'd suggest Bootstrap to start!
Good luck either way!

How do i save model data when creating a Backbone driven theme in Wordpress?

Ok so im messing around with Backbone for the first time. I think I've pretty much covered all the basics of frontend logic, but i have never really been any good at backend logic and coding.
I'm working with wordpress and creating a theme using backbone. My understanding is as long as i set up a template page that has the correct containers that my backbone code will render views in, the fact that it's a wordpress theme instead of it's own app shouldn't really change anything on the frontend side.
I'm at the stage where i want to save a model so that i can fetch it in my routes to link to my view to render.
I'm unsure about the whole process of saving data. I know i need to give the model attribute 'urlRoot' a string but i don't know what that string should be, and what happens after that.
Can someone explain the whole process, especially in terms of how to do it with Wordpress. (i did stumble upon the WP REST API plugin that i think helps, although i don't exactly know how.)
EDIT
OK so in the end i presume my problem was something to do with authentication when trying to access the database as the textResponse was just returning the entire HTML for the current page i was on, probably due to the fact it wasn't getting through to the database and being redirected back to the page.
After googling around for a while i came across this. Rather than reinventing the wheel I installed this plugin and followed the setup instructions and low and behold it worked pretty much out of the box. If your trying to build a Backbone theme i suggest using the WP-API Client JS plugin with the WP REST API plugin. Seems to cover everything.
How to expose a WordPress blog's content through an API?
WP REST API seems like a good way to start. There are a lot of options and it exposes everything you need.
Note that it is named WordPress REST API (Version 2) in the wordpress.org plugin directory.
You can test that the plugin works by navigating to:
http://www.example.com/wp-json/wp/v2/
It should output all the information on the blog as a big JSON dump.
You can also test that it works for other endpoints, like post:
http://www.example.com/wp-json/wp/v2/posts
There's a Backbone plugin for the WP REST API that works out of the box.
How to communicate with the API?
This is a simple example using Backbone without any plugin. If you want to know how to use the plugin, see the documentation for it.
Since it offers a lot of arguments that can be passed in the URL, I made a small collection and an example of how it could be used.
var API_ROOT = '/wp-json/wp/v2/',
DEFAULT_API_ARGS = ['context' /* etc. */ ];
var WordPressCollection = Backbone.Collection.extend({
constructor: function(models, options) {
options = options || {};
this.apiArgs = _.union(DEFAULT_API_ARGS, this.apiArgs, options.apiArgs);
this.args = _.extend({}, this.args, this.getApiArgs(options));
WordPressCollection.__super__.constructor.apply(this, arguments);
},
getApiArgs: function(obj) {
return _.pick(obj, this.apiArgs);
},
fetch: function(options) {
options = options || {};
options.data = _.extend({}, this.args, this.getApiArgs(options), options.data);
return WordPressCollection.__super__.fetch.call(this, options);
},
});
And to use it:
var CommentCollection = WordPressCollection.extend({
url: API_ROOT + 'comments',
// all the arguments to look for in the passed options
apiArgs: ['page', 'per_page', 'post' /* etc. */ ],
});
var myPostComments = new CommentCollection(null, {
post: 23 // id
});
console.log(myPostComments.url());
myPostComments.fetch({ page: 2 });
The fetch should make a GET request to:
/wp-json/wp/v2/comments?post=23&page=2
And from that point, the WP REST API plugin takes control. It returns a new JSON encoded array of comment objects in the body of the response.
It should looks something like this:
Backbone automatically parses the JSON received, so you don't need to worry about that and you just have to go on and use it:
myPostComments.each(function(comment) {
console.log(comment.get('author_name'));
});
Then, saving a new comment is a matter of calling:
// check the doc for the comment object details
myPostComments.create({
post: 23,
content: "my new comment",
/* etc. */
});
And this would make a POST request to /wp-json/wp/v2/comments.

How do I pass a value from an HTML form submission to a Google Sheet and back to HTML in a Google Apps Script Web App

I'm trying to create a basic time clock web app.
So far, I'm using this script to create this web app which takes the input values and puts them in this spreadsheet for the time stamping part.
I need it to use one of the values from the form and perform a lookup in this sheet (take the longId and find me the name) and return the (name) value to the html page as a verification for the end user that they were identified correctly. Unfortunately, I don't know enough to grasp what I'm doing wrong. Let me know if I need to provide more info.
Edit 1
I'm thinking that I wasn't clear enough. I don't need the user info from entry, I need the user from a lookup. The user will be entering their ID anonymously, I need to match the ID to their info, and bring the info back for them to verify.
Edit 2
Using the link provided by Br. Sayan, I've created this script using this spreadsheet as above to test one piece of this. The web app here spits out: undefined. It should spit out "Student 3" Still not sure what I'm doing wrong.
One way for the next button to grab the student input field:
<input type="submit" onclick="studentName(document.getElementById('student').value)" value="Next..."/>
That sends the value to this func in Javascript.html:
function studentName(value) {
google.script.run
.withSuccessHandler(findSuccess)
.findStudent(value);
}
Which sends it to a findStudent(value) in Code.gs
You do the lookup and the return value goes back to findSuccess( result ) back in Javascript.html. Handle the result from there.
Also consider keeping the stock preventDefault() code that comes with the Web App template in the Help > Welcome Screen.
Please try this one:
(source: technokarak.com)
Also please have a look at:
Retrieve rows from spreadsheet data using GAS
EDIT:
Please make these changes in your function and let us know.
function findValue() {
var data = SpreadsheetApp.openById("15DRZRQ2Hcd7MNnAsu_lnZ6n4kiHeXW_OMPP3squbTLE").getSheetByName("Volatile Data").getDataRange().getValues();
for(i in data) {
if(data[i][3] == 100000003) {
Logger.log("yes");
Logger.log(data[i][0]);
var student = [];
student.push(data[i][0]);
return student;
}
}
}
It is a complicated answer, I have had a lot of success with:
function process(object){
var user = Session.getActiveUser().getEmail();
var key = object.Key;
send(key);
}
function send(k){
var ss =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastR = ss.GetLastRow();
ss.GetRange(lastR,1).SetValue(k);
}
On your html button you will need to have inside the tags
onClick="google.script.run
.withSuccessHandler(Success)
.process(this.parentNode);"
In order for this to work, obviously you will need to have your fields named accordingly.
Edit: The only thing I did not include in the code was a Success handler, which will be in your html of the GAS script. This should point you in a direction that can resolve that.
Hope this helps.

Update glimpse tab plugin data using ajax

I'm trying to create a custom glimpse plugin that shows us some information from our server.
When I open the page I get all the data I need but I want to be able to update this data once every 20 seconds(or when i click on a button in the tab) without having to refresh the entire page.
I've managed to add my JavaScript to the page and subscribe to the render and shown events, but i don't know how to update the tab content when something happens.
This is my tab
public class EagleTab : AspNetTab
{
private readonly IGlimpseInterventionService _glimpseInterventionService;
public EagleTab()
:this(new GlimpseInterventionService()){}
public EagleTab(IGlimpseInterventionService glimpseInterventionService)
{
_glimpseInterventionService = glimpseInterventionService;
}
public override object GetData(ITabContext context)
{
var interventionSection = new TabSection("Last modification", "Last Message","Time since last modification","CSE","DPS", "Start Date","End date");
var now = DateTime.Now;
var twoHoursThresshold = new TimeSpan(1,0,0);
foreach(var inv in _glimpseInterventionService.GetActiveInterventions()){
var timeSinceLastMod = now - inv.LastModification;
interventionSection.AddRow()
.Column(inv.LastModification)
.Column(inv.LastMessage)
.Column(timeSinceLastMod.ToString("c"))
.Column(inv.CSEName)
.Column(inv.DPSName)
.Column(inv.StartDate)
.Column(inv.EndDate).WarnIf(timeSinceLastMod<twoHoursThresshold);
}
var plugin = Plugin.Create("Section", "Data");
plugin.AddRow().Column("Active interventions").Column(interventionSection);
return plugin;
}
public override string Name
{
get { return "Eagle Tab"; }
}
}
And this is the JavaScript
(function ($, pubsub, tab, render) {
'use strict';
function refreshTabContent(){
//what am I supposed to do here
}
pubsub.subscribe('action.panel.rendering.eagle_glimpse_plugins_eagletab', function (args) {
});
pubsub.subscribe('action.panel.showed.eagle_glimpse_plugins_eagletab', function (args) {
setTimeout(refreshTabContent,30000);
});
})(jQueryGlimpse, glimpse.pubsub, glimpse.tab, glimpse.render);
As you can see in the js there is a function called refreshTab i want there to update the content of the tab.
I know that i could make an Ajax call to a controller of mine get the data and then try updating the panel using jQuery but that just seams a bit wrong and i'm hoping there's a better way.
Any tutorial or documentation about glimpse client side extensibility would be welcomed as well.
You have gotten a fairly large amount of the way towards your goal. Unfortunately though there isn't really a way of getting data from a tab outside of a request. That said, there is a "Glimpse" way of getting data from the server. This is small semantic difference, but it has to do with server data, vs request data.
If I was you, I would probably write this as a client side only tab and not implement AspNetTab. Here are some examples of how this can be done. Next I would implement a Resource. Unfortunately its not very well documented but fortunately its not very hard to work with.
This repo has some examples of how to work with client tabs back to resources. Specifically the Inventory tab is a tab that lets people mouse over products in the site and have the tab show stock levels. Here is the resource and here is the client code that interacts with the resource (given what you have so far, this should be fairly easy to adapt. Lastly, as a bonus, if you haven't seen it already, here is how to include your script into your page. Note, the commits on that repo are the step by step guid to how things come together.
Let me know if that helps.

Categories

Resources