Code Monkey home page Code Monkey logo

kloudless / file-picker Goto Github PK

View Code? Open in Web Editor NEW
216.0 19.0 53.0 8.73 MB

The Kloudless File Picker is a file chooser and uploader for apps that integrates with 20+ cloud storage services with a few lines of code

Home Page: https://kloudless.com

License: MIT License

HTML 0.31% CSS 0.17% JavaScript 84.04% Shell 0.18% TypeScript 2.68% Less 7.20% Pug 4.63% EJS 0.78%
file-explorer file-uploader cloud-storage kloudless javascript file-picker picker file-upload file-transfer

file-picker's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

file-picker's Issues

Provide a `before` type hook in `Events`

Augment the provided success, error and cancel events with some sort of before type so that appropriate UI action can be taken.

Why? With no modal treatment provided users wanting that interaction must roll their own into the chooser (in our case) process. Activating the overlay before calling choose and removing it on the provided events. The common scenario is a success, which is good, but in the case of a large number of uploads the wait can make for poor UX. Given a hook into the beforeSend type of area would be ideal for us as we could dismiss any UI, telling the user to go about their business and we'll notify them when done.

webhdfs

any chance you can add support for webhdfs over their rest API?

thanks

Multipart uploads for file saver?

Is there any plan to have the File Explorer saver support multipart uploads? We can't release with the current 100MB limit.

Thanks Vinod.

Unclear which data was returned with the next page loaded

It's hard to view subsequent pages as the data returned is auto-sorted within the current data visible. The better approach would be to just append the "infinite scroll" data sorted locally, with the user having the option to sort the full dataset via the column headers.

Warn the user if they are closing a tab when an operation is in progress

Currently, there is no warning to the user if the user closes a browser tab in the middle of an operation. A confirmation alert would be good to have. The only operation that this matters for seems to be uploads via the Computer option. In other cases (such as a Save in progress), it doesn't seem necessary.

Second connection seems to fail in Internet Explorer 9, 10, and 11

Steps to reproduce:

  1. In Internet Explorer 9, 10, or 11, connect to Dropbox in the Kloudless widget.
  2. Refresh page.
  3. In Kloudless menu, click to view your accounts.
  4. Click the Box icon.
  5. Provide credentials and connect.

Expected: Box window closes and you see the file list of the service.

Observed: The Box window closes, but the view does not update. The Box service is not added to your list of accounts. If you then refresh the browser and go back to Kloudless, you'll see Box is already successfully connected.

I don't always get a bearer_token

I've specified retrieve_token in my explorer setup but it's not always being returned. For instance, i'm triggering inside a click handler but not using chooserify - shouldn't matter, right?

