Default HTML File manager - javascript

So I noticed when you put the path of your folder in a browser you get a default file manager.
I wanted to ask how could I manipulate the default changes in the path? Not just only the file manager but also the paths of other files, so I could parse them through a .md parser.
I tried fetching the data of the API that looked like a lot of work and I think there is a easier way to do this, because if there is a default way it generates the file manager I can just modify that.

In the end I couldn't really change the design of the main file system so I just extracted the elements and appended it to the the main HTML file.
fetch(`./Posts/`)
.then((response) => response.text())
.then((data) => {
//Parse the data to html
var parser = new DOMParser();
var posts = parser.parseFromString(data, "text/html");
// Get the files
var files = posts.querySelector("ul");
var li = files.querySelectorAll("li");
var content = document.querySelector("main");
//Seperate titles and push them in a array
var list = [];
for (var i = 0; i < li.length; i++) {
var text = li[i].innerText;
//split the innerText from ".md"
var titles = text.split(".md");
var title = titles[0];
list.push(title);
var name = li[i].getElementsByClassName("name");
//change the innerHTML of the "name" span's
name.item(0).innerHTML = title;
content.append(li[i]);
}
});

Related

Google Apps Script - batch download sheets as CSV file

This is a question that has been asked before but I'm struggling to adapt the answers to my needs.
references:
How to export to CSV from spreadsheet to drive or download folder
https://gist.github.com/mrkrndvs/a2c8ff518b16e9188338cb809e06ccf1
Initiate a download from google apps script
The structure seems to be:
create function in code.gs
create download.html
My workflow:
I have a bunch of files (20+) which I edit both manually and using a GAS.
To start with I've created a folder on Google Drive which I upload my CSV files to. I then run a standalone GAS to add a sum formula in column F to each file:
function addFormula() {
const folder = DriveApp.getFolderById('folderID');
const list = [];
const files = folder.getFiles();
while (files.hasNext()){
file = files.next();
let ssnameid = [];
ssnameid.push(file.getName(),file.getId());
list.push(ssnameid);
}
for (let g=0,len=list.length;g<len;g++) {
let id = list[g][1]; // list of Spreadsheet names[0] and ID numbers[1]
let csv = DriveApp.getFileById(id);
let docName = csv.getName();
let ss = SpreadsheetApp.openById(id);
let sheet = ss.getSheetByName(docName+'.csv');
let contents = sheet.getRange('A1:K100').getValues().filter(e => e[0]);
let rows = contents.length;
console.log(docName+' - number of rows: '+rows);
let cellF = 'F'+(rows+1);
let formulaF = '=SUM($F$2:$F$'+rows+')';
sheet.getRange(cellF).setValue(formulaF);
}
Then I go through each file, check if there are any other edits I need to make, and download as a CSV (File > Download > Comma Separated Values (.csv)). I was hoping to save time by also writing a function to download all the files as CSV.
So after making any manual edits, I then want to run a function in a standalone GAS to download all the files in the Google Drive folder as CSV files.
The answers I've found generally involve adding menu items and having pop-ups, and I don't know enough to make them suitable for a standalone GAS - I don't want any menu items or pop-ups, I just want to run a function which downloads a CSV.
For instance, how would I adapt this answer from Dr-Bracket?
Or this answer from soMarios, which works but only saves it to another folder in Google Drive, rather than downloading.
The reason I feel that having an HTML file work with a GS is that I've created a standalone function with this structure to send out emails. Using an HTML email template, I created a function in a standalone GAS to send out emails.
Is this the right approach for batch downloading files as CSV?
Thank you
Further references/clues:
https://developers.google.com/apps-script/guides/html/templates#code.gs https://developers.google.com/apps-script/guides/html/reference/run#index.html https://developers.google.com/apps-script/reference/drive/file#getDownloadUrl()
EDIT - My Solution
The workaround is to send all the files to a folder on Google Drive and then download the folder. So the benefit is only downloading one folder rather than downloading each file. Here's the code adapted from the soMarios answer linked to above:
function saveCSV() {
/** sourceFolder contains all the Google Sheets you want to save as CSV files */
const sourceFolder = DriveApp.getFolderById('folderID');
const list = [];
const files = sourceFolder.getFiles();
while (files.hasNext()){
file = files.next();
let ssnameid = [];
ssnameid.push(file.getName(),file.getId());
list.push(ssnameid);
}
console.log(list);
for (let g=0,len=list.length;g<len;g++) {
let id = list[g][1]; // list of Spreadsheet names[0] and ID numbers[1]
let csv = DriveApp.getFileById(id);
let docName = csv.getName();
let ss = SpreadsheetApp.openById(id);
let sheet = ss.getSheetByName(docName+'.csv');
/** save files as CSV to Google Drive folder */
let requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
let sheetID = sheet.getSheetId().toString();
let url = "https://docs.google.com/spreadsheets/d/"+id+"/export?gid="+sheetID+"&format=csv"
let result = UrlFetchApp.fetch(url, requestData);
let resource = {
title: docName+'.csv',
mimeType: 'application/vnd.csv',
parents: [{ id: 'downloadFolderID' }]
}
Drive.Files.insert(resource,result)
}
}
Note that for this to work you need to add Drive API (Services > Add a Service > Drive API)
To download a sheet as csv whitout any further manipulation, try this auto-download script
gs
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('M E N U')
.addItem('auto download', 'autoDownload')
.addToUi();
}
function autoDownload() {
var html = HtmlService.createHtmlOutputFromFile('download');
SpreadsheetApp.getUi().showModalDialog(html, 'CSV download interface');
}
function saveAsCSV() {
var ssid = 'your spreadsheet id';
var folderID = 'temporary folder id'
var csv = "";
var ss = SpreadsheetApp.openById(ssid)
ss.getSheets()[0].getDataRange().getValues().forEach(function (r) {
csv += r.join(",") + "\n";
});
var url = DriveApp.getFolderById(folderID)
.createFile(ss.getName() + '.csv', csv, MimeType.CSV)
.getDownloadUrl()
.replace("?e=download&gd=true", "");
return url;
}
download.html
<!DOCTYPE html>
<html>
<body>
Auto Download CSV ... please wait
</body>
<script>
function executeDownload(url) {
window.location.href = url;
}
window.onload=function() {
google.script.run
.withSuccessHandler(executeDownload)
.saveAsCSV();
window.setTimeout(function(){google.script.host.close()},9000);
}
</script>
</html>
tested with chrome
you can modify ssid, temporary folder id and setTimeout parameter to optimize

