UNPKG

@uppy/provider-views

Version:

View library for Uppy remote provider plugins.

187 lines (186 loc) 8.58 kB
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime"; import { remoteFileObjToLocal } from '@uppy/utils'; import classNames from 'classnames'; import packageJson from '../../package.json' with { type: 'json' }; import Browser from '../Browser.js'; import FooterActions from '../FooterActions.js'; import SearchInput from '../SearchInput.js'; import addFiles from '../utils/addFiles.js'; import getClickedRange from '../utils/getClickedRange.js'; import handleError from '../utils/handleError.js'; import getCheckedFilesWithPaths from '../utils/PartialTreeUtils/getCheckedFilesWithPaths.js'; import PartialTreeUtils from '../utils/PartialTreeUtils/index.js'; import shouldHandleScroll from '../utils/shouldHandleScroll.js'; const defaultState = { loading: false, searchString: '', partialTree: [ { type: 'root', id: null, cached: false, nextPagePath: null, }, ], currentFolderId: null, isInputMode: true, }; const defaultOptions = { viewType: 'grid', showTitles: true, showFilter: true, utmSource: 'Companion', }; /** * SearchProviderView, used for Unsplash and future image search providers. * Extends generic View, shared with regular providers like Google Drive and Instagram. */ export default class SearchProviderView { static VERSION = packageJson.version; plugin; provider; opts; isHandlingScroll = false; lastCheckbox = null; constructor(plugin, opts) { this.plugin = plugin; this.provider = opts.provider; this.opts = { ...defaultOptions, ...opts }; this.setSearchString = this.setSearchString.bind(this); this.search = this.search.bind(this); this.resetPluginState = this.resetPluginState.bind(this); this.handleScroll = this.handleScroll.bind(this); this.donePicking = this.donePicking.bind(this); this.cancelSelection = this.cancelSelection.bind(this); this.toggleCheckbox = this.toggleCheckbox.bind(this); this.render = this.render.bind(this); // Set default state for the plugin this.resetPluginState(); // @ts-expect-error this should be typed in @uppy/dashboard. this.plugin.uppy.on('dashboard:close-panel', this.resetPluginState); this.plugin.uppy.registerRequestClient(this.provider.provider, this.provider); } tearDown() { // Nothing. } setLoading(loading) { this.plugin.setPluginState({ loading }); } resetPluginState() { this.plugin.setPluginState(defaultState); } cancelSelection() { const { partialTree } = this.plugin.getPluginState(); const newPartialTree = partialTree.map((item) => item.type === 'root' ? item : { ...item, status: 'unchecked' }); this.plugin.setPluginState({ partialTree: newPartialTree }); } async search() { const { searchString } = this.plugin.getPluginState(); if (searchString === '') return; this.setLoading(true); try { const response = await this.provider.search(searchString); const newPartialTree = [ { type: 'root', id: null, cached: false, nextPagePath: response.nextPageQuery, }, ...response.items.map((item) => ({ type: 'file', id: item.requestPath, status: 'unchecked', parentId: null, data: item, })), ]; this.plugin.setPluginState({ partialTree: newPartialTree, isInputMode: false, }); } catch (error) { handleError(this.plugin.uppy)(error); } this.setLoading(false); } async handleScroll(event) { const { partialTree, searchString } = this.plugin.getPluginState(); const root = partialTree.find((i) => i.type === 'root'); if (shouldHandleScroll(event) && !this.isHandlingScroll && root.nextPagePath) { this.isHandlingScroll = true; try { const response = await this.provider.search(searchString, root.nextPagePath); const newRoot = { ...root, nextPagePath: response.nextPageQuery, }; const oldItems = partialTree.filter((i) => i.type !== 'root'); const newPartialTree = [ newRoot, ...oldItems, ...response.items.map((item) => ({ type: 'file', id: item.requestPath, status: 'unchecked', parentId: null, data: item, })), ]; this.plugin.setPluginState({ partialTree: newPartialTree }); } catch (error) { handleError(this.plugin.uppy)(error); } this.isHandlingScroll = false; } } async donePicking() { const { partialTree } = this.plugin.getPluginState(); // 1. Add files const companionFiles = getCheckedFilesWithPaths(partialTree); addFiles(companionFiles, this.plugin, this.provider); // 2. Reset state this.resetPluginState(); } toggleCheckbox(ourItem, isShiftKeyPressed) { const { partialTree } = this.plugin.getPluginState(); const clickedRange = getClickedRange(ourItem.id, this.getDisplayedPartialTree(), isShiftKeyPressed, this.lastCheckbox); const newPartialTree = PartialTreeUtils.afterToggleCheckbox(partialTree, clickedRange); this.plugin.setPluginState({ partialTree: newPartialTree }); this.lastCheckbox = ourItem.id; } validateSingleFile = (file) => { const companionFile = remoteFileObjToLocal(file); const result = this.plugin.uppy.validateSingleFile(companionFile); return result; }; getDisplayedPartialTree = () => { const { partialTree } = this.plugin.getPluginState(); return partialTree.filter((item) => item.type !== 'root'); }; setSearchString = (searchString) => { this.plugin.setPluginState({ searchString }); if (searchString === '') { this.plugin.setPluginState({ partialTree: [] }); } }; validateAggregateRestrictions = (partialTree) => { const checkedFiles = partialTree.filter((item) => item.type === 'file' && item.status === 'checked'); const uppyFiles = checkedFiles.map((file) => file.data); return this.plugin.uppy.validateAggregateRestrictions(uppyFiles); }; render(state, viewOptions = {}) { const { isInputMode, searchString, loading, partialTree } = this.plugin.getPluginState(); const { i18n } = this.plugin.uppy; const opts = { ...this.opts, ...viewOptions }; if (isInputMode) { return (_jsx(SearchInput, { searchString: searchString, setSearchString: this.setSearchString, submitSearchString: this.search, inputLabel: i18n('enterTextToSearch'), buttonLabel: i18n('searchImages'), wrapperClassName: "uppy-SearchProvider", inputClassName: "uppy-c-textInput uppy-SearchProvider-input", showButton: true, buttonCSSClassName: "uppy-SearchProvider-searchButton" })); } return (_jsxs("div", { className: classNames('uppy-ProviderBrowser', `uppy-ProviderBrowser-viewType--${opts.viewType}`), children: [opts.showFilter && (_jsx(SearchInput, { searchString: searchString, setSearchString: this.setSearchString, submitSearchString: this.search, inputLabel: i18n('search'), clearSearchLabel: i18n('resetSearch'), wrapperClassName: "uppy-ProviderBrowser-searchFilter", inputClassName: "uppy-ProviderBrowser-searchFilterInput" })), _jsx(Browser, { toggleCheckbox: this.toggleCheckbox, displayedPartialTree: this.getDisplayedPartialTree(), handleScroll: this.handleScroll, openFolder: async () => { }, noResultsLabel: i18n('noSearchResults'), viewType: opts.viewType, showTitles: opts.showTitles, isLoading: loading, i18n: i18n, virtualList: false, utmSource: this.opts.utmSource }), _jsx(FooterActions, { partialTree: partialTree, donePicking: this.donePicking, cancelSelection: this.cancelSelection, i18n: i18n, validateAggregateRestrictions: this.validateAggregateRestrictions })] })); } }