$(".toolbar").on("click", "a[data-action]", function (event) {
	event.preventDefault();
	var tgt = (event.target.nodeName.toUpperCase()=="A") ? event.target : event.target.parentNode, // handle clicking icon inside link
		id = tgt.getAttribute("data-fileid");
	switch (tgt.getAttribute("data-action")) {
		case "upload-kloudless":
	var inst = window.Kloudless.explorer({
		"app_id": KLOUDLESS_APP_ID,
		"flavor": "chooser",
		"retrieve_token": true
	});
	inst.on("success", function (files) {
		console.log("files", files);
		var xhr = new XMLHttpRequest();
		xhr.open("GET", "https://api.kloudless.com/v0/accounts/" + files[0].account + "/files/" + files[0].id + "/contents", true);
		xhr.setRequestHeader("Authorization", "Bearer " + files[0].bearer_token.key);
		xhr.responseType = "arraybuffer";
		xhr.onload = function(oEvent) {
			if (xhr.status === 200) {
				var content = new Blob([xhr.response], {type: files[0].mime_type});
				myHandler.HandleCloudUpload(files[0].name, content, files[0].mime_type);
			}
		};
		xhr.send();
	});
	inst.choose();
   	break;
   // etc

I'm trying to download a file (in this case from Dropbox) and then pass it onto my external handler. To do this requires the bearer token. It seems that if I perform the code above once, and select a file - it is downloaded fine once. If I then trigger the same code again (click the button on the toolbar a second time) then Chooser appears and lets me select the file - but the bearer_token is now missing from the files array that it returns.

Click it five more times, and it will return properly four of those times and then not the fifth. So bearer_token doesn't seem like it can be relied upon, or my code is doing something weird. Any pointers?

Box multipart uploads fail

I left an issue on the python lib repo as well. Our Box multipart uploads are failing to init. Is multipart box upload still supported?

Thanks,
-Alex

Select button doesn't handle double clicks/click spam

If a user clicks the select button multiple times while the widget is processing, it will fire multiple "success" events and make calls to Kloudless api for every click.

Sending two network requests on a double-click doesn't seem right. This button should probably be locked while processing, or debounced.

Version control on CDN?

I'm interested to hear if you guys have plans to tag release versions on the CDN? Or if you have a recommended way to manage version dependancies (npm+github?). An official ruby gem or npm module would be preferred for us.

Chrome console showing an error 404

Just trying out with my developer account in which I',m using chooser and saver.

About a second or so after my app loads, this shows up on the chrome console:

[Tue Nov 21 2017 22:41:50 GMT+1100 (AEDT)] body 404 Not Found get /p/platform/explorer/explorer.html?app_id=(hidden)&exp_id=535840947302&flavor=chooser&origin=https%3A%2F%2F(hidden)&custom_css=false&multiselect=false&link=true&computer=false&copy_to_upload_location=false&upload_location_uri=&services=null&persist=%22local%22&account_key=false&create_folder=true&types=[] 

When I press a button to start a chooser, I'm setting up a reference to the explorer, then using the success event to grab the value.

var KLOUDLESS_APP_ID = (hidden), 
		KLOUDLESS_INSTANCE = window.Kloudless.explorer({
		"app_id": KLOUDLESS_APP_ID,
		"flavor": "chooser",
		"retrieve_token": true
	})

That actually all works, but as soon as the explorer window appears I also see a similar console message - 404 not found , etc

Save explorer fails to popup

When I try to activate the save explorer I get the following error after waiting about 5 seconds from my explorer.save() call:

Uncaught TypeError: Cannot read property 'length' of undefined

this happens in the explorer.save function. During an internal callback, something doesn't provide a required argument.

I was able to fix it by replacing explorer.save with a function that provides a default argument like this:

var origSave = explorer.save

 explorer.save = function (o) {
    if (!Array.isArray(o)) o = [];
   origSave.call(this, o);
}

Not sure exactly the cause, or if this fix is fully valid. But it does get the popup working

link_options ignores direct parameter

When I initialize explorer with the following parameters explorer creates a link with the right expiration date and state but direct is set to false.
`

    link: true,
    link_options: 
    {
        direct: true,
        expiration: expiration_date.toISOString(),
        active: true
    },

`

The account is on Google Drive with normal access -admin access has the same result-, any ideas?


On further inspection of the request that the file explorer made I found this payload:

active: true
direct: false
expiration: "2017-04-23T06:33:59.264Z"
file_id: [FILE_ID]

Everything in the request body is accurate except direct, which should be true, is set to false.
Something in the library is forcing direct to be false.

Bypass mobile pop-up blocking

The experience on mobile currently requires the user to disable popup blocking so that the authentication popup may open. However, there is a possibility that popups will not be blocked if it is opened on the direct code path from the event handler rather than after a postMessage to the iframe on the same domain as the API server.

This can be accomplished in two ways:

  1. The user could click on a service button within the iframe.
    Each service button would have to be in its own iframe with the appropriate JS/CSS so that clicking them initiates the authentication process. These iframes must be loaded from the same domain as the API server, similar to the /static/iexd.html so it does require some work from the Kloudless team to configure the backend.
    Pros:

    • Better UX since we avoid an extra click.

    Cons:

    • The number of iframes that would have to be loaded increases linearly with the number of services displayed, which makes this more inefficient.
  2. Or we need to display a separate UI element after the user clicks a service that requires another click to open the popup.
    For example, it could be implemented as a light-box effect with a confirmation dialog indicating that a pop-up will be opened to connect the service. The iexd.html iframe can be made visible in preparation to display the lightbox, taking up the entirety of the UI, if we're on mobile and feel the open() might fail. If it does indeed fail, the confirmation dialog can display and request the second click.
    Pros:

    • Only a single additional iframe needs to be loaded.

    Cons:

    • An extra click is required by the mobile user.

I'm leaning towards 2 if the UX experience isn't terrible.

Angular 2 Support

Do you guys already have an official plan for supporting Angular 2? I'm planning to work on integrating this on an Angular 2 project.

`startFileUpload` does not fire

selected does but the startFileUpload does not.

i.e this hits:

explorer.on("selected", function() {... do stuff });

this does not:

 explorer.on("startFileUpload", function() {... do stuff });

Allow more complex options on link creation

direct_link isn't the only feature we'd like made available. Since link creation is such a common operation, it would make sense to take in additional attributes in an object for expiration and password as well. While it wouldn't work in the initialise_frame of the loader, this data should be able to be provided to the Explorer via the 'DATA' postMessage.

Do/will you support "Save" instead of "Save as..."?

First: Very cool library! I'm very interested in it.

The demo applications, upon clicking "Save file," require you to choose the location in which to save the file. So my question: Is it currently possible/documented (or is it a planned future feature) for the application to remember where the last file was saved, and re-save a new version over top of it?

That would be ideal for editor applications, in which the user is editing a file and regularly saving (or the application is regularly auto-saving).

JS errors when trying to upload file in FireFox

Environment: Win, Mac. FireFox 39.0.3

When the explorer is being invoked through explorer.choose(), the popup appears but number of errors appear:

ReferenceError: callback is not defined explorer.js:464:205438

Then selecting file to upload, file is added to the list. Pressing Upload starts upload, but once 100% is uploaded, new error is thrown:

TypeError: i.filesystem is not a function explorer.js:464:594370

And no Success event is invoked in the explorer itself. So, it is broken from that step.

Saver fails with https version of link.

This link fails to save:

https://public.plangrid.com/kloud/PlanGrid-is-processing-your-request.zip

while this link works:

http://public.plangrid.com/kloud/PlanGrid-is-processing-your-request.zip

The first one recieves a 400 error from the kloudless endpoint. Invalid URL: https…-your-request.zip

The second link is processed fine.

Saver should prompt to overwrite on a name conflict

If any of the files being saved conflict with existing files in the directory (as viewed by the Saver for the data it has loaded), the user should be prompted to confirm if they'd like to overwrite files with the same name or not. This should set the overwrite attribute on the requests made to save the files. The default overwrite option should be false, in case the Saver does not see an existing file with the same name.

Is persistent file access supported?

First, I would like to say that I'm amazed by the Kloudless file explorer, it is obvious a lot of work has been put into it. However, we are looking for the following functionalities and couldn't find if Kloudless offers it:

  • Read file from path
  • Write file to path
  • Prompt user to pick a file/folder for saving and return the selected file/folder path
  • Prompt user to pick a file/folder for opening and return the selected file/folder path

These 4 parts together enable a seamless cloud storage experience with the same capabilities as native local file access (i.e. once the user opened a file that file is then accessible by our web-app indefinitely).

Is this possible through Kloudless?


For example, opening a file and then reading it later seamlessly in OneDrive is possible through the MSGraph API by doing the following steps:

  1. Make user pick a file using the OneDrive file picker, configured to return metadata about the picked file, most notably its unique id
  2. Query the path of this file using its id
  3. Store this path

-- user closes, then later re-opens app --

  1. Acquire download link for previously stored path
  2. Download file

Saver doesn't follow HTTP Status Code 30x redirects

It would be nice if the saver could handle file URLs which may be redirected.

IE

File Explorer gives Kloudless the url "example.com/myFile.pdf" to save
Kloudless requests "example.com/myFile.pdf" and recieves a 302 status code with a "Location: example.com/myActualFile.pdf" header

It would be nice if Kloudless would follow that header to the actual file and save that one.

I don't know if this is feasable, but would be quite useful for hooking up to dynamic file systems.

Possible IE9 bug (console?)

Testing on IE9 I have just seen the familiar "works only with dev tools open" issue. In my experience the usual cause of this is console.log statements without a shim for the non-existent console object in IE9.

Solution is to simply polyfill console if not there.

thanks

bearer_token is never set, APIKey works

I have client-side web apps (no server-side code) that use chooser and saver. I've had previous problems getting the bearer token in a consistent manner. Now, Chooser doesn't ever return a bearer token. Here's a simple script to pick and display an image using chooser.

var KLOUDLESS_APP_ID = " (my api key) ",
    KLOUDLESS_CHOOSER = window.Kloudless.explorer({
			app_id: KLOUDLESS_APP_ID,
			retrieve_token: true
		}),
    picker = document.getElementById("pick");

picker.onclick = function () {
  KLOUDLESS_CHOOSER.choose();
}


KLOUDLESS_CHOOSER.on("success", function (files) {
  console.log("upload-kloudless", files);
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "https://api.kloudless.com/v0/accounts/" + files[0].account + "/files/" + files[0].id + "/contents", true);
  xhr.setRequestHeader("Authorization", "Bearer " + files[0].bearer_token.key);
  xhr.responseType = "arraybuffer";
  xhr.onload = function(oEvent) {
    if (xhr.status === 200) {
      
    var blob = new Blob([this.response], {type: files[0].mime_type}); 
    console.log("content", blob, blob.type, this.response, typeof this.response);  

      var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(this.response)));

      var src = 'data:' + files[0].mime_type + ';base64,'+ base64String;

      var img = document.createElement("img");
      document.body.appendChild(img);
      img.src = src;

      var p = document.createElement("p");
      p.textContent = files[0].name + " " + files[0].mime_type;
      document.body.appendChild(p);

    }
  };
  xhr.send();
});

however, I never get a bearer_token, so this code breaks setting the request header.

If I switch out the code and use the secret key then all is well

var KLOUDLESS_APP_ID = " (my app key) ",
    KLOUDLESS_APP_KEY = " (myy app secret) ",
    KLOUDLESS_CHOOSER = window.Kloudless.explorer({
      app_id: KLOUDLESS_APP_ID,
      retrieve_token: true
    }),
    picker = document.getElementById("pick");

picker.onclick = function () {
  KLOUDLESS_CHOOSER.choose();
}


KLOUDLESS_CHOOSER.on("success", function (files) {
  console.log("upload-kloudless", files);
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "https://api.kloudless.com/v0/accounts/" + files[0].account + "/files/" + files[0].id + "/contents", true);
  xhr.setRequestHeader("Authorization", "APIKey " + KLOUDLESS_APP_KEY);
  xhr.responseType = "arraybuffer";
  xhr.onload = function(oEvent) {
    if (xhr.status === 200) {
      
    var blob = new Blob([this.response], {type: files[0].mime_type}); 
    console.log("content", blob, blob.type, this.response, typeof this.response);  

      var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(this.response)));

      var src = 'data:' + files[0].mime_type + ';base64,'+ base64String;

      var img = document.createElement("img");
      document.body.appendChild(img);
      img.src = src;

      var p = document.createElement("p");
      p.textContent = files[0].name + " " + files[0].mime_type;
      document.body.appendChild(p);

    }
  };
  xhr.send();
});

