diff --git a/webmaker/src/components/SavedItemPane.jsx b/webmaker/src/components/SavedItemPane.jsx index a722730..bcbb240 100644 --- a/webmaker/src/components/SavedItemPane.jsx +++ b/webmaker/src/components/SavedItemPane.jsx @@ -1,5 +1,8 @@ import { h, Component } from 'preact'; import { getHumanDate } from '../utils'; +import { trackEvent } from '../analytics'; +import { itemService } from '../itemService'; +import { alertsService } from '../notifications'; export default class SavedItemPane extends Component { onCloseIntent() { @@ -62,6 +65,88 @@ export default class SavedItemPane extends Component { } } + mergeImportedItems(items) { + var existingItemIds = []; + var toMergeItems = {}; + const d = deferred(); + const savedItems = {}; + this.items.forEach(item => (savedItems[item.id] = item)); + items.forEach(item => { + // We can access `savedItems` here because this gets set when user + // opens the saved creations panel. And import option is available + // inside the saved items panel. + if (savedItems[item.id]) { + // Item already exists + existingItemIds.push(item.id); + } else { + log('merging', item.id); + toMergeItems[item.id] = item; + } + }); + var mergedItemCount = items.length - existingItemIds.length; + if (existingItemIds.length) { + var shouldReplace = confirm( + existingItemIds.length + + ' creations already exist. Do you want to replace them?' + ); + if (shouldReplace) { + log('shouldreplace', shouldReplace); + items.forEach(item => { + toMergeItems[item.id] = item; + }); + mergedItemCount = items.length; + } + } + if (mergedItemCount) { + itemService.saveItems(toMergeItems).then(() => { + d.resolve(); + alertsService.add( + mergedItemCount + ' creations imported successfully.' + ); + trackEvent('fn', 'itemsImported', mergedItemCount); + }); + } else { + d.resolve(); + } + // FIXME: Move from here + // toggleSavedItemsPane(false); + + return d.promise; + } + + importFileChangeHandler(e) { + var file = e.target.files[0]; + + var reader = new FileReader(); + reader.addEventListener('load', progressEvent => { + var items; + try { + items = JSON.parse(progressEvent.target.result); + log(items); + this.mergeImportedItems(items); + } catch (exception) { + log(exception); + alert( + 'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.' + ); + } + }); + + reader.readAsText(file, 'utf-8'); + } + + importBtnClickHandler(e) { + var input = document.createElement('input'); + input.type = 'file'; + input.style.display = 'none'; + input.accept = 'accept="application/json'; + document.body.appendChild(input); + input.addEventListener('change', this.importFileChangeHandler.bind(this)); + input.click(); + trackEvent('ui', 'importBtnClicked'); + e.preventDefault(); + } + render() { return (
{ + this.fetchItems().then(items => { + var d = new Date(); + var fileName = [ + 'web-maker-export', + d.getFullYear(), + d.getMonth() + 1, + d.getDate(), + d.getHours(), + d.getMinutes(), + d.getSeconds() + ].join('-'); + fileName += '.json'; + var blob = new Blob([JSON.stringify(items, false, 2)], { + type: 'application/json;charset=UTF-8' + }); + + downloadFile(fileName, blob); + + trackEvent('fn', 'exportItems'); + }); + }); + } + exportBtnClickHandler(e) { + this.exportItems(); + e.preventDefault(); + trackEvent('ui', 'exportBtnClicked'); + } render() { return ( @@ -874,6 +910,7 @@ export default class App extends Component { itemClickHandler={this.itemClickHandler.bind(this)} itemRemoveBtnClickHandler={this.itemRemoveBtnClickHandler.bind(this)} itemForkBtnClickHandler={this.itemForkBtnClickHandler.bind(this)} + exportBtnClickHandler={this.exportBtnClickHandler.bind(this)} />
{}