I'm trying to automate a process at my company where I have to send files to my customers every month.
These files are unique and each customer must receive their own. In addition, I wanted the client to be required to answer an NPS assessment form in order to have access to his file.
Honestly, I don't understand much about programming and I'm just trying to find a solution to do this automatically.
The solution I have in mind today is to use a google forms form and after filling out the form a link would be made available to access a google drive folder (that way the customer would be obliged to answer the form to have access to his file).
In the google drive, each file would be associated with a unique access key (for example, an identification number of that customer, in which he already knows what it is).
Then these customers should insert this key in the google drive folder in order to be able to access their file. That way I would be able to: get all the answers of the evaluation in a single form, make a standard message (or tutorial) available to all customers informing them how to access their file, and give access to the files automatically because the access key would be the same every month.
Sorry for the long text but I tried to describe my problem in the best way. I am accepting any kind of help or guidance. Even where I could get help about it. This automation would be very important to me because in addition to automating a process that costs a lot of time it would give me a very powerful tool to evaluate my services. Thanks in advance to everyone who took the time to read this question.
The best approach in this situation is to start by using Apps Script.
Apps Script is a powerful development platform which can be used to build web apps and specifically for your situation, automate tasks. What makes it special is the fact that it is easy to use and to create applications that integrate with G Suite.
Since you mention that the files are unique for each customer, what you can do is to store these values in a key - value list. However, depending on the number of the customers, you can store these value in a spreadsheet, something similar to this:
Making the files available only after submitting the Google Form mentioned can be done by taking advantage of Apps Script's triggers.
So essentially, you can use an onFormSubmit trigger which will execute every time the above mentioned form is submitted.
Code
You can also add another column in your spreadsheet to mark if the email was sent or not; taking this into account, this is how your spreadsheet will look like:
As for the code, this is just a short snippet which does the following:
opens the spreadsheet and retrieves the values for the File ID, Customer Email and Sent columns as the following arrays ids, emails and sent respectively;
retrieves the needed form and loops through the responses and checks if the last email of the form matches any of the ones from the spreadsheet;
if the conditions check, the file permissions are edited, an email is being sent, and the corresponding row on column C is being set to TRUE;
function editPermissions() {
let form = FormApp.openById('FORM_ID');
let sheet = SpreadsheetApp.openById('SPREADSHEET_ID').getSheetByName('SHEET_NAME');
let responses = form.getResponses();
let emails = sheet.getRange('EMAILS_RANGE').getValues();
let ids = sheet.getRange('IDS_RANGE').getValues();
let sent = sheet.getRange('SENT_RANGE').getValues();
for (let i = responses.length; i > 0; i--) {
let email = responses[i].getRespondentEmail();
for (let j = 0; j < emails.length; j++) {
if (emails[j][0] == email && sent[j][0] == false) {
// edit file permissions
// send email
// mark the associated row on the Sent col with TRUE
}
}
}
}
Trigger
As for making the function above run every time there's a new form submission, you will have to create an onFormSubmit trigger which will trigger the execution of the function.
Reference
Apps Script;
Apps Script Spreadsheet Service;
Apps Script Forms Service;
Apps Script Installable Triggers.
Related
I can only read from the first 100,000 rows of any particular tab in a Google Sheet via the API.
Is this a known limitation of the Google Sheets API? I didn't see a reference to it in the documentation.
Issue and workaround:
I thought that if you want to retrieve the values from Spreadsheet, it seems that when the method of "spreadsheets.get" is used for the Spreadsheet including the large data, the data cannot be correctly retrieved because of an error like Response Code: 413. Message: response too large.. I thought that this might be the reason for your issue. And, in this situation, I confirmed that even when the method is changed from "spreadsheets.get" to "spreadsheets.values.get " and "spreadsheets.values.batchGet", the issue occurred. So I thought that this situation might be the current specification of Sheets API.
But, fortunately, I confirmed that when I tested to retrieve the values from your Spreadsheet using the query language, all values can be retrieved. And also, I confirmed that when I tested to retrieve the values from your Spreadsheet using the Spreadsheet service of Google Apps Script, all values can be retrieved.
So in this answer, I would like to propose these 2 patterns.
Pattern 1:
In this pattern, the values are retrieved by the query language. I thought that in your situation, this might be suitable. The endpoint is as follows.
https://docs.google.com/spreadsheets/d/###spreadsheetId###/gviz/tq?tqx=out:csv&gid=###sheetId###&access_token=###accessToken###
In this case, the access token can be also included in the request header instead of the query parameter. At that time, please use Authorization: Bearer ###. When the above endpoint is accessed using your access token, all values are returned as CSV data.
Pattern 2:
In this pattern, the values are retrieved by the Spreadsheet service of Google Apps Script. The sample script is as follows. When you use this script, please test this script at the script editor of Google Apps Script.
function myFunction() {
const id = "###spreadsheetId###";
const sheet = SpreadsheetApp.openById(id).getSheetByName("Tab 1");
const values = sheet.getDataRange().getValues();
console.log(values.length)
}
When I tested this script for your sample Spreadsheet, 405028 can be seen in the log.
References:
Query Language
Spreadsheet Service
I am developing a site for online test series. I receive details o student on one page and wish to display the info on net page as dashboard. I need a global variables that can hold the detail of student like his roll no, name, email, class, semester, subject and the test he wishes to solve.
I have tries using a separate .js file to hold variables. However, the values of variables get lost as i move to next page.
can anyone help?
The code and links are attached.
https://ishuuw.wixsite.com/ymatutor/test-series
//import wixData from 'wix-data';
import {globalVars} from 'public/vars.js';
$w.onReady(function () {
});
export function button2_click(onClick,button2){
globalVars.StudentRoll=$w('#input1').value
globalVars.StudentName=$w('#input5').value
globalVars.StudentSurname=$w('#input6').value
globalVars.StudentMail=$w('#input7').value
globalVars.StudentClass=$w('#dropdown1').value
globalVars.StudentYear=$w('#dropdown2').value
globalVars.StudentSemester=$w('#dropdown3').value
globalVars.StudentPaper=$w('#dropdown5').value
globalVars.StudentTest=$w('#dropdown6').value
//Just to test, this works well
$w('#text63').text=globalVars.StudentRoll
$w('#text64').text=globalVars.StudentName
$w('#text65').text=globalVars.StudentSurname
$w('#text66').text=globalVars.StudentMail
$w('#text67').text=globalVars.StudentClass
$w('#text68').text=globalVars.StudentYear
$w('#text69').text=globalVars.StudentSemester
$w('#text70').text=globalVars.StudentPaper
$w('#text71').text=globalVars.StudentTest
}
`
Sounds like you should be using wix-storage. That will allow you to pass information between pages.
Use local storage if you want the data to persist for the user even after the user ends the session. Meaning, next session, the user's data will still be available.
Use session storage if you want the data to be removed when the user's session ends.
I have a table driven by DataTables 1.10. Filtering is turned on. When I talk about "doing a search" below, I'm talking about using the filtering function of this table.
Description of the Problem
Everything works fine with stateSave off. However, when stateSave is on, the following happens:
Alice logs in as admin. Because admin has all privileges, when she does a search through articles, she can see all articles. Because some articles are published and some are unpublished the table has a column that show which are published and which are not. So far so good.
Bob, a random user, accesses the site. Random users cannot ever see unpublished articles so the table hides the column that shows publication status. So far so good.
Alice logs out. She now accesses the site like a random user. So she should see exactly what Bob sees. However, when she does a search she still sees the column that indicates publication status.
(Note: The issue I'm discussing here is purely one of user interface. The server ensures that unprivileged users cannot ever get a record for an unpublished article. The problem though is that the additional column gives unpriviledged users information that they do not need. They can only see published articles in their search so they don't need to see that every article they get in a search is published.)
The code that configures the datatable hides the publication column by doing something like this:
var columnDefs = [];
if (!privileged) {
columnDefs.push({
targets: [1],
orderable: false,
visible: false
});
}
columnDefs is passed to DataTables as the columnDefs option.
Technical Reason for the Problem
The problem is that DataTables store things like column visibility into the state it saves into localStorage. So when Alice logs out and makes a search again as an unprivileged user, even though the value of columnDefs is correct, it is overwritten by the saved state. That state was stored when Alice was an admin, and it declared the publication column to be visible, so it remains visible even when Alice is accessing the site as an unprivileged user.
What I want is for users to benefit from the saved state but avoid having this state carry over when the user's privileges change.
Caveats:
I don't want to use sessionStorage because I want the state to persist between browser closings, but sessionStorage is cleared when the browser is closed.
I cannot use the session cookie assigned by the server to detect logins and logouts because it is HTTP only. Besides, privileges could change for other reasons.
I do not want to arbitrarily set an expiration time on the saved state.
The solution I've settled on is to use an additional field in the saved data to know when the conditions I care about have changed. This is a field whose value changes depending on the privileges that the user currently has. For instance, because in the case I described here, I decide to hide or show a column on the basis of a variable named priviledged (which is initialized from data provided by the server), it could be as simple as:
var token = privileged;
Then I set stateSaveParams to record the token when the state is saved:
stateSaveParams: function (settings, data) {
data.myapp_token = token;
}
The prefix myapp_ is just there to avoid possible collisions with DataTable's own fields.
I set stateLoadParams so that if the current value of token differs from what has been recorded before, the state is cleared:
stateLoadParams: function (settings, data) {
if (data.myapp_token !== token) {
this.api().state.clear(); // Clears the state.
return false; // Tells DataTables to not use the state that was stored.
}
// This return is here to keep the IDE happy but does not do anything special.
return undefined;
},
I've just set token to the single condition I've shown in my question (privileged) in this example but in production I use a combination of variables plus a local version number so I can bump the value of token as needed if I do something that requires clearing the state but cannot be detected just as a privilege change.
I need to develop an application that extracts all the contents in Content Tab of the Ektron Workarea and I have to keep tree structure of folders (taxonomies,collections,forms,etc.) also.When I click the content I need to get the Content ID in the code behind also.I need to do all these in a single function.
I tried this requirement with the concept of content block widget in workarea.When we drag that widget and edit it a pop up will come and it displays the folders of work area in tree structure.But when I created an aspx page, put the same code and I browse that page I didn't get the tree structure of all contents.Only the main tabs(Folders,Taxonomies and search ) are visible.Then I drag the user control in the aspx page .But it also doest work.
So how will I solve the above problem.
Can I pull all the contents in tree structure from work area from the root using API codes?.Then can anyone please give the API code to solve?
Please anyone reply!
Assuming you are using 8.6 look here to start with:
http://reference.ektron.com/developer/framework/content/contentmanager/getlist.aspx
Update:
I think I misread your question the first time around. Allow me to expand on my answer a bit. My original answer with the web services assumes that you are rendering the content tree from some sort of "presentation tier" -- a different web site, a console app, or a WPF/WinForms app, etc.
You can get the recursive folder structure with something like this:
private FolderData GetFolderWithChildren(long folderId)
{
var folderApi = new Ektron.Cms.API.Folder();
var folderData = folderApi.GetFolder(folderId);
// This next method is marked as obsolete in v9.0;
// a newer overload is available in v9.0, but I
// don't know if it's available in v8.0
folderData.ChildFolders = folderApi.GetChildFolders(folderId, true);
}
I'm a little confused as to what exactly you're trying to accomplish. If you want to show the entire tree structure graphically, have you tried taking the code and markup from the edit view of the content widget and using it on your non-edit view?
I must say, your requirement that "I need to do all these in a single function" worries me a bit. Workarea content trees can get really large very quickly. If you're trying to load all of the folders and all the taxonomies and all the collections, etc. Then the user will likely be waiting a long time for the page to load, and you risk running into timeout issues.
-- Original Answer --
Ektron v8.0 doesn't have the 3-tier option, which is too bad because that would really make your job a lot easier. In v8.0, there are ASMX web services that you can reference, including:
/workarea/webservices/content.asmx
/workarea/webservices/webserviceapi/user/user.asmx
There are lots more than this; browse through the folders within /workarea/ to see what's available.
It's been a while since I've worked with these services, so I'm a little rusty...
Suppose you add references to those two services I listed above and name them ContentService and UserService. The first thing you'll want to do is set the authentication headers. Then you can call the service methods in much the same way as the old legacy apis.
var contentApi = new ContentService.Content();
contentApi.AuthenticationHeaderValue = new ContentService.AuthenticationHeader();
contentApi.AuthenticationHeaderValue.Username = username;
contentApi.AuthenticationHeaderValue.Password = password;
contentApi.AuthenticationHeaderValue.Domain = domain;
var userApi = new UserService.User();
userApi.AuthenticationHeaderValue = new UserService.AuthenticationHeader();
userApi.AuthenticationHeaderValue.Username = username;
userApi.AuthenticationHeaderValue.Password = password;
userApi.AuthenticationHeaderValue.Domain = domain;
var ud = userApi.GetUserbyUsername("jimmy456");
long folderID = 85;
bool recursive = true;
ContentData[] folderContent = contentApi.GetChildContent(folderID, recursive, "content_id");
You can check here:
https://labs.aweber.com/docs/code_samples/subs/create
The script to add a new subscriber to the list via api requires those two pieces info...only I cannot figure out for the life of me what those two variables are!! I've beaten through every little aspect of my Aweber Subscriber Account, AND my Aweber Labs account...and I can't find any reference to either of those variables anywhere. I've submitted some tickets to them, and haven't gotten any response yet.
Does anyone have any ideas here? I've tried my account names, my list names, to no avail!
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Okay, I've got it! You can get the values of both of these variables by dumping some other variables in the aweber api after making certain api calls.
get the account id first:
$account = $aweber->getAccount($accessKey, $accessSecret);
then vardump or print_r $account.
next we get the list id:
$account = $aweber->getAccount($accessKey, $accessSecret);
$list_url = 'https://api.aweber.com/1.0/accounts/<id>/lists';
$lists = $account->loadFromUrl($list_url);
then vardump or print_r $lists.
And you are all set! I'm so happy I figured this out, it freakin took long enough. Hopefully this saves some one a bit of time.
I too have agonized over finding the $list_ID, so went to deactivate the list, and create a new one, and "discovered" that if you hover over the Deactivate button, you get a url you can copy, and this gives both %account and %list Ids
https://www.aweber.com/users/lists/deactivate/$accountID/$lisID
like this....
https://www.aweber.com/users/lists/deactivate/123456/123456
Hopefully this will help make someone as it is a super easy solution
The proper answer is Anne Allen's one, but...
Check the return of the /accounts endpoint. It should return the same account id as you detected in the link, but I had cases they were different (strange, isn't it?). Use the account id returned by the /accounts endpoint and other endpoints to retrieve lists, subscribers, etc. will start to work. It's like if some accounts have two ids, one partially works and the other fully works.
Let me tell you how to get $list_id value... login into your AWeber account and then create a new list copy only integer value from list's name.
At first, login.
1) click Reports>Settings. Your account ID will be displayed in the box,example: ?id=XXXXX
2) click List Options>List Settings. There you will see the list ID under the name.
p.s. To add subscriber, you can use this - Automatically add into aweber list