Blob would be exported before changes are made to the files

I wrote a google script to generate resume and cover letter faster. It does the following
use ui.prompt to input content
create a folder and copy docs to the folder
replace keyword to content
convert docs to pdf in the folder
However, somehow the docs would be converted to PDFs before the keywords were replaced.
I have tried below but to no avail:
async awaits to wait for the main function before starting exporting PDFs
use utilities.sleep() to delay the exports
I have the main function and export function below for your information.
function jobHuntAutomation() {
//UI prompts for documents
var ui = DocumentApp.getUi();
var companyName = ui.prompt('Cover Letter', 'Enter Company Name: \n', ui.ButtonSet.OK);
var positionName = ui.prompt('Cover Letter', 'Enter Position Name: \n', ui.ButtonSet.OK);
var hiringManagerName = ui.prompt('Cover Letter', 'Enter Hiring Manager Name: \n', ui.ButtonSet.OK);
//Create some file name strings
var folderName = `${companyName.getResponseText()}_${positionName.getResponseText()}`
var coverLetterName = `${companyName.getResponseText()}_${positionName.getResponseText()}_Coverletter`
var resumeName = `${companyName.getResponseText()}_${positionName.getResponseText()}_Resume`
//Get new folder object and Id
var newFolder = DriveApp.getFolderById(mainFolderId).createFolder(folderName);
var newFolderId = newFolder.getId();
var newFolderUrl = newFolder.getUrl()
//Make a copy
console.log('Making Copies')
DocumentApp.getUi().showModalDialog(modalMessage('Making Copies...'), 'Status');
var coverLetterId = DriveApp.getFileById(coverLetterTemplateId).makeCopy(coverLetterName, newFolder).getId();
var resumeId = DriveApp.getFileById(resumeTemplateId).makeCopy(resumeName, newFolder).getId();
//Status
DocumentApp.getUi().showModalDialog(modalMessage('Updating Content...'), 'Status');
//Get the coverLetter document body as a variable
var coverLetterBody = DocumentApp.openById(coverLetterId).getBody();
//Get the resume document body as a variable
var resumeBody = DocumentApp.openById(resumeId).getBody();
//Update Content
doc.replaceText(keyword, input.getResponseText())
.
.
.
//you get the idea
//export PDFs
convertToPdf(resumeId, newFolder)
convertToPdf(coverLetterId, newFolder)
DocumentApp.getUi().showModalDialog(folderLink(newFolderUrl), 'Link');
}
function convertToPdf(fileId, dest) {
doc = DriveApp.getFileById(fileId);
docblob = doc.getAs('application/pdf');
console.log(`Converting ${doc.getName()}...`)
/* Add the PDF extension */
docblob.setName(doc.getName() + ".pdf");
// add file to the dest Folder
dest.createFile(docblob);
}
It would be much appreciated if someone knows a solution to export PDFs AFTER the keywords are replaced. TIA
I figured it out. the docs need to be saveAndClose() before exporting so the changes would be flushed

Save Gmail attachments on Google Drive

