UNPKG

aws-amplify-react

Version:

AWS Amplify is a JavaScript library for Frontend and mobile developers building cloud-enabled applications.

262 lines (223 loc) • 8.63 kB
/* * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ import * as React from 'react'; import { Component } from 'react'; import { JS, ConsoleLogger as Logger, Hub } from '@aws-amplify/core'; import Storage from '@aws-amplify/storage'; import Picker from '../Widget/Picker'; import AmplifyTheme from '../AmplifyTheme'; import S3Image from './S3Image'; import S3Text from './S3Text'; import { calcKey } from './Common'; const logger = new Logger('Storage.S3Album'); export default class S3Album extends Component { constructor(props) { super(props); this.handlePick = this.handlePick.bind(this); this.handleClick = this.handleClick.bind(this); this.list = this.list.bind(this); this.marshal = this.marshal.bind(this); const theme = this.props.theme || AmplifyTheme; this.state = { theme, items: [], ts: new Date().getTime() }; Hub.listen('window', this, 'S3Album'); } getKey(file) { const { fileToKey } = this.props; const { name, size, type } = file; let key = encodeURI(name); if (fileToKey) { const callback_type = typeof fileToKey; if (callback_type === 'string') { key = fileToKey; } else if (callback_type === 'function') { key = fileToKey({ name, size, type }); } else { key = encodeURI(JSON.stringify(fileToKey)); } if (!key) { logger.debug('key is empty'); key = 'empty_key'; } } return key.replace(/\s/g, '_'); } handlePick(data) { const { onPick, onLoad, onError, track, level } = this.props; if (onPick) { onPick(data); } const path = this.props.path || ''; const { file, name, size, type } = data; const key = path + this.getKey(data); if (!Storage || typeof Storage.put !== 'function') { throw new Error('No Storage module found, please ensure @aws-amplify/storage is imported'); } Storage.put(key, file, { level: level? level: 'public', contentType: type, track }) .then(data => { logger.debug('handle pick data', data); const { items } = this.state; if (items.filter(item => item.key === key).length === 0) { const list = items.concat(data); this.marshal(list); } else { logger.debug('update an item'); } if (onLoad) { onLoad(data); } }) .catch(err => { logger.debug('handle pick error', err); if (onError) { onError(err); } }); this.setState({ ts: new Date().getTime() }); } handleClick(item) { const { onClickItem, select, onSelect } = this.props; if (onClickItem) { onClickItem(item); } if (!select) { return; } item.selected = !item.selected; this.setState({ items: this.state.items.slice() }); if (!onSelect) { return; } const selected_items = this.state.items.filter(item => item.selected); onSelect(item, selected_items); } onHubCapsule(capsule) { const theme = this.props.theme || AmplifyTheme; this.setState({ theme: Object.assign({}, theme) }); } componentDidMount() { this.list(); } componentDidUpdate(prevProps, prevState) { if (this.props.path === prevProps.path && this.props.ts === prevProps.ts && this.props.select === prevProps.select ) { return; } if (!this.props.select) { this.state.items.forEach(item => item.selected = false); } if (this.props.onSelect) { this.props.onSelect(null, []); } this.list(); } list() { const { path, level, track, identityId } = this.props; logger.debug('Album path: ' + path); if (!Storage || typeof Storage.list !== 'function') { throw new Error('No Storage module found, please ensure @aws-amplify/storage is imported'); } return Storage.list(path, { level: level? level : 'public', track, identityId }) .then(data => { logger.debug('album list', data); this.marshal(data); }) .catch(err => { logger.warn(err); return []; }); } contentType(item) { return JS.filenameToContentType(item.key, 'image/*'); } marshal(list) { const contentType = this.props.contentType || ''; list.forEach(item => { if (item.contentType) { return; } const isString = typeof contentType === 'string'; item.contentType = isString? contentType : contentType(item); if (!item.contentType) { item.contentType = this.contentType(item); } }); let items = this.filter(list); items = this.sort(items); this.setState({ items }); } filter(list) { const { filter } = this.props; return filter? filter(list) : list; } sort(list) { const { sort } = this.props; const typeof_sort = typeof sort; if (typeof_sort === 'function') { return sort(list); } if (['string', 'undefined'].includes(typeof_sort)) { const sort_str = sort? sort : 'lastModified'; const parts = sort_str.split(/\s+/); const field = parts[0]; let dir = parts.length > 1? parts[1] : ''; if (field === 'lastModified') { dir = (dir === 'asc')? 'asc' : 'desc'; } else { dir = (dir === 'desc')? 'desc' : 'asc'; } JS.sortByField(list, field, dir); return list; } logger.warn('invalid sort. done nothing. should be a string or function'); return list; } render() { const { picker, translateItem, level, identityId } = this.props; const { items, ts } = this.state; const pickerTitle = this.props.pickerTitle || 'Pick'; const theme = this.props.theme || AmplifyTheme; const list = items.map(item => { const isText = item.contentType && JS.isTextFile(item.contentType); return isText ? <S3Text key={item.key} textKey={item.key} theme={theme} style={theme.albumText} selected={item.selected} translate={translateItem} level={level} identityId={identityId} onClick={() => this.handleClick(item)} /> : <S3Image key={item.key} imgKey={item.key} theme={theme} style={theme.albumPhoto} selected={item.selected} translate={translateItem} level={level} identityId={identityId} onClick={() => this.handleClick(item)} />; }); return ( <div> <div style={theme.album}> {list} </div> { picker? <Picker key={ts} title={pickerTitle} accept="image/*, text/*" onPick={this.handlePick} theme={theme} /> : null } </div> ); } }