1
0
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:
Kushagra Gour 2018-06-10 03:28:49 +05:30
parent 80621132a1
commit 3518484568
6 changed files with 140 additions and 76 deletions

View File

@ -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

View File

@ -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"

View File

@ -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>

View File

@ -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" />

View File

@ -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;

View File

@ -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
});
}