I would like to save gmail attachments(.pdf files) from a specific email in a specific Google Drive folder. I also need to rename file with a string composed by some string of the email.
I have developed a simple script using Google Apps Script with some functions.
This is the main function I have wrote:
function GmailToDrive() {
var query = '';
query = 'in:inbox from:noreply#agyo.io has:nouserlabels ';
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if (threads.length > 0) {
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for (var i in threads) {
var mesgs = threads[i].getMessages();
for (var j in mesgs) {
//get attachments
var attachments = mesgs[j].getAttachments();
var message_body = mesgs[j].getBody();
for (var k in attachments) {
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if (!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
file.setName(renameFile_(attachment, message_body))
parentFolder.addFile(file);
root.removeFile(file);
}
}
threads[i].addLabel(label);
}
}
The checkIfDefinedType_(attachment) function checks if the attachments is a .pdf file and the renameFile_(attachment, message_body) rename the attachment extracting some string from the email.
The script seems to be correctly developed but sometimes I have two or more same attachments saved in my google drive folder.
Stefano, I had the same issue, if this is the same code as adapted from here.
I removed the line for (var i in fileTypesToExtract) { which was causing duplicates for me. It was running the query for each of the file types.
// `has:pdf` searches for messages with PDF attachments
var query = 'has:pdf in:inbox from:noreply#agyo.io has:nouserlabels ';
var results = Gmail.Users.Messages.list(userId, {q: query});
results.messages.forEach(function (m) {
var msg = GmailApp.getMessageById(m.id);
msg.getAttachments().forEach(function (a) {
var fileName = a.getName();
fileName = saveAttachmentToFolder(folder, a, fileName, msg.getDate(), input.tz);
});
});
function saveAttachmentToFolder(folder, attachment, fileName, date, timezone) {
if (timezone) {
fileName = standardizeName(attachment, date, timezone);
}
Logger.log(fileName);
folder.createFile(attachment.copyBlob()).setName(fileName);
}
The code snippet above is based on a Gmail add-on that I created, specifically for saving attachments to labeled folders in Drive: https://github.com/ellaqezi/archiveByLabel/blob/main/Code.gs#L24
In the label field, you can define nested directories to create in Drive e.g. foo/bar.
In the query field, you can copy the parameters as you would use them in Gmail's search bar.

JS Get properties from many files at once

What I have: 50 mp3 files in a folder.
What I want to do: Create an object for every file that includes name and src.
What I don't know how to do is select and get properties from all of the files. Is it even possible? I know that you can get info from a text file via JS.
It would maybe be something like:
for (var i = 0; i < musicFolder.length; i++) {
var object = new Object (
musicFolder[i].title,
musicFolder[i].path/src
);
objectArray.push(object);
}
I would perhaps need to select an entire folder, but I dont know how to do this is JS.
Assuming that you are running this in Node.js and you only need the name and the path of the file, you can do this:
var fs = require('fs');
path = 'your path here';
const res = [];
fs.readdir(path, (err, items) => {
for (var i=0; i<items.length; i++) {
res.push({
name: items[i],
src: `${path}/${items[i]}`
});
}
console.log(res)
});
This will iterate your folder and list all the files in it. Then it will save the name of the file and its path in a object and push it to an array.

Add javascript to pdf file using iTextSharp

I want to embed a javascript snippet inside of a pdf file so that it will immediately print when it's opened from a browser window. To try and achieve this I'm following this example here.
I have created a helper class that has a static method to handle this task. I already have the pdf file path string ready to pass into the method. What I don't understand is how the output stream portion of this works. I would like the updated pdf to be saved to my servers hard drive. I do not want to stream it back to my browser. Any guidance would be greatly appreciated.
public class PdfHelper
{
public static void AddPrintFunction(string pdfPath, Stream outputStream)
{
PdfReader reader = new PdfReader(pdfPath);
int pageCount = reader.NumberOfPages;
Rectangle pageSize = reader.GetPageSize(1);
// Set up Writer
PdfDocument document = new PdfDocument();
PdfWriter writer = PdfWriter.GetInstance(document, outputStream);
document.Open();
//Copy each page
PdfContentByte content = writer.DirectContent;
for (int i = 0; i < pageCount; i++)
{
document.NewPage();
// page numbers are one based
PdfImportedPage page = writer.GetImportedPage(reader, i + 1);
// x and y correspond to position on the page
content.AddTemplate(page, 0, 0);
}
// Inert Javascript to print the document after a fraction of a second to allow time to become visible.
string jsText = "var res = app.setTimeOut(‘var pp = this.getPrintParams();pp.interactive = pp.constants.interactionLevel.full;this.print(pp);’, 200);";
//string jsTextNoWait = “var pp = this.getPrintParams();pp.interactive = pp.constants.interactionLevel.full;this.print(pp);”;
PdfAction js = PdfAction.JavaScript(jsText, writer);
writer.AddJavaScript(js);
document.Close();
}
}
For how to accomplish this task, please take a look at this and this SO posts.
Basically you should have something like this:
var pdfLocalFilePath = Server.MapPath("~/sourceFile.pdf");
var outputLocalFilePath = Server.MapPath("~/outputFile.pdf");
using (var outputStream = new FileStream(outputLocalFilePath, FileMode.CreateNew))
{
AddPrintFunction(pdfLocalFilePath, outputStream);
outputStream.Flush();
}

Categories