Socket
Socket
Sign inDemoInstall

@uppy/provider-views

Package Overview
Dependencies
Maintainers
7
Versions
108
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uppy/provider-views - npm Package Compare versions

Comparing version 2.0.2 to 2.0.3

lib/View.js

130

lib/Browser.js
"use strict";
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
const classNames = require('classnames');
const {

@@ -11,9 +7,15 @@ h

const classNames = require('classnames');
const remoteFileObjToLocal = require('@uppy/utils/lib/remoteFileObjToLocal');
const Filter = require('./Filter');
const ItemList = require('./ItemList');
const FooterActions = require('./FooterActions');
const Browser = props => {
const Item = require('./Item/index');
const VIRTUAL_SHARED_DIR = 'shared-with-me';
function Browser(props) {
const {

@@ -24,43 +26,89 @@ currentSelection,

uppyFiles,
filterItems,
filterInput
viewType,
headerComponent,
showBreadcrumbs,
isChecked,
toggleCheckbox,
handleScroll,
showTitles,
i18n,
validateRestrictions,
showFilter,
filterQuery,
filterInput,
getNextFolder,
cancel,
done,
columns
} = props;
let filteredFolders = folders;
let filteredFiles = files;
if (filterInput !== '') {
filteredFolders = filterItems(folders);
filteredFiles = filterItems(files);
}
const selected = currentSelection.length;
return h("div", {
className: classNames('uppy-ProviderBrowser', `uppy-ProviderBrowser-viewType--${props.viewType}`)
className: classNames('uppy-ProviderBrowser', `uppy-ProviderBrowser-viewType--${viewType}`)
}, h("div", {
className: "uppy-ProviderBrowser-header"
}, h("div", {
className: classNames('uppy-ProviderBrowser-headerBar', !props.showBreadcrumbs && 'uppy-ProviderBrowser-headerBar--simple')
}, props.headerComponent)), props.showFilter && h(Filter, props), h(ItemList, {
columns: [{
name: 'Name',
key: 'title'
}],
folders: filteredFolders,
files: filteredFiles,
isChecked: props.isChecked,
handleFolderClick: props.getNextFolder,
toggleCheckbox: props.toggleCheckbox,
handleScroll: props.handleScroll,
title: props.title,
showTitles: props.showTitles,
i18n: props.i18n,
viewType: props.viewType,
validateRestrictions: props.validateRestrictions,
uppyFiles: uppyFiles,
currentSelection: currentSelection
}), selected > 0 && h(FooterActions, _extends({
selected: selected
}, props)));
};
className: classNames('uppy-ProviderBrowser-headerBar', !showBreadcrumbs && 'uppy-ProviderBrowser-headerBar--simple')
}, headerComponent)), showFilter && h(Filter, {
i18n: i18n,
filterQuery: filterQuery,
filterInput: filterInput
}), (() => {
if (!folders.length && !files.length) {
return h("div", {
className: "uppy-Provider-empty"
}, props.i18n('noFilesFound'));
}
return h("div", {
className: "uppy-ProviderBrowser-body"
}, h("ul", {
className: "uppy-ProviderBrowser-list",
onScroll: handleScroll,
role: "listbox" // making <ul> not focusable for firefox
,
tabIndex: "-1"
}, folders.map(folder => {
var _isChecked;
return Item({
columns,
showTitles,
viewType,
i18n,
id: folder.id,
title: folder.name,
getItemIcon: () => folder.icon,
isChecked: isChecked(folder),
toggleCheckbox: event => toggleCheckbox(event, folder),
type: 'folder',
isDisabled: (_isChecked = isChecked(folder)) == null ? void 0 : _isChecked.loading,
isCheckboxDisabled: folder.id === VIRTUAL_SHARED_DIR,
handleFolderClick: () => getNextFolder(folder)
});
}), files.map(file => {
const validated = validateRestrictions(remoteFileObjToLocal(file), [...uppyFiles, ...currentSelection]);
return Item({
id: file.id,
title: file.name,
author: file.author,
getItemIcon: () => file.icon,
isChecked: isChecked(file),
toggleCheckbox: event => toggleCheckbox(event, file),
columns,
showTitles,
viewType,
i18n,
type: 'file',
isDisabled: !validated.result && isChecked(file),
restrictionReason: validated.reason
});
})));
})(), selected > 0 && h(FooterActions, {
selected: selected,
done: done,
cancel: cancel,
i18n: i18n
}));
}
module.exports = Browser;

@@ -17,3 +17,4 @@ "use strict";

toggleCheckbox,
id
id,
children
} = props;

@@ -36,5 +37,7 @@ return h("li", {

className: "uppy-u-reset uppy-ProviderBrowserItem-inner"
}, itemIconEl, showTitles && title));
}, h("span", {
className: "uppy-ProviderBrowserItem-inner-relative"
}, itemIconEl, showTitles && title, children)));
}
module.exports = GridListItem;

@@ -13,7 +13,10 @@ "use strict";