But doing so would mean exposing my secret key in my source code. Is there a solution to always guaranteeing a bearer_token will be returned?

Account ID is absent if user selects root folder

I'm using File Explorer in folder selection mode.
It works well if user selects non-root folder. But if user selects root folder, selected folder metadata doesn't contain account property.

Here is code:

var explorer = window.Kloudless.explorer({
  'app_id': '<app_id>',
  'persist': 'none',
  'link': false,
  'keys': keys,
  'services': [],
  'types': ['folders'],
  'display_backdrop': true
});

explorer.on('success', function(files) {
  console.log('Successfully selected folder', files);
});

explorer.on('cancel', function() {
  console.log('Folder selection cancelled');
});

explorer.on('error', function(error) {
  console.error('Failed to select folder', error);
});

explorer.choose();

Result for non-root folder:

[{
    "account": "<account_id>",
    "ancestors": [],
    "name": "<folder_name>",
    "parent": {
        "name": "<parent_name>",
        "id": "<parent_id>"
    },
    "created": null,
    "modified": null,
    "can_upload_files": true,
    "raw_id": "<raw_id>",
    "can_create_folders": true,
    "path": "<path>",
    "type": "folder",
    "id": "<folder_id>",
    "size": null,
    "friendlySize": ""
}]

Result for root folder:

[{
    "id": "root",
    "name": "root",
    "type": "root",
    "modified": null,
    "size": null,
    "friendlySize": null,
    "path": "/",
    "can_create_folders": true,
    "can_upload_files": true
}]

Save to Computer

The Saver should include a 'Computer' option that opens a Save As dialog to save a file to.

A typo in docs

There is a typo in the basic example

<body>
  <button id="file-explorer">Explore!</button>
  <script type="text/javascript" src="https://static-cdn.kloudless.com/p/platform/sdk/kloudless.explorer.js"></script>
  <script type="text/javscript">
      // Explorer initialization JS here.
  </script>
</body>

Error in "text/javscript"

Can I save a file using a base-64-encoded data URL?

Using the JavaScript library documented here, if I try explorer.save( [ { url : 'data:text/plain;base64,Tm90aGluZwpNdWNo', type : 'text/plain' } ] ); I get back an error that the URL is invalid.

Do you support base-64-encoded data URLs? If so, what am I doing wrong? If not, do you plan to support them in the future?

Thank you!

Switching accounts in saver broken on Chrome

Transposed from an internally filed bug:

Steps to reproduce:

Open Kloudless Saver.
Associate an account with Dropbox.
Save to Dropbox.
Reopen Kloudless Saver.
Click account switcher dropdown and then click "Accounts".

Expected: Able to pick another account or another cloud service.

Observed: No response.

Note: In the uploader, this isn't happening. You can work around this by clicking on the first dropbox account and then clicking on "Accounts", but it's very unintuitive, and should work directly.

publish to npm/bower

Hi,

You should publish this to npm and optionally to bower so that we can use it in our projects.

Dropbox sort flips as you go through multiple levels of subfolders

Reproduced in Google Chrome, 43.0.2357.124 (64-bit)
Steps to reproduce:

  1. Using the file explorer, connect to Dropbox.
  2. Go to a folder with a lot of nesting layers (see structure below).
  3. Navigate to deepest level of heirarchy.

Structure: Folder 1> Folder 1a> Folder 1b> Folder 1c.

Expected: Sorting stays consistent on all levels.

Observed: Sorting flips as you go from folder to folder.

Limit Number of Files

Hi,
I was wondering if there was an ability to limit the user to only upload 2 files from the chooser is, this possible?

Allow types string to be a RegExp

I have a use case where any permutation of a ".foo" extension's capitalization needs to be allowed. I can list them all:

`['foo', 'FOO', 'Foo', 'fOo'...]`

Much better would be:

`/[FfOo]{3}/`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.