I am engaged on a mission to assist with native initiatives and as a part of that effort, I wanted to look into creating a pleasant technique to show, make accessible, and so on., information saved in Google Drive. Google Drive permits you to make a folder public, and to be sincere, the interface is not too laborious to make use of. I’ve received a folder you’ll be able to open your self at https://drive.google.com/drive/folders/1FYLaoscxWBV_BU5sFouf7XCrv7cKktBY?usp=sharing. This is the way it appears in case you do not need to click on.
It is a fairly easy interface. You get good thumbnails, you’ll be able to view just about any form of file, and you’ll obtain it. It is good, however we will do higher, proper? I made a decision to look into utilizing the Google Drive API through Pipedream if I may get a data-centric model of the information. I may then render them on my web site and have extra management over the expertise. I may do filtering, sorting, present context, and so forth, whereas nonetheless having a dynamic checklist of information. I’ve received an preliminary model of this I am sharing right this moment, however have a follow-up deliberate with a couple of extra superior options. Okay, let’s get began.
Step One – Make/Resolve on the Folder
You are going to want a folder of some kind to check with. I made a brand new folder in Google Drive, went to the Sharing choices, and enabled public entry to view gadgets within the folder. That lets anybody see and obtain information however would not allow them to have management over it. Whereas doing so, I made observe of the URL,
https://drive.google.com/drive/u/0/folders/1FYLaoscxWBV_BU5sFouf7XCrv7cKktBY
Particularly the worth after folders
, which I assumed to be a novel folder identifier.
Step Two – Create the Pipedream workflow
In Pipedream, I constructed a brand new workflow utilizing the HTTP request set off. Do not forget Pipedream lately added assist to routinely filter out requests to favicon.ico and you must completely flip that on.
I then went so as to add an motion to get my Google Drive folders. I knew that Pipedream had built-in actions for working with Google Drive, and fairly a couple of of them:
Sadly, and a bit odd, they do not but have an motion for “Record Recordsdata in Folder”. I raised this of their Slack (monitor the problem right here!) and there is a good likelihood that by the point you learn this it will likely be supported, however fortunately, Pipedream made it extremely straightforward to do. Simply choose one of many first two choices, “Use any Google Drive with…”. I selected Node.js and also you get code like so:
import { axios } from "@pipedream/platform"
export default defineComponent({
props: {
google_drive: {
sort: "app",
app: "google_drive",
}
},
async run({steps, $}) {
return await axios($, {
url: `https://www.googleapis.com/oauth2/v1/userinfo`,
headers: {
Authorization: `Bearer ${this.google_drive.$auth.oauth_access_token}`,
},
})
},
})
After you authenticate within the step along with your account, you actually simply want to vary url
. That is it! Most instances you should add some question parameters and such and that may be further work, however 100% of the authentication is dealt with by Pipedream. I’ve mentioned it earlier than and I will say it once more – I freaking love that the boring, hard-to-do half is finished and I can simply concentrate on constructing.
I started by wanting on the Recordsdata/Record API. I wanted to determine two issues right here.
First, how will we filter to a folder? That is finished by utilizing the syntax:
q={FOLDERID} in dad and mom
I discussed needing the folder ID from step and that is the place it is available in. So my code then regarded like so:
let folderId = '1FYLaoscxWBV_BU5sFouf7XCrv7cKktBY'
let q = `"${folderId}" in dad and mom`
let url = `https://www.googleapis.com/drive/v3/information` + `?q=` + encodeURIComponent(q);
As a reminder, Pipedream helps dynamic props in actions, and I may transfer folderId
outdoors of the code and make it a step parameter if I wished. I used to be lazy this time and did not trouble.
This by itself was sufficient, however by default Google Drive returns possibly 3-4 fields per file. So as to add extra, you’ll be able to specify an inventory of fields. I used fields=*
to see the whole lot, after which determined to get:
- identify
- mime sort
- view, obtain, and thumbnail hyperlinks
- measurement
This is my code now with that replace:
import { axios } from "@pipedream/platform"
export default defineComponent({
props: {
google_drive: {
sort: "app",
app: "google_drive",
}
},
async run({steps, $}) {
let folderId = '1FYLaoscxWBV_BU5sFouf7XCrv7cKktBY'
let q = `"${folderId}" in dad and mom`
let url = `https://www.googleapis.com/drive/v3/information` + `?q=` + encodeURIComponent(q);
url += '&fields=information/identify,information/mimeType,information/webContentLink,information/thumbnailLink,information/measurement,information/webViewLink';
return await axios($, {
url,
headers: {
Authorization: `Bearer ${this.google_drive.$auth.oauth_access_token}`,
},
})
},
})
To be clear, all I did was change URL. It took extra time for me to analysis the API than it did to truly write code, due to Pipedream.
I added yet another code step simply to return my data:
export default defineComponent({
async run({ steps, $ }) {
let resp = steps.get_files.$return_value.information;
await $.reply({
standing: 200,
headers: {},
physique: resp
})
},
})
And that is it. I nonetheless cannot share new Pipedream workflows, however you’ll be able to see the endpoint your self right here: https://eoemdgkqfhrtf27.m.pipedream.web/
Step Three – Construct the Entrance Finish with Alpine.js
For the entrance finish, I made a decision on a easy interface constructed with Alpine.js. For this primary iteration, I will get the information and render them in a desk. Let’s begin with the HTML:
<div x-data="app">
<!-- on high, render an inventory of information in a desk -->
<h2>Out there Recordsdata</h2>
<desk id="fileList">
<thead>
<tr>
<th>Title</th>
<th>Kind</th>
<th>Measurement</th>
<th></th>
</tr>
</thead>
<tbody>
<template x-for="file in information">
<tr>
<td><span x-text="file.identify"></span></td>
<td><span x-text="file.mimeType"></span></td>
<td><span x-text="file.measurement"></span></td>
<td><a :href="file.webViewLink" goal="_new">view</a>/<a :href="file.webContentLink">obtain</a></td>
</tr>
</template>
</tbody>
</desk>
</div>
I’ve a desk displaying identify, sort, and measurement, with a fourth column for viewing and downloading. Viewing is finished on Google Drive, so I take advantage of a brand new tab to view it, whereas obtain will simply plain work. For my JavaScript, I saved it quite easy – on load, hit the endpoint.
const FILES_API = 'https://eoemdgkqfhrtf27.m.pipedream.web/';
doc.addEventListener('alpine:init', () => {
Alpine.knowledge('app', () => ({
async init() {
this.getFiles();
},
information: [],
async getFiles() {
let resp = await fetch(FILES_API);
this.information = await resp.json();
}
}))
});
I actually ought to have some error dealing with right here, and I positively ought to have a loading indicator, however here is the primary draft in motion:
See the Pen Render Google Drive Recordsdata by Raymond Camden (@cfjedimaster) on CodePen.
For my second draft, and with the mindset of getting non-technical folks use this, I made three adjustments. First, I modified the dimensions to a barely extra human-readable type. I discovered a superb little operate on StackOverflow named humanFileSize and up to date the desk cell to make use of it:
<td><span x-text="humanFileSize(file.measurement,true)"></span></td>
Subsequent, I regarded into altering the mime sort. There have been a couple of choices on the market however nothing that felt applicable for this straightforward front-end utility. Subsequently, I made a decision to easily roll my very own and make a judgment name on what’s supported. I made a decision to assist:
- PDFs (in fact)
- Photographs (and I did not trouble with JPG vs GIF vs and so on – common folks do not care)
- HTML
- Phrase, PowerPoint, and Excel
MDN has a nice checklist of frequent mime sorts and I used that as my reference.
This is the operate I wrote:
operate humanType(mime)
And here is how I up to date the entrance finish:
<td><span x-text="humanType(file.mimeType)"></span></td>
Lastly, I added a loading indicator:
<h2>Out there Recordsdata <span x-text="loading"></span></h2>
The place loading
default to (Loading...)
and will get set to an empty string when, nicely, issues load. This is the whole JavaScript now:
const FILES_API = 'https://eoemdgkqfhrtf27.m.pipedream.web/';
doc.addEventListener('alpine:init', () => {
Alpine.knowledge('app', () => ({
async init() {
this.getFiles();
},
information: [],
loading:"(Loading...)",
async getFiles() {
let resp = await fetch(FILES_API);
this.loading = '';
this.information = await resp.json();
}
}))
});
// https://stackoverflow.com/a/14919494/52160
/**
* Format bytes as human-readable textual content.
*
* @param bytes Variety of bytes.
* @param si True to make use of metric (SI) items, aka powers of 1000. False to make use of
* binary (IEC), aka powers of 1024.
* @param dp Variety of decimal locations to show.
*
* @return Formatted string.
*/
operate humanFileSize(bytes, si=false, dp=1) {
const thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}
const items = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
let u = -1;
const r = 10**dp;
do {
bytes /= thresh;
++u;
} whereas (Math.spherical(Math.abs(bytes) * r) / r >= thresh && u < items.size - 1);
return bytes.toFixed(dp) + ' ' + items[u];
}
operate humanType(mime)
And here is it in motion:
See the Pen Render Google Drive Recordsdata V2 by Raymond Camden (@cfjedimaster) on CodePen.
That is it for this model, however as I mentioned above, I’ve received some concepts for learn how to make this higher and I will be coming again to it in a couple of days. As at all times, let me know what you assume!
Picture by Mr Cup / Fabien Barral on Unsplash