const GridLi = require('./components/GridLi');
const GridListItem = require('./components/GridLi');
const ListLi = require('./components/ListLi');
const ListItem = require('./components/ListLi');
module.exports = props => {
const {
author
} = props;
const itemIconString = props.getItemIcon();

@@ -33,3 +36,3 @@ const className = classNames('uppy-ProviderBrowserItem', {

case 'grid':
return h(GridLi, _extends({}, props, {
return h(GridListItem, _extends({}, props, {
className: className,

@@ -40,3 +43,3 @@ itemIconEl: itemIconEl

case 'list':
return h(ListLi, _extends({}, props, {
return h(ListItem, _extends({}, props, {
className: className,

@@ -46,2 +49,13 @@ itemIconEl: itemIconEl

case 'unsplash':
return h(GridListItem, _extends({}, props, {
className: className,
itemIconEl: itemIconEl
}), h("a", {
href: `${author.url}?utm_source=Companion&utm_medium=referral`,
target: "_blank",
rel: "noopener noreferrer",
className: "uppy-ProviderBrowserItem-author"
}, author.name));
default:

@@ -48,0 +62,0 @@ throw new Error(`There is no such type ${props.viewType}`);

"use strict";
var _class, _isHandlingScroll, _sharedHandler, _updateFilesAndFolders, _isOriginAllowed, _temp;
var _class, _updateFilesAndFolders, _isOriginAllowed, _temp;

@@ -15,8 +15,2 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }

const generateFileID = require('@uppy/utils/lib/generateFileID');
const getFileType = require('@uppy/utils/lib/getFileType');
const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported');
const AuthView = require('./AuthView');

@@ -30,6 +24,6 @@

const SharedHandler = require('../SharedHandler');
const CloseWrapper = require('../CloseWrapper');
const View = require('../View');
function getOrigin() {

@@ -44,3 +38,3 @@ // eslint-disable-next-line no-restricted-globals

module.exports = (_temp = (_isHandlingScroll = /*#__PURE__*/_classPrivateFieldLooseKey("isHandlingScroll"), _sharedHandler = /*#__PURE__*/_classPrivateFieldLooseKey("sharedHandler"), _updateFilesAndFolders = /*#__PURE__*/_classPrivateFieldLooseKey("updateFilesAndFolders"), _isOriginAllowed = /*#__PURE__*/_classPrivateFieldLooseKey("isOriginAllowed"), _class = class ProviderView {
module.exports = (_temp = (_updateFilesAndFolders = /*#__PURE__*/_classPrivateFieldLooseKey("updateFilesAndFolders"), _isOriginAllowed = /*#__PURE__*/_classPrivateFieldLooseKey("isOriginAllowed"), _class = class ProviderView extends View {
/**

@@ -51,2 +45,4 @@ * @param {object} plugin instance of the plugin

constructor(plugin, opts) {
super(plugin, opts); // set default options
Object.defineProperty(this, _isOriginAllowed, {

@@ -58,14 +54,2 @@ value: _isOriginAllowed2

});
Object.defineProperty(this, _isHandlingScroll, {
writable: true,
value: void 0
});
Object.defineProperty(this, _sharedHandler, {
writable: true,
value: void 0
});
this.plugin = plugin;
this.provider = opts.provider;
_classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler] = new SharedHandler(plugin); // set default options
const defaultOptions = {

@@ -82,3 +66,2 @@ viewType: 'list',

this.addFile = this.addFile.bind(this);
this.filterQuery = this.filterQuery.bind(this);

@@ -88,13 +71,8 @@ this.getFolder = this.getFolder.bind(this);

this.logout = this.logout.bind(this);
this.preFirstRender = this.preFirstRender.bind(this);
this.handleAuth = this.handleAuth.bind(this);
this.handleError = this.handleError.bind(this);
this.handleScroll = this.handleScroll.bind(this);
this.listAllFiles = this.listAllFiles.bind(this);
this.donePicking = this.donePicking.bind(this);
this.cancelPicking = this.cancelPicking.bind(this);
this.clearSelection = this.clearSelection.bind(this); // Visual
this.donePicking = this.donePicking.bind(this); // Visual
this.render = this.render.bind(this);
this.clearSelection(); // Set default state for the plugin
this.render = this.render.bind(this); // Set default state for the plugin

@@ -107,3 +85,4 @@ this.plugin.setPluginState({

filterInput: '',
isSearchVisible: false
isSearchVisible: false,
currentSelection: []
});

@@ -116,12 +95,2 @@ }

/**
* Called only the first time the provider view is rendered.
* Kind of like an init function.
*/
preFirstRender() {
this.plugin.setPluginState({
didFirstRender: true
});
this.plugin.onFirstRender();
}
/**
* Based on folder ID, fetch a new folder and update it to state

@@ -132,6 +101,4 @@ *

*/
getFolder(id, name) {
return _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].loaderWrapper(this.provider.list(id), res => {
return this.sharedHandler.loaderWrapper(this.provider.list(id), res => {
const folders = [];

@@ -172,42 +139,2 @@ const files = [];

}
addFile(file) {
const tagFile = {
id: this.providerFileToId(file),
source: this.plugin.id,
data: file,
name: file.name || file.id,
type: file.mimeType,
isRemote: true,
body: {
fileId: file.id
},
remote: {
companionUrl: this.plugin.opts.companionUrl,
url: `${this.provider.fileUrl(file.requestPath)}`,
body: {
fileId: file.id
},
providerOptions: this.provider.opts
}
};
const fileType = getFileType(tagFile); // TODO Should we just always use the thumbnail URL if it exists?
if (fileType && isPreviewSupported(fileType)) {
tagFile.preview = file.thumbnail;
}
this.plugin.uppy.log('Adding remote file');
try {
this.plugin.uppy.addFile(tagFile);
return true;
} catch (err) {
if (!err.isRestriction) {
this.plugin.uppy.log(err);
}
return false;
}
}
/**

@@ -327,10 +254,2 @@ * Removes session token on client side.

providerFileToId(file) {
return generateFileID({
data: file,
name: file.name || file.id,
type: file.mimeType
});
}
handleAuth() {

@@ -357,2 +276,14 @@ const authState = btoa(JSON.stringify({

if (data.error) {
this.plugin.uppy.log('auth aborted');
const {
uppy
} = this.plugin;
const message = uppy.i18n('authAborted');
uppy.info({
message
}, 'warning', 5000);
return;
}
if (!data.token) {

@@ -372,25 +303,10 @@ this.plugin.uppy.log('did not receive token from auth window');

handleError(error) {
const {
uppy
} = this.plugin;
uppy.log(error.toString());
async handleScroll(event) {
const path = this.nextPagePath || null;
if (error.isAuthError) {
return;
}
if (this.shouldHandleScroll(event) && path) {
this.isHandlingScroll = true;
const message = uppy.i18n('companionError');
uppy.info({
message,
details: error.toString()
}, 'error', 5000);
}
handleScroll(e) {
const scrollPos = e.target.scrollHeight - (e.target.scrollTop + e.target.offsetHeight);
const path = this.nextPagePath || null;
if (scrollPos < 50 && path && !_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll]) {
this.provider.list(path).then(res => {
try {
const response = await this.provider.list(path);
const {

@@ -401,8 +317,8 @@ files,

_classPrivateFieldLooseBase(this, _updateFilesAndFolders)[_updateFilesAndFolders](res, files, folders);
}).catch(this.handleError).then(() => {
_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll] = false;
}); // always called
_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll] = true;
_classPrivateFieldLooseBase(this, _updateFilesAndFolders)[_updateFilesAndFolders](response, files, folders);
} catch (error) {
this.handleError(error);
} finally {
this.isHandlingScroll = false;
}
}

@@ -444,4 +360,3 @@ }

});
_classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].loaderWrapper(Promise.all(promises), () => {
this.sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.clearSelection();

@@ -451,14 +366,2 @@ }, () => {});

cancelPicking() {
this.clearSelection();
const dashboard = this.plugin.uppy.getPlugin('Dashboard');
if (dashboard) dashboard.hideAllPanels();
}
clearSelection() {
this.plugin.setPluginState({
currentSelection: []
});
}
render(state, viewOptions = {}) {

@@ -472,29 +375,20 @@ const {

this.preFirstRender();
} // reload pluginState for "loading" attribute because it might
// have changed above.
if (this.plugin.getPluginState().loading) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(LoaderView, {
i18n: this.plugin.uppy.i18n
}));
}
if (!authenticated) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(AuthView, {
pluginName: this.plugin.title,
pluginIcon: this.plugin.icon,
handleAuth: this.handleAuth,
i18n: this.plugin.uppy.i18n,
i18nArray: this.plugin.uppy.i18nArray
}));
}
const targetViewOptions = { ...this.opts,
...viewOptions
};
const {
files,
folders,
filterInput,
loading,
currentSelection
} = this.plugin.getPluginState();
const {
isChecked,
toggleCheckbox,
filterItems
} = this.sharedHandler;
const hasInput = filterInput !== '';
const headerProps = {

@@ -510,11 +404,14 @@ showBreadcrumbs: targetViewOptions.showBreadcrumbs,

};
const browserProps = { ...this.plugin.getPluginState(),
const browserProps = {
isChecked,
toggleCheckbox,
currentSelection,
files: hasInput ? filterItems(files) : files,
folders: hasInput ? filterItems(folders) : folders,
username: this.username,
getNextFolder: this.getNextFolder,
getFolder: this.getFolder,
filterItems: _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].filterItems,
filterItems: this.sharedHandler.filterItems,
filterQuery: this.filterQuery,
logout: this.logout,
isChecked: _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].isChecked,
toggleCheckbox: _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].toggleCheckbox,
handleScroll: this.handleScroll,

@@ -535,2 +432,23 @@ listAllFiles: this.listAllFiles,

};
if (loading) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(LoaderView, {
i18n: this.plugin.uppy.i18n
}));
}
if (!authenticated) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(AuthView, {
pluginName: this.plugin.title,
pluginIcon: this.plugin.icon,
handleAuth: this.handleAuth,
i18n: this.plugin.uppy.i18n,
i18nArray: this.plugin.uppy.i18nArray
}));
}
return h(CloseWrapper, {

@@ -541,3 +459,3 @@ onUnmount: this.clearSelection

}), _class.VERSION = "2.0.2", _temp);
}), _class.VERSION = "2.0.3", _temp);

@@ -544,0 +462,0 @@ function _updateFilesAndFolders2(res, files, folders) {

"use strict";
var _class, _isHandlingScroll, _searchTerm, _sharedHandler, _updateFilesAndInputMode, _temp;
var _class, _searchTerm, _updateFilesAndInputMode, _temp;

@@ -15,8 +15,2 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }

const generateFileID = require('@uppy/utils/lib/generateFileID');
const getFileType = require('@uppy/utils/lib/getFileType');
const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported');
const SearchInput = require('./InputView');

@@ -30,5 +24,5 @@

const SharedHandler = require('../SharedHandler');
const CloseWrapper = require('../CloseWrapper');
const CloseWrapper = require('../CloseWrapper');
const View = require('../View');
/**

@@ -39,3 +33,3 @@ * Class to easily generate generic views for Provider plugins

module.exports = (_temp = (_isHandlingScroll = /*#__PURE__*/_classPrivateFieldLooseKey("isHandlingScroll"), _searchTerm = /*#__PURE__*/_classPrivateFieldLooseKey("searchTerm"), _sharedHandler = /*#__PURE__*/_classPrivateFieldLooseKey("sharedHandler"), _updateFilesAndInputMode = /*#__PURE__*/_classPrivateFieldLooseKey("updateFilesAndInputMode"), _class = class ProviderView {
module.exports = (_temp = (_searchTerm = /*#__PURE__*/_classPrivateFieldLooseKey("searchTerm"), _updateFilesAndInputMode = /*#__PURE__*/_classPrivateFieldLooseKey("updateFilesAndInputMode"), _class = class SearchProviderView extends View {
/**

@@ -46,9 +40,7 @@ * @param {object} plugin instance of the plugin

constructor(plugin, opts) {
super(plugin, opts); // set default options
Object.defineProperty(this, _updateFilesAndInputMode, {
value: _updateFilesAndInputMode2
});
Object.defineProperty(this, _isHandlingScroll, {
writable: true,
value: void 0
});
Object.defineProperty(this, _searchTerm, {

@@ -58,10 +50,2 @@ writable: true,

});
Object.defineProperty(this, _sharedHandler, {
writable: true,
value: void 0
});
this.plugin = plugin;
this.provider = opts.provider;
_classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler] = new SharedHandler(plugin); // set default options
const defaultOptions = {

@@ -81,11 +65,6 @@ viewType: 'grid',

this.addFile = this.addFile.bind(this);
this.preFirstRender = this.preFirstRender.bind(this);
this.handleError = this.handleError.bind(this);
this.handleScroll = this.handleScroll.bind(this);
this.donePicking = this.donePicking.bind(this);
this.cancelPicking = this.cancelPicking.bind(this);
this.clearSelection = this.clearSelection.bind(this); // Visual
this.donePicking = this.donePicking.bind(this); // Visual
this.render = this.render.bind(this);
this.clearSelection(); // Set default state for the plugin
this.render = this.render.bind(this); // Set default state for the plugin

@@ -98,3 +77,4 @@ this.plugin.setPluginState({

filterInput: '',
isSearchVisible: false
isSearchVisible: false,
currentSelection: []
});

@@ -106,13 +86,2 @@ }

/**
* Called only the first time the provider view is rendered.
* Kind of like an init function.
*/
preFirstRender() {
this.plugin.setPluginState({
didFirstRender: true
});
this.plugin.onFirstRender();
}
search(query) {

@@ -127,3 +96,3 @@ if (query && query === _classPrivateFieldLooseBase(this, _searchTerm)[_searchTerm]) {

return _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].loaderWrapper(this.provider.search(query), res => {
return this.sharedHandler.loaderWrapper(this.provider.search(query), res => {
_classPrivateFieldLooseBase(this, _updateFilesAndInputMode)[_updateFilesAndInputMode](res, []);

@@ -137,71 +106,12 @@ }, this.handleError);

});
} // @todo this function should really be a function of the plugin and not the view.
// maybe we should consider creating a base ProviderPlugin class that has this method
addFile(file) {
const tagFile = {
id: this.providerFileToId(file),
source: this.plugin.id,
data: file,
name: file.name || file.id,
type: file.mimeType,
isRemote: true,
body: {
fileId: file.id
},
remote: {
companionUrl: this.plugin.opts.companionUrl,
url: `${this.provider.fileUrl(file.requestPath)}`,
body: {
fileId: file.id
},
providerOptions: { ...this.provider.opts,
provider: null
}
}
};
const fileType = getFileType(tagFile); // TODO Should we just always use the thumbnail URL if it exists?
if (fileType && isPreviewSupported(fileType)) {
tagFile.preview = file.thumbnail;
}
this.plugin.uppy.log('Adding remote file');
try {
this.plugin.uppy.addFile(tagFile);
} catch (err) {
if (!err.isRestriction) {
this.plugin.uppy.log(err);
}
}
}
providerFileToId(file) {
return generateFileID({
data: file,
name: file.name || file.id,
type: file.mimeType
});
}
async handleScroll(event) {
const query = this.nextPageQuery || null;
handleError(error) {
const {
uppy
} = this.plugin;
uppy.log(error.toString());
const message = uppy.i18n('companionError');
uppy.info({
message,
details: error.toString()
}, 'error', 5000);
}
if (this.shouldHandleScroll(event) && query) {
this.isHandlingScroll = true;
handleScroll(e) {
const scrollPos = e.target.scrollHeight - (e.target.scrollTop + e.target.offsetHeight);
const query = this.nextPageQuery || null;
if (scrollPos < 50 && query && !_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll]) {
this.provider.search(_classPrivateFieldLooseBase(this, _searchTerm)[_searchTerm], query).then(res => {
try {
const response = await this.provider.search(_classPrivateFieldLooseBase(this, _searchTerm)[_searchTerm], query);
const {

@@ -211,8 +121,8 @@ files

_classPrivateFieldLooseBase(this, _updateFilesAndInputMode)[_updateFilesAndInputMode](res, files);
}).catch(this.handleError).then(() => {
_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll] = false;
}); // always called
_classPrivateFieldLooseBase(this, _isHandlingScroll)[_isHandlingScroll] = true;
_classPrivateFieldLooseBase(this, _updateFilesAndInputMode)[_updateFilesAndInputMode](response, files);
} catch (error) {
this.handleError(error);
} finally {
this.isHandlingScroll = false;
}
}

@@ -226,4 +136,3 @@ }

const promises = currentSelection.map(file => this.addFile(file));
_classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].loaderWrapper(Promise.all(promises), () => {
this.sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.clearSelection();

@@ -233,14 +142,2 @@ }, () => {});

cancelPicking() {
this.clearSelection();
const dashboard = this.plugin.uppy.getPlugin('Dashboard');
if (dashboard) dashboard.hideAllPanels();
}
clearSelection() {
this.plugin.setPluginState({
currentSelection: []
});
}
render(state, viewOptions = {}) {

@@ -254,29 +151,26 @@ const {

this.preFirstRender();
} // reload pluginState for "loading" attribute because it might
// have changed above.
if (this.plugin.getPluginState().loading) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(LoaderView, {
i18n: this.plugin.uppy.i18n
}));
}
if (isInputMode) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(SearchInput, {
search: this.search,
i18n: this.plugin.uppy.i18n
}));
}
const targetViewOptions = { ...this.opts,
...viewOptions
};
const browserProps = { ...this.plugin.getPluginState(),
isChecked: _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].isChecked,
toggleCheckbox: _classPrivateFieldLooseBase(this, _sharedHandler)[_sharedHandler].toggleCheckbox,
const {
files,
folders,
filterInput,
loading,
currentSelection
} = this.plugin.getPluginState();
const {
isChecked,
toggleCheckbox,
filterItems
} = this.sharedHandler;
const hasInput = filterInput !== '';
const browserProps = {
isChecked,
toggleCheckbox,
currentSelection,
files: hasInput ? filterItems(files) : files,
folders: hasInput ? filterItems(folders) : folders,
handleScroll: this.handleScroll,

@@ -299,2 +193,20 @@ done: this.donePicking,

};
if (loading) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(LoaderView, {
i18n: this.plugin.uppy.i18n
}));
}
if (isInputMode) {
return h(CloseWrapper, {
onUnmount: this.clearSelection
}, h(SearchInput, {
search: this.search,
i18n: this.plugin.uppy.i18n
}));
}
return h(CloseWrapper, {

@@ -305,3 +217,3 @@ onUnmount: this.clearSelection

}), _class.VERSION = "2.0.2", _temp);
}), _class.VERSION = "2.0.3", _temp);

@@ -308,0 +220,0 @@ function _updateFilesAndInputMode2(res, files) {

{
"name": "@uppy/provider-views",
"description": "View library for Uppy remote provider plugins.",
"version": "2.0.2",
"version": "2.0.3",
"license": "MIT",

@@ -22,3 +22,3 @@ "main": "lib/index.js",

"dependencies": {
"@uppy/utils": "^4.0.1",
"@uppy/utils": "^4.0.2",
"classnames": "^2.2.6",

@@ -30,3 +30,3 @@ "preact": "^10.5.13"

},
"gitHead": "b3b68c07773395d1521c38148cbf87ed88ff2364"
"gitHead": "1eb317ba3a3115596212ac50f1d81d3188dd0619"
}

@@ -0,8 +1,13 @@

const { h } = require('preact')
const classNames = require('classnames')
const { h } = require('preact')
const remoteFileObjToLocal = require('@uppy/utils/lib/remoteFileObjToLocal')
const Filter = require('./Filter')
const ItemList = require('./ItemList')
const FooterActions = require('./FooterActions')
const Item = require('./Item/index')
const Browser = (props) => {
const VIRTUAL_SHARED_DIR = 'shared-with-me'
function Browser (props) {
const {

@@ -13,44 +18,119 @@ currentSelection,

uppyFiles,
filterItems,
viewType,
headerComponent,
showBreadcrumbs,
isChecked,
toggleCheckbox,
handleScroll,
showTitles,
i18n,
validateRestrictions,
showFilter,
filterQuery,
filterInput,
getNextFolder,
cancel,
done,
columns,
} = props
let filteredFolders = folders
let filteredFiles = files
if (filterInput !== '') {
filteredFolders = filterItems(folders)
filteredFiles = filterItems(files)
}
const selected = currentSelection.length
return (
<div className={classNames('uppy-ProviderBrowser', `uppy-ProviderBrowser-viewType--${props.viewType}`)}>
<div
className={classNames(
'uppy-ProviderBrowser',
`uppy-ProviderBrowser-viewType--${viewType}`
)}
>
<div className="uppy-ProviderBrowser-header">
<div className={classNames('uppy-ProviderBrowser-headerBar', !props.showBreadcrumbs && 'uppy-ProviderBrowser-headerBar--simple')}>
{props.headerComponent}
<div
className={classNames(
'uppy-ProviderBrowser-headerBar',
!showBreadcrumbs && 'uppy-ProviderBrowser-headerBar--simple'
)}
>
{headerComponent}
</div>
</div>
{props.showFilter && <Filter {...props} />}
<ItemList
columns={[{
name: 'Name',
key: 'title',
}]}
folders={filteredFolders}
files={filteredFiles}
isChecked={props.isChecked}
handleFolderClick={props.getNextFolder}
toggleCheckbox={props.toggleCheckbox}
handleScroll={props.handleScroll}
title={props.title}
showTitles={props.showTitles}
i18n={props.i18n}
viewType={props.viewType}
validateRestrictions={props.validateRestrictions}
uppyFiles={uppyFiles}
currentSelection={currentSelection}
/>
{selected > 0 && <FooterActions selected={selected} {...props} />}
{showFilter && (
<Filter
i18n={i18n}
filterQuery={filterQuery}
filterInput={filterInput}
/>
)}
{(() => {
if (!folders.length && !files.length) {
return (
<div className="uppy-Provider-empty">
{props.i18n('noFilesFound')}
</div>
)
}
return (
<div className="uppy-ProviderBrowser-body">
<ul
className="uppy-ProviderBrowser-list"
onScroll={handleScroll}
role="listbox"
// making <ul> not focusable for firefox
tabIndex="-1"
>
{folders.map((folder) => {
return Item({
columns,
showTitles,
viewType,
i18n,
id: folder.id,
title: folder.name,
getItemIcon: () => folder.icon,
isChecked: isChecked(folder),
toggleCheckbox: (event) => toggleCheckbox(event, folder),
type: 'folder',
isDisabled: isChecked(folder)?.loading,
isCheckboxDisabled: folder.id === VIRTUAL_SHARED_DIR,
handleFolderClick: () => getNextFolder(folder),
})
})}
{files.map((file) => {
const validated = validateRestrictions(
remoteFileObjToLocal(file),
[...uppyFiles, ...currentSelection]
)
return Item({
id: file.id,
title: file.name,
author: file.author,
getItemIcon: () => file.icon,
isChecked: isChecked(file),
toggleCheckbox: (event) => toggleCheckbox(event, file),
columns,
showTitles,
viewType,
i18n,
type: 'file',
isDisabled: !validated.result && isChecked(file),
restrictionReason: validated.reason,
})
})}
</ul>
</div>
)
})()}
{selected > 0 && (
<FooterActions
selected={selected}
done={done}
cancel={cancel}
i18n={i18n}
/>
)}
</div>

@@ -57,0 +137,0 @@ )

@@ -14,2 +14,3 @@ const { h } = require('preact')

id,
children,
} = props

@@ -39,4 +40,9 @@

>
{itemIconEl}
{showTitles && title}
<span className="uppy-ProviderBrowserItem-inner-relative">
{itemIconEl}
{showTitles && title}
{children}
</span>
</label>

@@ -43,0 +49,0 @@ </li>

const { h } = require('preact')
const classNames = require('classnames')
const ItemIcon = require('./components/ItemIcon')
const GridLi = require('./components/GridLi')
const ListLi = require('./components/ListLi')
const GridListItem = require('./components/GridLi')
const ListItem = require('./components/ListLi')
module.exports = (props) => {
const { author } = props
const itemIconString = props.getItemIcon()

@@ -21,5 +22,26 @@

case 'grid':
return <GridLi {...props} className={className} itemIconEl={itemIconEl} />
return (
<GridListItem
{...props}
className={className}
itemIconEl={itemIconEl}
/>
)
case 'list':
return <ListLi {...props} className={className} itemIconEl={itemIconEl} />
return (
<ListItem {...props} className={className} itemIconEl={itemIconEl} />
)
case 'unsplash':
return (
<GridListItem {...props} className={className} itemIconEl={itemIconEl}>
<a
href={`${author.url}?utm_source=Companion&utm_medium=referral`}
target="_blank"
rel="noopener noreferrer"
className="uppy-ProviderBrowserItem-author"
>
{author.name}
</a>
</GridListItem>
)
default:

@@ -26,0 +48,0 @@ throw new Error(`There is no such type ${props.viewType}`)

const { h } = require('preact')
const generateFileID = require('@uppy/utils/lib/generateFileID')
const getFileType = require('@uppy/utils/lib/getFileType')
const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported')
const AuthView = require('./AuthView')

@@ -9,4 +6,4 @@ const Header = require('./Header')

const LoaderView = require('../Loader')
const SharedHandler = require('../SharedHandler')
const CloseWrapper = require('../CloseWrapper')
const View = require('../View')

@@ -21,9 +18,5 @@ function getOrigin () {

*/
module.exports = class ProviderView {
module.exports = class ProviderView extends View {
static VERSION = require('../../package.json').version
#isHandlingScroll
#sharedHandler
/**

@@ -34,6 +27,3 @@ * @param {object} plugin instance of the plugin

constructor (plugin, opts) {
this.plugin = plugin
this.provider = opts.provider
this.#sharedHandler = new SharedHandler(plugin)
super(plugin, opts)
// set default options

@@ -51,3 +41,2 @@ const defaultOptions = {

// Logic
this.addFile = this.addFile.bind(this)
this.filterQuery = this.filterQuery.bind(this)

@@ -57,10 +46,6 @@ this.getFolder = this.getFolder.bind(this)

this.logout = this.logout.bind(this)
this.preFirstRender = this.preFirstRender.bind(this)
this.handleAuth = this.handleAuth.bind(this)
this.handleError = this.handleError.bind(this)
this.handleScroll = this.handleScroll.bind(this)
this.listAllFiles = this.listAllFiles.bind(this)
this.donePicking = this.donePicking.bind(this)
this.cancelPicking = this.cancelPicking.bind(this)
this.clearSelection = this.clearSelection.bind(this)

@@ -70,4 +55,2 @@ // Visual

this.clearSelection()
// Set default state for the plugin

@@ -81,2 +64,3 @@ this.plugin.setPluginState({

isSearchVisible: false,
currentSelection: [],
})

@@ -103,11 +87,2 @@ }

/**
* Called only the first time the provider view is rendered.
* Kind of like an init function.
*/
preFirstRender () {
this.plugin.setPluginState({ didFirstRender: true })
this.plugin.onFirstRender()
}
/**
* Based on folder ID, fetch a new folder and update it to state

@@ -119,3 +94,3 @@ *

getFolder (id, name) {
return this.#sharedHandler.loaderWrapper(
return this.sharedHandler.loaderWrapper(
this.provider.list(id),

@@ -154,40 +129,2 @@ (res) => {

addFile (file) {
const tagFile = {
id: this.providerFileToId(file),
source: this.plugin.id,
data: file,
name: file.name || file.id,
type: file.mimeType,
isRemote: true,
body: {
fileId: file.id,
},
remote: {
companionUrl: this.plugin.opts.companionUrl,
url: `${this.provider.fileUrl(file.requestPath)}`,
body: {
fileId: file.id,
},
providerOptions: this.provider.opts,
},
}
const fileType = getFileType(tagFile)
// TODO Should we just always use the thumbnail URL if it exists?
if (fileType && isPreviewSupported(fileType)) {
tagFile.preview = file.thumbnail
}
this.plugin.uppy.log('Adding remote file')
try {
this.plugin.uppy.addFile(tagFile)
return true
} catch (err) {
if (!err.isRestriction) {
this.plugin.uppy.log(err)
}
return false
}
}
/**

@@ -294,10 +231,2 @@ * Removes session token on client side.

providerFileToId (file) {
return generateFileID({
data: file,
name: file.name || file.id,
type: file.mimeType,
})
}
handleAuth () {

@@ -319,2 +248,10 @@ const authState = btoa(JSON.stringify({ origin: getOrigin() }))

if (data.error) {
this.plugin.uppy.log('auth aborted')
const { uppy } = this.plugin
const message = uppy.i18n('authAborted')
uppy.info({ message }, 'warning', 5000)
return
}
if (!data.token) {

@@ -348,25 +285,18 @@ this.plugin.uppy.log('did not receive token from auth window')

handleError (error) {
const { uppy } = this.plugin
uppy.log(error.toString())
if (error.isAuthError) {
return
}
const message = uppy.i18n('companionError')
uppy.info({ message, details: error.toString() }, 'error', 5000)
}
handleScroll (e) {
const scrollPos = e.target.scrollHeight - (e.target.scrollTop + e.target.offsetHeight)
async handleScroll (event) {
const path = this.nextPagePath || null
if (scrollPos < 50 && path && !this.#isHandlingScroll) {
this.provider.list(path)
.then((res) => {
const { files, folders } = this.plugin.getPluginState()
this.#updateFilesAndFolders(res, files, folders)
}).catch(this.handleError)
.then(() => { this.#isHandlingScroll = false }) // always called
if (this.shouldHandleScroll(event) && path) {
this.isHandlingScroll = true
this.#isHandlingScroll = true
try {
const response = await this.provider.list(path)
const { files, folders } = this.plugin.getPluginState()
this.#updateFilesAndFolders(response, files, folders)
} catch (error) {
this.handleError(error)
} finally {
this.isHandlingScroll = false
}
}

@@ -406,3 +336,3 @@ }

this.#sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.clearSelection()

@@ -412,15 +342,5 @@ }, () => {})

cancelPicking () {
this.clearSelection()
const dashboard = this.plugin.uppy.getPlugin('Dashboard')
if (dashboard) dashboard.hideAllPanels()
}
clearSelection () {
this.plugin.setPluginState({ currentSelection: [] })
}
render (state, viewOptions = {}) {
const { authenticated, didFirstRender } = this.plugin.getPluginState()
if (!didFirstRender) {

@@ -430,27 +350,6 @@ this.preFirstRender()

// reload pluginState for "loading" attribute because it might
// have changed above.
if (this.plugin.getPluginState().loading) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<LoaderView i18n={this.plugin.uppy.i18n} />
</CloseWrapper>
)
}
if (!authenticated) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<AuthView
pluginName={this.plugin.title}
pluginIcon={this.plugin.icon}
handleAuth={this.handleAuth}
i18n={this.plugin.uppy.i18n}
i18nArray={this.plugin.uppy.i18nArray}
/>
</CloseWrapper>
)
}
const targetViewOptions = { ...this.opts, ...viewOptions }
const { files, folders, filterInput, loading, currentSelection } = this.plugin.getPluginState()
const { isChecked, toggleCheckbox, filterItems } = this.sharedHandler
const hasInput = filterInput !== ''
const headerProps = {

@@ -468,11 +367,13 @@ showBreadcrumbs: targetViewOptions.showBreadcrumbs,

const browserProps = {
...this.plugin.getPluginState(),
isChecked,
toggleCheckbox,
currentSelection,
files: hasInput ? filterItems(files) : files,
folders: hasInput ? filterItems(folders) : folders,
username: this.username,
getNextFolder: this.getNextFolder,
getFolder: this.getFolder,
filterItems: this.#sharedHandler.filterItems,
filterItems: this.sharedHandler.filterItems,
filterQuery: this.filterQuery,
logout: this.logout,
isChecked: this.#sharedHandler.isChecked,
toggleCheckbox: this.#sharedHandler.toggleCheckbox,
handleScroll: this.handleScroll,

@@ -494,2 +395,24 @@ listAllFiles: this.listAllFiles,

if (loading) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<LoaderView i18n={this.plugin.uppy.i18n} />
</CloseWrapper>
)
}
if (!authenticated) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<AuthView
pluginName={this.plugin.title}
pluginIcon={this.plugin.icon}
handleAuth={this.handleAuth}
i18n={this.plugin.uppy.i18n}
i18nArray={this.plugin.uppy.i18nArray}
/>
</CloseWrapper>
)
}
return (

@@ -496,0 +419,0 @@ <CloseWrapper onUnmount={this.clearSelection}>

const { h } = require('preact')
const generateFileID = require('@uppy/utils/lib/generateFileID')
const getFileType = require('@uppy/utils/lib/getFileType')
const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported')
const SearchInput = require('./InputView')

@@ -9,4 +6,4 @@ const Browser = require('../Browser')

const Header = require('./Header')
const SharedHandler = require('../SharedHandler')
const CloseWrapper = require('../CloseWrapper')
const View = require('../View')

@@ -16,11 +13,7 @@ /**

*/
module.exports = class ProviderView {
module.exports = class SearchProviderView extends View {
static VERSION = require('../../package.json').version
#isHandlingScroll
#searchTerm
#sharedHandler
/**

@@ -31,5 +24,3 @@ * @param {object} plugin instance of the plugin

constructor (plugin, opts) {
this.plugin = plugin
this.provider = opts.provider
this.#sharedHandler = new SharedHandler(plugin)
super(plugin, opts)

@@ -51,8 +42,4 @@ // set default options

this.addFile = this.addFile.bind(this)
this.preFirstRender = this.preFirstRender.bind(this)
this.handleError = this.handleError.bind(this)
this.handleScroll = this.handleScroll.bind(this)
this.donePicking = this.donePicking.bind(this)
this.cancelPicking = this.cancelPicking.bind(this)
this.clearSelection = this.clearSelection.bind(this)

@@ -62,4 +49,2 @@ // Visual

this.clearSelection()
// Set default state for the plugin

@@ -73,2 +58,3 @@ this.plugin.setPluginState({

isSearchVisible: false,
currentSelection: [],
})

@@ -88,11 +74,2 @@ }

/**
* Called only the first time the provider view is rendered.
* Kind of like an init function.
*/
preFirstRender () {
this.plugin.setPluginState({ didFirstRender: true })
this.plugin.onFirstRender()
}
search (query) {

@@ -105,3 +82,3 @@ if (query && query === this.#searchTerm) {

return this.#sharedHandler.loaderWrapper(
return this.sharedHandler.loaderWrapper(
this.provider.search(query),

@@ -119,68 +96,18 @@ (res) => {

// @todo this function should really be a function of the plugin and not the view.
// maybe we should consider creating a base ProviderPlugin class that has this method
addFile (file) {
const tagFile = {
id: this.providerFileToId(file),
source: this.plugin.id,
data: file,
name: file.name || file.id,
type: file.mimeType,
isRemote: true,
body: {
fileId: file.id,
},
remote: {
companionUrl: this.plugin.opts.companionUrl,
url: `${this.provider.fileUrl(file.requestPath)}`,
body: {
fileId: file.id,
},
providerOptions: { ...this.provider.opts, provider: null },
},
}
async handleScroll (event) {
const query = this.nextPageQuery || null
const fileType = getFileType(tagFile)
// TODO Should we just always use the thumbnail URL if it exists?
if (fileType && isPreviewSupported(fileType)) {
tagFile.preview = file.thumbnail
}
this.plugin.uppy.log('Adding remote file')
try {
this.plugin.uppy.addFile(tagFile)
} catch (err) {
if (!err.isRestriction) {
this.plugin.uppy.log(err)
}
}
}
if (this.shouldHandleScroll(event) && query) {
this.isHandlingScroll = true
providerFileToId (file) {
return generateFileID({
data: file,
name: file.name || file.id,
type: file.mimeType,
})
}
try {
const response = await this.provider.search(this.#searchTerm, query)
const { files } = this.plugin.getPluginState()
handleError (error) {
const { uppy } = this.plugin
uppy.log(error.toString())
const message = uppy.i18n('companionError')
uppy.info({ message, details: error.toString() }, 'error', 5000)
}
handleScroll (e) {
const scrollPos = e.target.scrollHeight - (e.target.scrollTop + e.target.offsetHeight)
const query = this.nextPageQuery || null
if (scrollPos < 50 && query && !this.#isHandlingScroll) {
this.provider.search(this.#searchTerm, query)
.then((res) => {
const { files } = this.plugin.getPluginState()
this.#updateFilesAndInputMode(res, files)
}).catch(this.handleError)
.then(() => { this.#isHandlingScroll = false }) // always called
this.#isHandlingScroll = true
this.#updateFilesAndInputMode(response, files)
} catch (error) {
this.handleError(error)
} finally {
this.isHandlingScroll = false
}
}

@@ -193,3 +120,3 @@ }

this.#sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.sharedHandler.loaderWrapper(Promise.all(promises), () => {
this.clearSelection()

@@ -199,15 +126,5 @@ }, () => {})

cancelPicking () {
this.clearSelection()
const dashboard = this.plugin.uppy.getPlugin('Dashboard')
if (dashboard) dashboard.hideAllPanels()
}
clearSelection () {
this.plugin.setPluginState({ currentSelection: [] })
}
render (state, viewOptions = {}) {
const { didFirstRender, isInputMode } = this.plugin.getPluginState()
if (!didFirstRender) {

@@ -217,28 +134,13 @@ this.preFirstRender()

// reload pluginState for "loading" attribute because it might
// have changed above.
if (this.plugin.getPluginState().loading) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<LoaderView i18n={this.plugin.uppy.i18n} />
</CloseWrapper>
)
}
const targetViewOptions = { ...this.opts, ...viewOptions }
const { files, folders, filterInput, loading, currentSelection } = this.plugin.getPluginState()
const { isChecked, toggleCheckbox, filterItems } = this.sharedHandler
const hasInput = filterInput !== ''
if (isInputMode) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<SearchInput
search={this.search}
i18n={this.plugin.uppy.i18n}
/>
</CloseWrapper>
)
}
const targetViewOptions = { ...this.opts, ...viewOptions }
const browserProps = {
...this.plugin.getPluginState(),
isChecked: this.#sharedHandler.isChecked,
toggleCheckbox: this.#sharedHandler.toggleCheckbox,
isChecked,
toggleCheckbox,
currentSelection,
files: hasInput ? filterItems(files) : files,
folders: hasInput ? filterItems(folders) : folders,
handleScroll: this.handleScroll,

@@ -262,2 +164,21 @@ done: this.donePicking,

if (loading) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<LoaderView i18n={this.plugin.uppy.i18n} />
</CloseWrapper>
)
}
if (isInputMode) {
return (
<CloseWrapper onUnmount={this.clearSelection}>
<SearchInput
search={this.search}
i18n={this.plugin.uppy.i18n}
/>
</CloseWrapper>
)
}
return (

@@ -264,0 +185,0 @@ <CloseWrapper onUnmount={this.clearSelection}>

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc