|
@@ -1,649 +1,7 @@
|
|
|
-const { h, Component } = require('preact')
|
|
|
-const AuthView = require('./AuthView')
|
|
|
-const Browser = require('./Browser')
|
|
|
-const LoaderView = require('./Loader')
|
|
|
-const generateFileID = require('@uppy/utils/lib/generateFileID')
|
|
|
-const getFileType = require('@uppy/utils/lib/getFileType')
|
|
|
-const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported')
|
|
|
+const ProviderViews = require('./ProviderView')
|
|
|
+const SearchProviderViews = require('./SearchProviderView')
|
|
|
|
|
|
-/**
|
|
|
- * Array.prototype.findIndex ponyfill for old browsers.
|
|
|
- */
|
|
|
-function findIndex (array, predicate) {
|
|
|
- for (let i = 0; i < array.length; i++) {
|
|
|
- if (predicate(array[i])) return i
|
|
|
- }
|
|
|
- return -1
|
|
|
-}
|
|
|
-
|
|
|
-// location.origin does not exist in IE
|
|
|
-function getOrigin () {
|
|
|
- if ('origin' in location) {
|
|
|
- return location.origin // eslint-disable-line compat/compat
|
|
|
- }
|
|
|
- return `${location.protocol}//${location.hostname}${location.port ? `:${location.port}` : ''}`
|
|
|
-}
|
|
|
-
|
|
|
-class CloseWrapper extends Component {
|
|
|
- componentWillUnmount () {
|
|
|
- this.props.onUnmount()
|
|
|
- }
|
|
|
-
|
|
|
- render () {
|
|
|
- return this.props.children[0]
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Class to easily generate generic views for Provider plugins
|
|
|
- */
|
|
|
-module.exports = class ProviderView {
|
|
|
- static VERSION = require('../package.json').version
|
|
|
-
|
|
|
- /**
|
|
|
- * @param {object} plugin instance of the plugin
|
|
|
- * @param {object} opts
|
|
|
- */
|
|
|
- constructor (plugin, opts) {
|
|
|
- this.plugin = plugin
|
|
|
- this.provider = opts.provider
|
|
|
-
|
|
|
- // set default options
|
|
|
- const defaultOptions = {
|
|
|
- viewType: 'list',
|
|
|
- showTitles: true,
|
|
|
- showFilter: true,
|
|
|
- showBreadcrumbs: true
|
|
|
- }
|
|
|
-
|
|
|
- // merge default options with the ones set by user
|
|
|
- this.opts = { ...defaultOptions, ...opts }
|
|
|
-
|
|
|
- // Logic
|
|
|
- this.addFile = this.addFile.bind(this)
|
|
|
- this.filterItems = this.filterItems.bind(this)
|
|
|
- this.filterQuery = this.filterQuery.bind(this)
|
|
|
- this.toggleSearch = this.toggleSearch.bind(this)
|
|
|
- this.getFolder = this.getFolder.bind(this)
|
|
|
- this.getNextFolder = this.getNextFolder.bind(this)
|
|
|
- this.logout = this.logout.bind(this)
|
|
|
- this.preFirstRender = this.preFirstRender.bind(this)
|
|
|
- this.handleAuth = this.handleAuth.bind(this)
|
|
|
- this.sortByTitle = this.sortByTitle.bind(this)
|
|
|
- this.sortByDate = this.sortByDate.bind(this)
|
|
|
- this.isActiveRow = this.isActiveRow.bind(this)
|
|
|
- this.isChecked = this.isChecked.bind(this)
|
|
|
- this.toggleCheckbox = this.toggleCheckbox.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.render = this.render.bind(this)
|
|
|
-
|
|
|
- this.clearSelection()
|
|
|
-
|
|
|
- // Set default state for the plugin
|
|
|
- this.plugin.setPluginState({
|
|
|
- authenticated: false,
|
|
|
- files: [],
|
|
|
- folders: [],
|
|
|
- directories: [],
|
|
|
- activeRow: -1,
|
|
|
- filterInput: '',
|
|
|
- isSearchVisible: false
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- tearDown () {
|
|
|
- // Nothing.
|
|
|
- }
|
|
|
-
|
|
|
- _updateFilesAndFolders (res, files, folders) {
|
|
|
- this.nextPagePath = res.nextPagePath
|
|
|
- res.items.forEach((item) => {
|
|
|
- if (item.isFolder) {
|
|
|
- folders.push(item)
|
|
|
- } else {
|
|
|
- files.push(item)
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- this.plugin.setPluginState({ folders, files })
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 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
|
|
|
- *
|
|
|
- * @param {string} id Folder id
|
|
|
- * @returns {Promise} Folders/files in folder
|
|
|
- */
|
|
|
- getFolder (id, name) {
|
|
|
- return this._loaderWrapper(
|
|
|
- this.provider.list(id),
|
|
|
- (res) => {
|
|
|
- const folders = []
|
|
|
- const files = []
|
|
|
- let updatedDirectories
|
|
|
-
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
- const index = findIndex(state.directories, (dir) => id === dir.id)
|
|
|
-
|
|
|
- if (index !== -1) {
|
|
|
- updatedDirectories = state.directories.slice(0, index + 1)
|
|
|
- } else {
|
|
|
- updatedDirectories = state.directories.concat([{ id, title: name }])
|
|
|
- }
|
|
|
-
|
|
|
- this.username = res.username || this.username
|
|
|
- this._updateFilesAndFolders(res, files, folders)
|
|
|
- this.plugin.setPluginState({ directories: updatedDirectories })
|
|
|
- },
|
|
|
- this.handleError)
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Fetches new folder
|
|
|
- *
|
|
|
- * @param {object} folder
|
|
|
- * @param {string} title Folder title
|
|
|
- */
|
|
|
- getNextFolder (folder) {
|
|
|
- this.getFolder(folder.requestPath, folder.name)
|
|
|
- this.lastCheckbox = undefined
|
|
|
- }
|
|
|
-
|
|
|
- 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
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- removeFile (id) {
|
|
|
- const { currentSelection } = this.plugin.getPluginState()
|
|
|
- this.plugin.setPluginState({
|
|
|
- currentSelection: currentSelection.filter((file) => file.id !== id)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Removes session token on client side.
|
|
|
- */
|
|
|
- logout () {
|
|
|
- this.provider.logout()
|
|
|
- .then((res) => {
|
|
|
- if (res.ok) {
|
|
|
- if (!res.revoked) {
|
|
|
- const message = this.plugin.uppy.i18n('companionUnauthorizeHint', {
|
|
|
- provider: this.plugin.title,
|
|
|
- url: res.manual_revoke_url
|
|
|
- })
|
|
|
- this.plugin.uppy.info(message, 'info', 7000)
|
|
|
- }
|
|
|
-
|
|
|
- const newState = {
|
|
|
- authenticated: false,
|
|
|
- files: [],
|
|
|
- folders: [],
|
|
|
- directories: []
|
|
|
- }
|
|
|
- this.plugin.setPluginState(newState)
|
|
|
- }
|
|
|
- }).catch(this.handleError)
|
|
|
- }
|
|
|
-
|
|
|
- filterQuery (e) {
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
- this.plugin.setPluginState(Object.assign({}, state, {
|
|
|
- filterInput: e ? e.target.value : ''
|
|
|
- }))
|
|
|
- }
|
|
|
-
|
|
|
- toggleSearch (inputEl) {
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
-
|
|
|
- this.plugin.setPluginState({
|
|
|
- isSearchVisible: !state.isSearchVisible,
|
|
|
- filterInput: ''
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- filterItems (items) {
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
- if (!state.filterInput || state.filterInput === '') {
|
|
|
- return items
|
|
|
- }
|
|
|
- return items.filter((folder) => {
|
|
|
- return folder.name.toLowerCase().indexOf(state.filterInput.toLowerCase()) !== -1
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- sortByTitle () {
|
|
|
- const state = Object.assign({}, this.plugin.getPluginState())
|
|
|
- const { files, folders, sorting } = state
|
|
|
-
|
|
|
- const sortedFiles = files.sort((fileA, fileB) => {
|
|
|
- if (sorting === 'titleDescending') {
|
|
|
- return fileB.name.localeCompare(fileA.name)
|
|
|
- }
|
|
|
- return fileA.name.localeCompare(fileB.name)
|
|
|
- })
|
|
|
-
|
|
|
- const sortedFolders = folders.sort((folderA, folderB) => {
|
|
|
- if (sorting === 'titleDescending') {
|
|
|
- return folderB.name.localeCompare(folderA.name)
|
|
|
- }
|
|
|
- return folderA.name.localeCompare(folderB.name)
|
|
|
- })
|
|
|
-
|
|
|
- this.plugin.setPluginState(Object.assign({}, state, {
|
|
|
- files: sortedFiles,
|
|
|
- folders: sortedFolders,
|
|
|
- sorting: (sorting === 'titleDescending') ? 'titleAscending' : 'titleDescending'
|
|
|
- }))
|
|
|
- }
|
|
|
-
|
|
|
- sortByDate () {
|
|
|
- const state = Object.assign({}, this.plugin.getPluginState())
|
|
|
- const { files, folders, sorting } = state
|
|
|
-
|
|
|
- const sortedFiles = files.sort((fileA, fileB) => {
|
|
|
- const a = new Date(fileA.modifiedDate)
|
|
|
- const b = new Date(fileB.modifiedDate)
|
|
|
-
|
|
|
- if (sorting === 'dateDescending') {
|
|
|
- return a > b ? -1 : a < b ? 1 : 0
|
|
|
- }
|
|
|
- return a > b ? 1 : a < b ? -1 : 0
|
|
|
- })
|
|
|
-
|
|
|
- const sortedFolders = folders.sort((folderA, folderB) => {
|
|
|
- const a = new Date(folderA.modifiedDate)
|
|
|
- const b = new Date(folderB.modifiedDate)
|
|
|
-
|
|
|
- if (sorting === 'dateDescending') {
|
|
|
- return a > b ? -1 : a < b ? 1 : 0
|
|
|
- }
|
|
|
-
|
|
|
- return a > b ? 1 : a < b ? -1 : 0
|
|
|
- })
|
|
|
-
|
|
|
- this.plugin.setPluginState(Object.assign({}, state, {
|
|
|
- files: sortedFiles,
|
|
|
- folders: sortedFolders,
|
|
|
- sorting: (sorting === 'dateDescending') ? 'dateAscending' : 'dateDescending'
|
|
|
- }))
|
|
|
- }
|
|
|
-
|
|
|
- sortBySize () {
|
|
|
- const state = Object.assign({}, this.plugin.getPluginState())
|
|
|
- const { files, sorting } = state
|
|
|
-
|
|
|
- // check that plugin supports file sizes
|
|
|
- if (!files.length || !this.plugin.getItemData(files[0]).size) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- const sortedFiles = files.sort((fileA, fileB) => {
|
|
|
- const a = fileA.size
|
|
|
- const b = fileB.size
|
|
|
-
|
|
|
- if (sorting === 'sizeDescending') {
|
|
|
- return a > b ? -1 : a < b ? 1 : 0
|
|
|
- }
|
|
|
- return a > b ? 1 : a < b ? -1 : 0
|
|
|
- })
|
|
|
-
|
|
|
- this.plugin.setPluginState(Object.assign({}, state, {
|
|
|
- files: sortedFiles,
|
|
|
- sorting: (sorting === 'sizeDescending') ? 'sizeAscending' : 'sizeDescending'
|
|
|
- }))
|
|
|
- }
|
|
|
-
|
|
|
- isActiveRow (file) {
|
|
|
- return this.plugin.getPluginState().activeRow === this.plugin.getItemId(file)
|
|
|
- }
|
|
|
-
|
|
|
- isChecked (file) {
|
|
|
- const { currentSelection } = this.plugin.getPluginState()
|
|
|
- // comparing id instead of the file object, because the reference to the object
|
|
|
- // changes when we switch folders, and the file list is updated
|
|
|
- return currentSelection.some((item) => item.id === file.id)
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Adds all files found inside of specified folder.
|
|
|
- *
|
|
|
- * Uses separated state while folder contents are being fetched and
|
|
|
- * mantains list of selected folders, which are separated from files.
|
|
|
- */
|
|
|
- addFolder (folder) {
|
|
|
- const folderId = this.providerFileToId(folder)
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
- const folders = { ...state.selectedFolders }
|
|
|
- if (folderId in folders && folders[folderId].loading) {
|
|
|
- return
|
|
|
- }
|
|
|
- folders[folderId] = { loading: true, files: [] }
|
|
|
- this.plugin.setPluginState({ selectedFolders: { ...folders } })
|
|
|
- return this.listAllFiles(folder.requestPath).then((files) => {
|
|
|
- let count = 0
|
|
|
- files.forEach((file) => {
|
|
|
- const success = this.addFile(file)
|
|
|
- if (success) count++
|
|
|
- })
|
|
|
- const ids = files.map(this.providerFileToId)
|
|
|
- folders[folderId] = {
|
|
|
- loading: false,
|
|
|
- files: ids
|
|
|
- }
|
|
|
- this.plugin.setPluginState({ selectedFolders: folders })
|
|
|
-
|
|
|
- let message
|
|
|
- if (files.length) {
|
|
|
- message = this.plugin.uppy.i18n('folderAdded', {
|
|
|
- smart_count: count, folder: folder.name
|
|
|
- })
|
|
|
- } else {
|
|
|
- message = this.plugin.uppy.i18n('emptyFolderAdded')
|
|
|
- }
|
|
|
- this.plugin.uppy.info(message)
|
|
|
- }).catch((e) => {
|
|
|
- const state = this.plugin.getPluginState()
|
|
|
- const selectedFolders = { ...state.selectedFolders }
|
|
|
- delete selectedFolders[folderId]
|
|
|
- this.plugin.setPluginState({ selectedFolders })
|
|
|
- this.handleError(e)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Toggles file/folder checkbox to on/off state while updating files list.
|
|
|
- *
|
|
|
- * Note that some extra complexity comes from supporting shift+click to
|
|
|
- * toggle multiple checkboxes at once, which is done by getting all files
|
|
|
- * in between last checked file and current one.
|
|
|
- */
|
|
|
- toggleCheckbox (e, file) {
|
|
|
- e.stopPropagation()
|
|
|
- e.preventDefault()
|
|
|
- e.currentTarget.focus()
|
|
|
- const { folders, files } = this.plugin.getPluginState()
|
|
|
- const items = this.filterItems(folders.concat(files))
|
|
|
-
|
|
|
- // Shift-clicking selects a single consecutive list of items
|
|
|
- // starting at the previous click and deselects everything else.
|
|
|
- if (this.lastCheckbox && e.shiftKey) {
|
|
|
- let currentSelection
|
|
|
- const prevIndex = items.indexOf(this.lastCheckbox)
|
|
|
- const currentIndex = items.indexOf(file)
|
|
|
- if (prevIndex < currentIndex) {
|
|
|
- currentSelection = items.slice(prevIndex, currentIndex + 1)
|
|
|
- } else {
|
|
|
- currentSelection = items.slice(currentIndex, prevIndex + 1)
|
|
|
- }
|
|
|
- this.plugin.setPluginState({ currentSelection })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- this.lastCheckbox = file
|
|
|
- const { currentSelection } = this.plugin.getPluginState()
|
|
|
- if (this.isChecked(file)) {
|
|
|
- this.plugin.setPluginState({
|
|
|
- currentSelection: currentSelection.filter((item) => item.id !== file.id)
|
|
|
- })
|
|
|
- } else {
|
|
|
- this.plugin.setPluginState({
|
|
|
- currentSelection: currentSelection.concat([file])
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- providerFileToId (file) {
|
|
|
- return generateFileID({
|
|
|
- data: file,
|
|
|
- name: file.name || file.id,
|
|
|
- type: file.mimeType
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- handleAuth () {
|
|
|
- const authState = btoa(JSON.stringify({ origin: getOrigin() }))
|
|
|
- const clientVersion = encodeURIComponent(`@uppy/provider-views=${ProviderView.VERSION}`)
|
|
|
- const link = `${this.provider.authUrl()}?state=${authState}&uppyVersions=${clientVersion}`
|
|
|
-
|
|
|
- const authWindow = window.open(link, '_blank')
|
|
|
- const handleToken = (e) => {
|
|
|
- if (!this._isOriginAllowed(e.origin, this.plugin.opts.companionAllowedHosts) || e.source !== authWindow) {
|
|
|
- this.plugin.uppy.log(`rejecting event from ${e.origin} vs allowed pattern ${this.plugin.opts.companionAllowedHosts}`)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // Check if it's a string before doing the JSON.parse to maintain support
|
|
|
- // for older Companion versions that used object references
|
|
|
- const data = typeof e.data === 'string' ? JSON.parse(e.data) : e.data
|
|
|
-
|
|
|
- if (!data.token) {
|
|
|
- this.plugin.uppy.log('did not receive token from auth window')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- authWindow.close()
|
|
|
- window.removeEventListener('message', handleToken)
|
|
|
- this.provider.setAuthToken(data.token)
|
|
|
- this.preFirstRender()
|
|
|
- }
|
|
|
- window.addEventListener('message', handleToken)
|
|
|
- }
|
|
|
-
|
|
|
- _isOriginAllowed (origin, allowedOrigin) {
|
|
|
- const getRegex = (value) => {
|
|
|
- if (typeof value === 'string') {
|
|
|
- return new RegExp(`^${value}$`)
|
|
|
- } else if (value instanceof RegExp) {
|
|
|
- return value
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const patterns = Array.isArray(allowedOrigin) ? allowedOrigin.map(getRegex) : [getRegex(allowedOrigin)]
|
|
|
- return patterns
|
|
|
- .filter((pattern) => pattern != null) // loose comparison to catch undefined
|
|
|
- .some((pattern) => pattern.test(origin) || pattern.test(`${origin}/`)) // allowing for trailing '/'
|
|
|
- }
|
|
|
-
|
|
|
- handleError (error) {
|
|
|
- const uppy = this.plugin.uppy
|
|
|
- uppy.log(error.toString())
|
|
|
- if (error.isAuthError) {
|
|
|
- return
|
|
|
- }
|
|
|
- const message = uppy.i18n('companionError')
|
|
|
- uppy.info({ message: 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 && !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
|
|
|
-
|
|
|
- this._isHandlingScroll = true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- listAllFiles (path, files = null) {
|
|
|
- files = files || []
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- this.provider.list(path).then((res) => {
|
|
|
- res.items.forEach((item) => {
|
|
|
- if (!item.isFolder) {
|
|
|
- files.push(item)
|
|
|
- } else {
|
|
|
- this.addFolder(item)
|
|
|
- }
|
|
|
- })
|
|
|
- const moreFiles = res.nextPagePath || null
|
|
|
- if (moreFiles) {
|
|
|
- return this.listAllFiles(moreFiles, files)
|
|
|
- .then((files) => resolve(files))
|
|
|
- .catch(e => reject(e))
|
|
|
- } else {
|
|
|
- return resolve(files)
|
|
|
- }
|
|
|
- }).catch(e => reject(e))
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- donePicking () {
|
|
|
- const { currentSelection } = this.plugin.getPluginState()
|
|
|
- const promises = currentSelection.map((file) => {
|
|
|
- if (file.isFolder) {
|
|
|
- return this.addFolder(file)
|
|
|
- } else {
|
|
|
- return this.addFile(file)
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- this._loaderWrapper(Promise.all(promises), () => {
|
|
|
- this.clearSelection()
|
|
|
- }, () => {})
|
|
|
- }
|
|
|
-
|
|
|
- cancelPicking () {
|
|
|
- this.clearSelection()
|
|
|
-
|
|
|
- const dashboard = this.plugin.uppy.getPlugin('Dashboard')
|
|
|
- if (dashboard) dashboard.hideAllPanels()
|
|
|
- }
|
|
|
-
|
|
|
- clearSelection () {
|
|
|
- this.plugin.setPluginState({ currentSelection: [] })
|
|
|
- }
|
|
|
-
|
|
|
- // displays loader view while asynchronous request is being made.
|
|
|
- _loaderWrapper (promise, then, catch_) {
|
|
|
- promise
|
|
|
- .then((result) => {
|
|
|
- this.plugin.setPluginState({ loading: false })
|
|
|
- then(result)
|
|
|
- }).catch((err) => {
|
|
|
- this.plugin.setPluginState({ loading: false })
|
|
|
- catch_(err)
|
|
|
- })
|
|
|
- this.plugin.setPluginState({ loading: true })
|
|
|
- }
|
|
|
-
|
|
|
- render (state, viewOptions = {}) {
|
|
|
- const { authenticated, didFirstRender } = this.plugin.getPluginState()
|
|
|
- if (!didFirstRender) {
|
|
|
- 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 browserProps = Object.assign({}, this.plugin.getPluginState(), {
|
|
|
- username: this.username,
|
|
|
- getNextFolder: this.getNextFolder,
|
|
|
- getFolder: this.getFolder,
|
|
|
- filterItems: this.filterItems,
|
|
|
- filterQuery: this.filterQuery,
|
|
|
- toggleSearch: this.toggleSearch,
|
|
|
- sortByTitle: this.sortByTitle,
|
|
|
- sortByDate: this.sortByDate,
|
|
|
- logout: this.logout,
|
|
|
- isActiveRow: this.isActiveRow,
|
|
|
- isChecked: this.isChecked,
|
|
|
- toggleCheckbox: this.toggleCheckbox,
|
|
|
- handleScroll: this.handleScroll,
|
|
|
- listAllFiles: this.listAllFiles,
|
|
|
- done: this.donePicking,
|
|
|
- cancel: this.cancelPicking,
|
|
|
- title: this.plugin.title,
|
|
|
- viewType: targetViewOptions.viewType,
|
|
|
- showTitles: targetViewOptions.showTitles,
|
|
|
- showFilter: targetViewOptions.showFilter,
|
|
|
- showBreadcrumbs: targetViewOptions.showBreadcrumbs,
|
|
|
- pluginIcon: this.plugin.icon,
|
|
|
- i18n: this.plugin.uppy.i18n
|
|
|
- })
|
|
|
-
|
|
|
- return (
|
|
|
- <CloseWrapper onUnmount={this.clearSelection}>
|
|
|
- <Browser {...browserProps} />
|
|
|
- </CloseWrapper>
|
|
|
- )
|
|
|
- }
|
|
|
+module.exports = {
|
|
|
+ ProviderViews,
|
|
|
+ SearchProviderViews
|
|
|
}
|