mirror of
https://github.com/chinchang/web-maker.git
synced 2025-04-07 20:32:31 +02:00
removeitem, filtering items, infiniteloop warning ported
This commit is contained in:
parent
80621132a1
commit
3518484568
@ -22,11 +22,11 @@ export default class AskToImportModal extends Component {
|
||||
them anytime on this browser.
|
||||
</p>
|
||||
<div class="flex flex-h-end">
|
||||
<button d-click="dontAskToImportAnymore" class="btn">
|
||||
<button onClick={this.props.dontAskBtnClickHandler} class="btn">
|
||||
Don't ask me again
|
||||
</button>
|
||||
<button
|
||||
d-click="importCreationsAndSettingsIntoApp"
|
||||
onClick={this.props.importBtnClickHandler}
|
||||
class="btn btn--primary ml-1"
|
||||
>
|
||||
Yes, please import
|
||||
|
@ -17,7 +17,8 @@ export default class ContentWrap extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isConsoleOpen: false
|
||||
isConsoleOpen: false,
|
||||
isCssSettingsModalOpen: false
|
||||
};
|
||||
this.updateTimer = null;
|
||||
this.updateDelay = 500;
|
||||
@ -33,6 +34,7 @@ export default class ContentWrap extends Component {
|
||||
|
||||
window.onMessageFromConsole = this.onMessageFromConsole.bind(this);
|
||||
|
||||
window.previewException = this.previewException.bind(this);
|
||||
// `clearConsole` is on window because it gets called from inside iframe also.
|
||||
window.clearConsole = this.clearConsole.bind(this);
|
||||
}
|
||||
@ -285,14 +287,13 @@ export default class ContentWrap extends Component {
|
||||
if (!this.cm) {
|
||||
return;
|
||||
}
|
||||
$('#js-html-code').querySelector('.CodeMirror').style.fontSize = $(
|
||||
'#js-css-code'
|
||||
).querySelector('.CodeMirror').style.fontSize = $(
|
||||
'#js-js-code'
|
||||
).querySelector('.CodeMirror').style.fontSize = `${parseInt(
|
||||
prefs.fontSize,
|
||||
10
|
||||
)}px`;
|
||||
htmlCodeEl.querySelector(
|
||||
'.CodeMirror'
|
||||
).style.fontSize = cssCodeEl.querySelector(
|
||||
'.CodeMirror'
|
||||
).style.fontSize = jsCodeEl.querySelector(
|
||||
'.CodeMirror'
|
||||
).style.fontSize = `${parseInt(prefs.fontSize, 10)}px`;
|
||||
window.consoleEl.querySelector('.CodeMirror').style.fontSize = `${parseInt(
|
||||
prefs.fontSize,
|
||||
10
|
||||
@ -350,10 +351,11 @@ export default class ContentWrap extends Component {
|
||||
updateCodeWrapCollapseStates() {
|
||||
// This is debounced!
|
||||
clearTimeout(this.updateCodeWrapCollapseStates.timeout);
|
||||
updateCodeWrapCollapseStates.timeout = setTimeout(function() {
|
||||
this.updateCodeWrapCollapseStates.timeout = setTimeout(() => {
|
||||
const { currentLayoutMode } = this.props;
|
||||
const prop =
|
||||
currentLayoutMode === 2 || currentLayoutMode === 5 ? 'width' : 'height';
|
||||
[htmlCode, cssCode, jsCode].forEach(function(el) {
|
||||
[htmlCodeEl, cssCodeEl, jsCodeEl].forEach(function(el) {
|
||||
const bounds = el.getBoundingClientRect();
|
||||
const size = bounds[prop];
|
||||
if (size < 100) {
|
||||
@ -617,6 +619,11 @@ export default class ContentWrap extends Component {
|
||||
/* eslint-enable no-param-reassign */
|
||||
}
|
||||
|
||||
previewException(error) {
|
||||
console.error('Possible infinite loop detected.', error.stack);
|
||||
this.onMessageFromConsole('Possible infinite loop detected.', error.stack);
|
||||
}
|
||||
|
||||
toggleConsole() {
|
||||
this.setState({ isConsoleOpen: !this.state.isConsoleOpen });
|
||||
trackEvent('ui', 'consoleToggle');
|
||||
@ -690,14 +697,15 @@ export default class ContentWrap extends Component {
|
||||
: 'vertical'
|
||||
}
|
||||
onDragStart={this.codeSplitDragStart.bind(this)}
|
||||
onDragend={this.codeSplitDragEnd.bind(this)}
|
||||
onDragEnd={this.codeSplitDragEnd.bind(this)}
|
||||
onSplit={splitInstance => (this.codeSplitInstance = splitInstance)}
|
||||
>
|
||||
<div
|
||||
data-code-wrap-id="0"
|
||||
id="js-html-code"
|
||||
id="htmlCodeEl"
|
||||
data-type="html"
|
||||
class="code-wrap"
|
||||
onTransitionEnd={this.updateCodeWrapCollapseStates.bind(this)}
|
||||
>
|
||||
<div
|
||||
class="js-code-wrap__header code-wrap__header"
|
||||
@ -742,9 +750,10 @@ export default class ContentWrap extends Component {
|
||||
</div>
|
||||
<div
|
||||
data-code-wrap-id="1"
|
||||
id="js-css-code"
|
||||
id="cssCodeEl"
|
||||
data-type="css"
|
||||
class="code-wrap"
|
||||
onTransitionEnd={this.updateCodeWrapCollapseStates.bind(this)}
|
||||
>
|
||||
<div
|
||||
class="js-code-wrap__header code-wrap__header"
|
||||
@ -804,9 +813,10 @@ export default class ContentWrap extends Component {
|
||||
</div>
|
||||
<div
|
||||
data-code-wrap-id="2"
|
||||
id="js-js-code"
|
||||
id="jsCodeEl"
|
||||
data-type="js"
|
||||
class="code-wrap"
|
||||
onTransitionEnd={this.updateCodeWrapCollapseStates.bind(this)}
|
||||
>
|
||||
<div
|
||||
class="js-code-wrap__header code-wrap__header"
|
||||
|
@ -5,6 +5,24 @@ import { itemService } from '../itemService';
|
||||
import { alertsService } from '../notifications';
|
||||
|
||||
export default class SavedItemPane extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.items = [];
|
||||
this.state = {
|
||||
filteredItems: []
|
||||
};
|
||||
}
|
||||
componentWillUpdate(nextProps) {
|
||||
if (this.props.items !== nextProps.items) {
|
||||
this.items = Object.values(nextProps.items);
|
||||
this.items.sort(function(a, b) {
|
||||
return b.updatedOn - a.updatedOn;
|
||||
});
|
||||
this.setState({
|
||||
filteredItems: this.items
|
||||
});
|
||||
}
|
||||
}
|
||||
onCloseIntent() {
|
||||
this.props.closeHandler();
|
||||
}
|
||||
@ -48,18 +66,15 @@ export default class SavedItemPane extends Component {
|
||||
}
|
||||
|
||||
if (isEnterKeyPressed && selectedItemElement) {
|
||||
const item = this.props.items.filter(
|
||||
item => (item.id = selectedItemElement.dataset.itemId)
|
||||
)[0];
|
||||
const item = this.props.items[selectedItemElement.dataset.itemId];
|
||||
console.log('opening', item);
|
||||
this.props.itemClickHandler(item);
|
||||
}
|
||||
|
||||
// Fork shortcut inside saved creations panel with Ctrl/⌘ + F
|
||||
if (isForkKeyPressed) {
|
||||
event.preventDefault();
|
||||
const item = this.props.items.filter(
|
||||
item => (item.id = selectedItemElement.dataset.itemId)
|
||||
)[0];
|
||||
const item = this.props.items[selectedItemElement.dataset.itemId];
|
||||
this.props.itemForkBtnClickHandler(item);
|
||||
trackEvent('ui', 'forkKeyboardShortcut');
|
||||
}
|
||||
@ -147,6 +162,23 @@ export default class SavedItemPane extends Component {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
searchInputHandler(e) {
|
||||
const text = e.target.value;
|
||||
let el;
|
||||
if (!text) {
|
||||
this.setState({
|
||||
filteredItems: this.items
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
filteredItems: this.items.filter(
|
||||
item => item.title.toLowerCase().indexOf(text) !== -1
|
||||
)
|
||||
});
|
||||
}
|
||||
trackEvent('ui', 'searchInputType');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
@ -162,12 +194,7 @@ export default class SavedItemPane extends Component {
|
||||
X
|
||||
</button>
|
||||
<div class="flex flex-v-center" style="justify-content: space-between;">
|
||||
<h3>
|
||||
My Library{' '}
|
||||
<span id="savedItemCountEl">
|
||||
{this.props.items ? this.props.items.length : 0}
|
||||
</span>
|
||||
</h3>
|
||||
<h3>My Library ({this.items.length})</h3>
|
||||
|
||||
<div class="main-header__btn-wrap">
|
||||
<a
|
||||
@ -192,42 +219,42 @@ export default class SavedItemPane extends Component {
|
||||
type=""
|
||||
id="searchInput"
|
||||
class="search-input"
|
||||
d-input="onSearchInputChange"
|
||||
onInput={this.searchInputHandler.bind(this)}
|
||||
placeholder="Search your creations here..."
|
||||
/>
|
||||
|
||||
<div id="js-saved-items-wrap" class="saved-items-pane__container">
|
||||
{this.props.items &&
|
||||
this.props.items.length &&
|
||||
this.props.items.map(item => (
|
||||
<div
|
||||
class="js-saved-item-tile saved-item-tile"
|
||||
data-item-id={item.id}
|
||||
onClick={this.itemClickHandler.bind(this, item)}
|
||||
>
|
||||
<div class="saved-item-tile__btns">
|
||||
<a
|
||||
class="js-saved-item-tile__fork-btn saved-item-tile__btn hint--left hint--medium"
|
||||
aria-label="Creates a duplicate of this creation (Ctrl/⌘ + F)"
|
||||
onClick={this.itemForkBtnClickHandler.bind(this, item)}
|
||||
>
|
||||
Fork<span class="show-when-selected">(Ctrl/⌘ + F)</span>
|
||||
</a>
|
||||
<a
|
||||
class="js-saved-item-tile__remove-btn saved-item-tile__btn hint--left"
|
||||
aria-label="Remove"
|
||||
onClick={this.itemRemoveBtnClickHandler.bind(this, item)}
|
||||
>
|
||||
X
|
||||
</a>
|
||||
</div>
|
||||
<h3 class="saved-item-tile__title">{item.title}</h3>
|
||||
<span class="saved-item-tile__meta">
|
||||
Last updated: {getHumanDate(item.updatedOn)}
|
||||
</span>
|
||||
{!this.state.filteredItems.length &&
|
||||
!this.items.length && <div class="mt-1">No match found.</div>}
|
||||
{this.state.filteredItems.map(item => (
|
||||
<div
|
||||
class="js-saved-item-tile saved-item-tile"
|
||||
data-item-id={item.id}
|
||||
onClick={this.itemClickHandler.bind(this, item)}
|
||||
>
|
||||
<div class="saved-item-tile__btns">
|
||||
<a
|
||||
class="js-saved-item-tile__fork-btn saved-item-tile__btn hint--left hint--medium"
|
||||
aria-label="Creates a duplicate of this creation (Ctrl/⌘ + F)"
|
||||
onClick={this.itemForkBtnClickHandler.bind(this, item)}
|
||||
>
|
||||
Fork<span class="show-when-selected">(Ctrl/⌘ + F)</span>
|
||||
</a>
|
||||
<a
|
||||
class="js-saved-item-tile__remove-btn saved-item-tile__btn hint--left"
|
||||
aria-label="Remove"
|
||||
onClick={this.itemRemoveBtnClickHandler.bind(this, item)}
|
||||
>
|
||||
X
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
{!(this.props.items && this.props.items.length) && (
|
||||
<h3 class="saved-item-tile__title">{item.title}</h3>
|
||||
<span class="saved-item-tile__meta">
|
||||
Last updated: {getHumanDate(item.updatedOn)}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
{!this.items.length && (
|
||||
<h2 class="opacity--30">Nothing saved here.</h2>
|
||||
)}
|
||||
</div>
|
||||
|
@ -54,12 +54,14 @@ export default class App extends Component {
|
||||
isSavedItemPaneOpen: false,
|
||||
isModalOpen: false,
|
||||
isAddLibraryModalOpen: false,
|
||||
isSettingsModalOpen: false,
|
||||
isHelpModalOpen: false,
|
||||
isNotificationsModalOpen: false,
|
||||
isLoginModalOpen: false,
|
||||
isProfileModalOpen: false,
|
||||
isSupportDeveloperModalOpen: false,
|
||||
isKeyboardShortcutsModalOpen: false,
|
||||
isAskToImportModalOpen: false,
|
||||
prefs: {},
|
||||
currentItem: {
|
||||
title: '',
|
||||
@ -269,28 +271,26 @@ export default class App extends Component {
|
||||
this.setCurrentItem(item).then(() => this.refreshEditor());
|
||||
alertsService.add('Saved item loaded');
|
||||
}
|
||||
removeItem(itemId) {
|
||||
var answer = confirm(
|
||||
`Are you sure you want to delete "${savedItems[itemId].title}"?`
|
||||
);
|
||||
removeItem(item) {
|
||||
var answer = confirm(`Are you sure you want to delete "${item.title}"?`);
|
||||
if (!answer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove from items list
|
||||
itemService.unsetItemForUser(itemId);
|
||||
itemService.unsetItemForUser(item.id);
|
||||
|
||||
// Remove individual item too.
|
||||
itemService.removeItem(itemId).then(() => {
|
||||
alertsService.add('Item removed.');
|
||||
itemService.removeItem(item.id).then(() => {
|
||||
alertsService.add('Item removed.', item);
|
||||
// This item is open in the editor. Lets open a new one.
|
||||
if (this.state.currentItem.id === itemId) {
|
||||
if (this.state.currentItem.id === item.id) {
|
||||
this.createNewItem();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove from cached list
|
||||
delete this.state.savedItems[itemId];
|
||||
delete this.state.savedItems[item.id];
|
||||
this.setState({
|
||||
savedItems: { ...this.state.savedItems }
|
||||
});
|
||||
@ -327,9 +327,7 @@ export default class App extends Component {
|
||||
const savedItemsPane = $('#js-saved-items-pane');
|
||||
// TODO: sort desc. by updation date
|
||||
this.setState({
|
||||
savedItems: items.sort(function(a, b) {
|
||||
return b.updatedOn - a.updatedOn;
|
||||
})
|
||||
savedItems: { ...this.state.savedItems }
|
||||
});
|
||||
|
||||
this.toggleSavedItemsPane();
|
||||
@ -727,8 +725,8 @@ export default class App extends Component {
|
||||
}, 350);
|
||||
this.toggleSavedItemsPane();
|
||||
}
|
||||
itemRemoveBtnClickHandler(itemId) {
|
||||
this.removeItem(itemId);
|
||||
itemRemoveBtnClickHandler(item) {
|
||||
this.removeItem(item);
|
||||
}
|
||||
itemForkBtnClickHandler(item) {
|
||||
this.toggleSavedItemsPane();
|
||||
@ -860,6 +858,27 @@ export default class App extends Component {
|
||||
this.openSupportDeveloperModal(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from inside ask-to-import-modal
|
||||
*/
|
||||
dontAskToImportAnymore(e) {
|
||||
this.setState({ isAskToImportModalOpen: false });
|
||||
window.localStorage[LocalStorageKeys.ASKED_TO_IMPORT_CREATIONS] = true;
|
||||
if (e) {
|
||||
trackEvent('ui', 'dontAskToImportBtnClick');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from inside ask-to-import-modal
|
||||
*/
|
||||
importCreationsAndSettingsIntoApp() {
|
||||
this.mergeImportedItems(this.oldSavedItems).then(() => {
|
||||
trackEvent('fn', 'oldItemsImported');
|
||||
this.dontAskToImportAnymore();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
@ -1013,6 +1032,10 @@ export default class App extends Component {
|
||||
show={this.state.isAskToImportModalOpen}
|
||||
closeHandler={() => this.setState({ isAskToImportModalOpen: false })}
|
||||
oldSavedCreationsCount={this.oldSavedCreationsCount}
|
||||
importBtnClickHandler={this.importCreationsAndSettingsIntoApp.bind(
|
||||
this
|
||||
)}
|
||||
dontAskBtnClickHandler={this.dontAskToImportAnymore.bind(this)}
|
||||
/>
|
||||
|
||||
<div class="modal-overlay" />
|
||||
|
@ -41,6 +41,10 @@ import {
|
||||
}
|
||||
}, FAUX_DELAY);
|
||||
/* eslint-enable consistent-return */
|
||||
},
|
||||
remove: (key, cb) => {
|
||||
window.localStorage.removeItem(key);
|
||||
setTimeout(() => cb(), FAUX_DELAY);
|
||||
}
|
||||
};
|
||||
const dbLocalAlias = chrome && chrome.storage ? chrome.storage.local : local;
|
||||
|
@ -159,7 +159,7 @@ export const itemService = {
|
||||
// When not logged in
|
||||
if (!window.user) {
|
||||
var d = deferred();
|
||||
db.local.remove(id, d.resolve);
|
||||
window.db.local.remove(id, d.resolve);
|
||||
return d.promise;
|
||||
}
|
||||
const remoteDb = await window.db.getDb();
|
||||
@ -211,7 +211,7 @@ export const itemService = {
|
||||
},
|
||||
function (result) {
|
||||
delete result.items[itemId];
|
||||
db.local.set({
|
||||
window.db.local.set({
|
||||
items: result.items
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user