mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-27 08:40:10 +02:00
port import export
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import { h, Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import { getHumanDate } from '../utils';
|
import { getHumanDate } from '../utils';
|
||||||
|
import { trackEvent } from '../analytics';
|
||||||
|
import { itemService } from '../itemService';
|
||||||
|
import { alertsService } from '../notifications';
|
||||||
|
|
||||||
export default class SavedItemPane extends Component {
|
export default class SavedItemPane extends Component {
|
||||||
onCloseIntent() {
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -86,7 +171,7 @@ export default class SavedItemPane extends Component {
|
|||||||
|
|
||||||
<div class="main-header__btn-wrap">
|
<div class="main-header__btn-wrap">
|
||||||
<a
|
<a
|
||||||
d-click="exportItems"
|
onClick={this.props.exportBtnClickHandler}
|
||||||
href=""
|
href=""
|
||||||
class="btn btn-icon hint--bottom-left hint--rounded hint--medium"
|
class="btn btn-icon hint--bottom-left hint--rounded hint--medium"
|
||||||
aria-label="Export all your creations into a single importable file."
|
aria-label="Export all your creations into a single importable file."
|
||||||
@@ -94,7 +179,7 @@ export default class SavedItemPane extends Component {
|
|||||||
Export
|
Export
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
d-click="onImportBtnClicked"
|
onClick={this.importBtnClickHandler.bind(this)}
|
||||||
href=""
|
href=""
|
||||||
class="btn btn-icon hint--bottom-left hint--rounded hint--medium"
|
class="btn btn-icon hint--bottom-left hint--rounded hint--medium"
|
||||||
aria-label="Only the file that you export through the 'Export' button can be imported."
|
aria-label="Only the file that you export through the 'Export' button can be imported."
|
||||||
|
@@ -9,7 +9,14 @@ import AddLibrary from './AddLibrary.jsx';
|
|||||||
import Modal from './Modal.jsx';
|
import Modal from './Modal.jsx';
|
||||||
import HelpModal from './HelpModal.jsx';
|
import HelpModal from './HelpModal.jsx';
|
||||||
import Login from './Login.jsx';
|
import Login from './Login.jsx';
|
||||||
import { log, generateRandomId, semverCompare, saveAsHtml } from '../utils';
|
import {
|
||||||
|
log,
|
||||||
|
generateRandomId,
|
||||||
|
semverCompare,
|
||||||
|
saveAsHtml,
|
||||||
|
handleDownloadsPermission,
|
||||||
|
downloadFile
|
||||||
|
} from '../utils';
|
||||||
import { itemService } from '../itemService';
|
import { itemService } from '../itemService';
|
||||||
import '../db';
|
import '../db';
|
||||||
import Notifications from './Notifications';
|
import Notifications from './Notifications';
|
||||||
@@ -811,6 +818,35 @@ export default class App extends Component {
|
|||||||
this.contentWrap.setPreviewContent(true, true);
|
this.contentWrap.setPreviewContent(true, true);
|
||||||
trackEvent('ui', 'runBtnClick');
|
trackEvent('ui', 'runBtnClick');
|
||||||
}
|
}
|
||||||
|
exportItems() {
|
||||||
|
handleDownloadsPermission().then(() => {
|
||||||
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@@ -874,6 +910,7 @@ export default class App extends Component {
|
|||||||
itemClickHandler={this.itemClickHandler.bind(this)}
|
itemClickHandler={this.itemClickHandler.bind(this)}
|
||||||
itemRemoveBtnClickHandler={this.itemRemoveBtnClickHandler.bind(this)}
|
itemRemoveBtnClickHandler={this.itemRemoveBtnClickHandler.bind(this)}
|
||||||
itemForkBtnClickHandler={this.itemForkBtnClickHandler.bind(this)}
|
itemForkBtnClickHandler={this.itemForkBtnClickHandler.bind(this)}
|
||||||
|
exportBtnClickHandler={this.exportBtnClickHandler.bind(this)}
|
||||||
/>
|
/>
|
||||||
<div class="alerts-container" id="js-alerts-container" />
|
<div class="alerts-container" id="js-alerts-container" />
|
||||||
<form
|
<form
|
||||||
|
@@ -403,6 +403,37 @@ export function saveAsHtml(item) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function handleDownloadsPermission() {
|
||||||
|
var d = deferred();
|
||||||
|
if (!window.IS_EXTENSION) {
|
||||||
|
d.resolve();
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
chrome.permissions.contains({
|
||||||
|
permissions: ['downloads']
|
||||||
|
},
|
||||||
|
function (result) {
|
||||||
|
if (result) {
|
||||||
|
d.resolve();
|
||||||
|
} else {
|
||||||
|
chrome.permissions.request({
|
||||||
|
permissions: ['downloads']
|
||||||
|
},
|
||||||
|
function (granted) {
|
||||||
|
if (granted) {
|
||||||
|
trackEvent('fn', 'downloadsPermGiven');
|
||||||
|
d.resolve();
|
||||||
|
} else {
|
||||||
|
d.reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
|
||||||
window.chrome = window.chrome || {};
|
window.chrome = window.chrome || {};
|
||||||
window.chrome.i18n = {
|
window.chrome.i18n = {
|
||||||
getMessage: () => {}
|
getMessage: () => {}
|
||||||
|
Reference in New Issue
Block a user