Folder Picker using jsTree with Google Apps Script and Javascript

Gists

This is a sample script for the folder picker using jsTree with Google Apps Script and Javascript.

I have already published “File Picker using Google Apps Script and Javascript without 3rd party”. In this post, jsTree is used.

Usage

1. Install Google Apps Script library.

In this script, “FilesApp” of my Google Apps Script library is used. So, please install it. You can see how to install it at here.

2. Sample script.

Please create a new Spreadsheet, and copy and paste the following script to the script editor of Spreadsheet.

Code.gs

Please set the top folder ID you want to use in topFolderId. This folder picker shows the sub-folders in the top folder. When root is used, all folders in your Google Drive are used.

function createObjFromFolderList_(obj, initTop = null) {
  if (obj.id.length == 0) {
    return [
      {
        id: obj.folderTree.id[0][0],
        parent: "#",
        text: obj.folderTree.name[0][0],
        icon: "jstree-folder",
      },
    ];
  }
  return obj.id.map((e, i) => {
    const n = obj.name;
    if (e.length == 1) {
      return {
        id: e[0],
        parent: initTop || "#",
        text: n[i][0],
        icon: "jstree-folder",
      };
    }
    return {
      id: e[e.length - 1],
      parent: e[e.length - 2],
      text: n[i][e.length - 1],
      icon: "jstree-folder",
    };
  });
}

function getFolderTree() {
  const topFolderId = "root"; // Please set the top folder ID you want to use.

  const obj = FilesApp.getAllFoldersInFolder(topFolderId);
  return createObjFromFolderList_(obj);
}

// Please run this function.
function main() {
  SpreadsheetApp.getUi().showSidebar(
    HtmlService.createTemplateFromFile("index")
      .evaluate()
      .setTitle("Folder picker sample")
  );
}

index.html

<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.10/themes/default/style.min.css"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.10/jstree.min.js"></script>
<div id="status"></div>
<div id="tree"></div>
<div id="result"></div>
<script>
  $("#status").text("Now loading...");
  google.script.run
    .withFailureHandler((err) => console.log(err))
    .withSuccessHandler((data) => {
      $("#tree").jstree({ core: { data } });
      $("#tree").on("select_node.jstree", (_, selected) => {
        $("#result").html(`Selected folder is "${selected.node.text}"`);
      });
      $("#status").text("");
    })
    .getFolderTree();
</script>
  • If you want to show the selected folder ID, please modify selected.node.text to selected.node.id

3. Testing.

When main() is run with the script editor, a sidebar is opened. You can see the folder tree in the sidebar. When you select one of folder, you can see the folder name of the selected folder. The demonstration can be seen at the top of this post.

Note

In this script, the folder tree of the folder in Google Drive of the service account can be used. When you want to show the folder tree of Google Drive of the service account, the sample script is as follows. In this case, only Google Apps Script is modified from the above script.

Please add a function of getAccessTokenFromServiceAccount_ and modify getFolderTree as follows.

// Ref: https://tanaikech.github.io/2018/12/07/retrieving-access-token-for-service-account-using-google-apps-script/
function getAccessTokenFromServiceAccount_(scopes) {
  const private_key =
    "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n"; // private_key of JSON file retrieved by creating Service Account
  const client_email = "###"; // client_email of JSON file retrieved by creating Service Account
  const url = "https://www.googleapis.com/oauth2/v4/token";
  const header = { alg: "RS256", typ: "JWT" };
  const now = Math.floor(Date.now() / 1000);
  const claim = {
    iss: client_email,
    scope: scopes.join(" "),
    aud: url,
    exp: (now + 3600).toString(),
    iat: now.toString(),
  };
  const signature =
    Utilities.base64Encode(JSON.stringify(header)) +
    "." +
    Utilities.base64Encode(JSON.stringify(claim));
  const jwt =
    signature +
    "." +
    Utilities.base64Encode(
      Utilities.computeRsaSha256Signature(signature, private_key)
    );
  const params = {
    method: "post",
    payload: {
      assertion: jwt,
      grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
    },
  };
  const data = UrlFetchApp.fetch(url, params).getContentText();
  const obj = JSON.parse(data);
  return obj.access_token;
}

function getFolderTree() {
  const obj = FilesApp.getAllFoldersInFolder(
    "root",
    getAccessTokenFromServiceAccount_([
      "https://www.googleapis.com/auth/drive.metadata.readonly",
    ])
  );
  return createObjFromFolderList_(obj);
}
  • By this modification, when main is run, you can see the folder tree of the Google Drive of the service account.

References

 Share!