1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-04-30 07:27:58 +02:00

complete functionality for header

This commit is contained in:
Kushagra Gour 2018-06-02 22:55:44 +05:30
parent 4642571658
commit 959fef487f
5 changed files with 183 additions and 62 deletions

View File

@ -25,17 +25,29 @@ export default class ContentWrap extends Component {
onHtmlCodeChange(editor, change) { onHtmlCodeChange(editor, change) {
this.cmCodes.html = editor.getValue(); this.cmCodes.html = editor.getValue();
this.props.onCodeChange('html', this.cmCodes.html); this.props.onCodeChange(
'html',
this.cmCodes.html,
change.origin !== 'setValue'
);
this.onCodeChange(editor, change); this.onCodeChange(editor, change);
} }
onCssCodeChange(editor, change) { onCssCodeChange(editor, change) {
this.cmCodes.css = editor.getValue(); this.cmCodes.css = editor.getValue();
this.props.onCodeChange('css', this.cmCodes.css); this.props.onCodeChange(
'css',
this.cmCodes.css,
change.origin !== 'setValue'
);
this.onCodeChange(editor, change); this.onCodeChange(editor, change);
} }
onJsCodeChange(editor, change) { onJsCodeChange(editor, change) {
this.cmCodes.js = editor.getValue(); this.cmCodes.js = editor.getValue();
this.props.onCodeChange('js', this.cmCodes.js); this.props.onCodeChange(
'js',
this.cmCodes.js,
change.origin !== 'setValue'
);
this.onCodeChange(editor, change); this.onCodeChange(editor, change);
} }
onCodeChange(editor, change) { onCodeChange(editor, change) {
@ -51,25 +63,11 @@ export default class ContentWrap extends Component {
this.setPreviewContent(); this.setPreviewContent();
} }
/* saveBtn.classList.add('is-marked');
this.unsavedEditCount += 1;
if (
this.unsavedEditCount % this.unsavedEditWarningCount === 0 &&
this.unsavedEditCount >= this.unsavedEditWarningCount
) {
saveBtn.classList.add('animated');
saveBtn.classList.add('wobble');
saveBtn.addEventListener('animationend', () => {
saveBtn.classList.remove('animated');
saveBtn.classList.remove('wobble');
});
} */
// Track when people actually are working. // Track when people actually are working.
// trackEvent.previewCount = (trackEvent.previewCount || 0) + 1; trackEvent.previewCount = (trackEvent.previewCount || 0) + 1;
// if (trackEvent.previewCount === 4) { if (trackEvent.previewCount === 4) {
// trackEvent('fn', 'usingPreview'); trackEvent('fn', 'usingPreview');
// } }
} }
}, this.updateDelay); }, this.updateDelay);
} }
@ -292,17 +290,26 @@ export default class ContentWrap extends Component {
this.codeInPreview.js = currentCode.js; this.codeInPreview.js = currentCode.js;
} }
componentDidUpdate() { componentDidUpdate() {
this.refreshEditor();
// this.setPreviewContent(true);
// console.log('componentdidupdate', this.props.currentItem);
}
componentDidMount() {
this.props.onRef(this);
}
refreshEditor() {
console.log('ContentWrap refresh editor');
this.cmCodes.html = this.props.currentItem.html; this.cmCodes.html = this.props.currentItem.html;
this.cmCodes.css = this.props.currentItem.css; this.cmCodes.css = this.props.currentItem.css;
this.cmCodes.js = this.props.currentItem.js; this.cmCodes.js = this.props.currentItem.js;
this.cm.html.setValue(this.cmCodes.html || ''); this.cm.html.setValue(this.cmCodes.html || '');
this.cm.css.setValue(this.cmCodes.css || ''); this.cm.css.setValue(this.cmCodes.css || '');
this.cm.js.setValue(this.cmCodes.js || ''); this.cm.js.setValue(this.cmCodes.js || '');
// this.setPreviewContent(true); this.cm.html.refresh();
// console.log('componentdidupdate', this.props.currentItem); this.cm.css.refresh();
} this.cm.js.refresh();
componentDidMount() {
this.props.onRef(this); this.setPreviewContent(true);
} }
applyCodemirrorSettings(prefs) { applyCodemirrorSettings(prefs) {
if (!this.cm) { if (!this.cm) {

View File

@ -9,18 +9,6 @@ export default class Login extends Component {
trackEvent('ui', 'loginProviderClick', provider); trackEvent('ui', 'loginProviderClick', provider);
auth.login(provider); auth.login(provider);
} }
logout(e) {
if (this.unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to logout?'
);
if (!shouldDiscard) {
return;
}
}
trackEvent('fn', 'loggedOut');
auth.logout();
}
render() { render() {
return ( return (
<div> <div>

View File

@ -9,7 +9,7 @@ export default class Header extends Component {
id="titleInput" id="titleInput"
title="Click to edit" title="Click to edit"
class="item-title-input" class="item-title-input"
value="Untitled Work" value={this.props.title}
onBlur={this.props.titleInputBlurHandler} onBlur={this.props.titleInputBlurHandler}
/> />
<div class="main-header__btn-wrap flex flex-v-center"> <div class="main-header__btn-wrap flex flex-v-center">
@ -46,7 +46,7 @@ export default class Header extends Component {
<a <a
class="flex flex-v-center hint--rounded hint--bottom-left" class="flex flex-v-center hint--rounded hint--bottom-left"
aria-label="Start a new creation" aria-label="Start a new creation"
d-click="onNewBtnClick" onClick={this.props.newBtnHandler}
> >
<svg <svg
style="vertical-align:middle;width:14px;height:14px" style="vertical-align:middle;width:14px;height:14px"
@ -59,7 +59,7 @@ export default class Header extends Component {
id="saveBtn" id="saveBtn"
class={`flex flex-v-center hint--rounded hint--bottom-left ${ class={`flex flex-v-center hint--rounded hint--bottom-left ${
this.props.isSaving ? 'is-loading' : '' this.props.isSaving ? 'is-loading' : ''
}`} } ${this.props.unsavedEditCount ? 'is-marked' : 0}`}
aria-label="Save current creation (Ctrl/⌘ + S)" aria-label="Save current creation (Ctrl/⌘ + S)"
onClick={this.props.saveBtnHandler} onClick={this.props.saveBtnHandler}
> >

View File

@ -5,6 +5,17 @@ export default class SavedItemPane extends Component {
onCloseIntent() { onCloseIntent() {
this.props.closeHandler(); this.props.closeHandler();
} }
itemClickHandler(item) {
this.props.itemClickHandler(item);
}
itemRemoveBtnClickHandler(item, e) {
e.stopPropagation();
this.props.itemRemoveBtnClickHandler(item);
}
itemForkBtnClickHandler(item, e) {
e.stopPropagation();
this.props.itemForkBtnClickHandler(item);
}
render() { render() {
return ( return (
<div <div
@ -60,17 +71,20 @@ export default class SavedItemPane extends Component {
<div <div
class="js-saved-item-tile saved-item-tile" class="js-saved-item-tile saved-item-tile"
data-item-id={item.id} data-item-id={item.id}
onClick={this.itemClickHandler.bind(this, item)}
> >
<div class="saved-item-tile__btns"> <div class="saved-item-tile__btns">
<a <a
class="js-saved-item-tile__fork-btn saved-item-tile__btn hint--left hint--medium" 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)" 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> Fork<span class="show-when-selected">(Ctrl/ + F)</span>
</a> </a>
<a <a
class="js-saved-item-tile__remove-btn saved-item-tile__btn hint--left" class="js-saved-item-tile__remove-btn saved-item-tile__btn hint--left"
aria-label="Remove" aria-label="Remove"
onClick={this.itemRemoveBtnClickHandler.bind(this, item)}
> >
X X
</a> </a>

View File

@ -21,6 +21,7 @@ import { alertsService } from '../notifications';
import firebase from 'firebase/app'; import firebase from 'firebase/app';
import 'firebase/auth'; import 'firebase/auth';
import Profile from './Profile'; import Profile from './Profile';
import { auth } from '../auth';
if (module.hot) { if (module.hot) {
require('preact/debug'); require('preact/debug');
@ -30,6 +31,7 @@ const LocalStorageKeys = {
LOGIN_AND_SAVE_MESSAGE_SEEN: 'loginAndsaveMessageSeen', LOGIN_AND_SAVE_MESSAGE_SEEN: 'loginAndsaveMessageSeen',
ASKED_TO_IMPORT_CREATIONS: 'askedToImportCreations' ASKED_TO_IMPORT_CREATIONS: 'askedToImportCreations'
}; };
const UNSAVED_WARNING_COUNT = 15;
export default class App extends Component { export default class App extends Component {
constructor() { constructor() {
@ -71,7 +73,8 @@ export default class App extends Component {
preserveConsoleLogs: true, preserveConsoleLogs: true,
lightVersion: false, lightVersion: false,
lineWrap: true, lineWrap: true,
infiniteLoopTimeout: 1000 infiniteLoopTimeout: 1000,
layoutMode: 2
}; };
this.prefs = {}; this.prefs = {};
@ -131,7 +134,7 @@ export default class App extends Component {
}, },
result => { result => {
// this.toggleLayout(result.layoutMode); // this.toggleLayout(result.layoutMode);
this.prefs.layoutMode = result.layoutMode; this.state.prefs.layoutMode = result.layoutMode;
if (result.code) { if (result.code) {
lastCode = result.code; lastCode = result.code;
} }
@ -174,7 +177,31 @@ export default class App extends Component {
} }
} }
refreshEditor() {} refreshEditor() {
this.toggleLayout(
this.state.currentItem.layoutMode || this.state.prefs.layoutMode
);
// this.contentWrap.refreshEditor();
}
// Creates a new item with passed item's contents
forkItem(sourceItem) {
if (this.state.unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes in your current work. Do you want to discard unsaved changes and continue?'
);
if (!shouldDiscard) {
return;
}
}
const fork = JSON.parse(JSON.stringify(sourceItem));
delete fork.id;
fork.title = '(Forked) ' + sourceItem.title;
fork.updatedOn = Date.now();
this.setCurrentItem(fork);
this.refreshEditor();
alertsService.add(`"${sourceItem.title}" was forked`);
trackEvent('fn', 'itemForked');
}
createNewItem() { createNewItem() {
var d = new Date(); var d = new Date();
this.setCurrentItem({ this.setCurrentItem({
@ -196,8 +223,43 @@ export default class App extends Component {
this.refreshEditor(); this.refreshEditor();
alertsService.add('New item created'); alertsService.add('New item created');
} }
openItem(item) {
// console.log(itemId, this.state.savedItems)
this.setCurrentItem(item);
this.refreshEditor();
alertsService.add('Saved item loaded');
}
removeItem(itemId) {
var answer = confirm(
`Are you sure you want to delete "${savedItems[itemId].title}"?`
);
if (!answer) {
return;
}
// Remove from items list
itemService.unsetItemForUser(itemId);
// Remove individual item too.
itemService.removeItem(itemId).then(() => {
alertsService.add('Item removed.');
// This item is open in the editor. Lets open a new one.
if (this.state.currentItem.id === itemId) {
this.createNewItem();
}
});
// Remove from cached list
delete this.state.savedItems[itemId];
this.setState({
savedItems: { ...this.state.savedItems }
});
trackEvent('fn', 'itemRemoved');
}
setCurrentItem(item) { setCurrentItem(item) {
this.state.currentItem = item; this.setState({ currentItem: item });
log('Current Item set', item); log('Current Item set', item);
// Reset auto-saving flag // Reset auto-saving flag
@ -373,8 +435,8 @@ export default class App extends Component {
d.getSeconds() d.getSeconds()
].join('-'); ].join('-');
if (currentItem.title) { if (this.state.currentItem.title) {
fileName = currentItem.title; fileName = this.state.currentItem.title;
} }
fileName += '.html'; fileName += '.html';
@ -440,8 +502,8 @@ export default class App extends Component {
} }
layoutBtnClickHandler(layoutId) { layoutBtnClickHandler(layoutId) {
// saveSetting('layoutMode', mode); this.saveSetting('layoutMode', layoutId);
trackEvent('ui', 'toggleLayoutClick', mode); trackEvent('ui', 'toggleLayoutClick', layoutId);
this.toggleLayout(layoutId); this.toggleLayout(layoutId);
} }
saveSetting(setting, value) { saveSetting(setting, value) {
@ -454,8 +516,6 @@ export default class App extends Component {
} }
saveCode(key) { saveCode(key) {
this.state.currentItem.title = window.titleInput.value;
// currentItem.htmlMode = htmlMode; // currentItem.htmlMode = htmlMode;
// currentItem.cssMode = cssMode; // currentItem.cssMode = cssMode;
// currentItem.jsMode = jsMode; // currentItem.jsMode = jsMode;
@ -466,10 +526,6 @@ export default class App extends Component {
} }
this.state.currentItem.updatedOn = Date.now(); this.state.currentItem.updatedOn = Date.now();
this.state.currentItem.layoutMode = this.state.currentLayoutMode; this.state.currentItem.layoutMode = this.state.currentLayoutMode;
// this.state.currentItem.externalLibs = {
// js: externalJsTextarea.value,
// css: externalCssTextarea.value
// };
// currentItem.sizes = getCodePaneSizes(); // currentItem.sizes = getCodePaneSizes();
// currentItem.mainSizes = getMainPaneSizes(); // currentItem.mainSizes = getMainPaneSizes();
@ -537,11 +593,28 @@ export default class App extends Component {
itemService.setItemForUser(this.state.currentItem.id); itemService.setItemForUser(this.state.currentItem.id);
} }
} }
onCodeChange(type, code) { onCodeChange(type, code, isUserChange) {
this.state.currentItem[type] = code; this.state.currentItem[type] = code;
if (isUserChange) {
this.setState({ unsavedEditCount: this.state.unsavedEditCount + 1 });
if (
this.state.unsavedEditCount % UNSAVED_WARNING_COUNT === 0 &&
this.state.unsavedEditCount >= UNSAVED_WARNING_COUNT
) {
window.saveBtn.classList.add('animated');
window.saveBtn.classList.add('wobble');
window.saveBtn.addEventListener('animationend', () => {
window.saveBtn.classList.remove('animated');
window.saveBtn.classList.remove('wobble');
});
}
}
} }
titleInputBlurHandler() { titleInputBlurHandler(e) {
this.state.currentItem.title = e.target.value;
if (this.state.currentItem.id) { if (this.state.currentItem.id) {
this.saveItem(); this.saveItem();
trackEvent('ui', 'titleChanged'); trackEvent('ui', 'titleChanged');
@ -622,9 +695,8 @@ export default class App extends Component {
this.setState({ isProfileModalOpen: true }); this.setState({ isProfileModalOpen: true });
} }
logout(e) { logout() {
e.preventDefault(); if (this.state.unsavedEditCount) {
if (unsavedEditCount) {
var shouldDiscard = confirm( var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to logout?' 'You have unsaved changes. Do you still want to logout?'
); );
@ -633,7 +705,36 @@ export default class App extends Component {
} }
} }
trackEvent('fn', 'loggedOut'); trackEvent('fn', 'loggedOut');
window.logout(); auth.logout();
}
itemClickHandler(item) {
setTimeout(() => {
this.openItem(item);
}, 350);
this.toggleSavedItemsPane();
}
itemRemoveBtnClickHandler(itemId) {
this.removeItem(itemId);
}
itemForkBtnClickHandler(item) {
this.toggleSavedItemsPane();
setTimeout(() => {
this.forkItem(item);
}, 350);
}
newBtnClickHandler() {
trackEvent('ui', 'newBtnClick');
if (this.state.unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to create something new?'
);
if (shouldDiscard) {
this.createNewItem();
}
} else {
this.createNewItem();
}
} }
render() { render() {
@ -643,19 +744,24 @@ export default class App extends Component {
<MainHeader <MainHeader
externalLibCount={this.state.externalLibCount} externalLibCount={this.state.externalLibCount}
openBtnHandler={this.openSavedItemsPane.bind(this)} openBtnHandler={this.openSavedItemsPane.bind(this)}
newBtnHandler={this.newBtnClickHandler.bind(this)}
saveBtnHandler={this.saveBtnClickHandler.bind(this)} saveBtnHandler={this.saveBtnClickHandler.bind(this)}
loginBtnHandler={this.loginBtnClickHandler.bind(this)} loginBtnHandler={this.loginBtnClickHandler.bind(this)}
profileBtnHandler={this.profileBtnClickHandler.bind(this)} profileBtnHandler={this.profileBtnClickHandler.bind(this)}
addLibraryBtnHandler={this.openAddLibrary.bind(this)} addLibraryBtnHandler={this.openAddLibrary.bind(this)}
isFetchingItems={this.state.isFetchingItems} isFetchingItems={this.state.isFetchingItems}
isSaving={this.state.isSaving} isSaving={this.state.isSaving}
title={this.state.currentItem.title}
titleInputBlurHandler={this.titleInputBlurHandler.bind(this)} titleInputBlurHandler={this.titleInputBlurHandler.bind(this)}
user={this.state.user} user={this.state.user}
unsavedEditCount={this.state.unsavedEditCount}
/> />
<ContentWrap <ContentWrap
currentLayoutMode={this.state.currentLayoutMode}
currentItem={this.state.currentItem} currentItem={this.state.currentItem}
onCodeChange={this.onCodeChange.bind(this)} onCodeChange={this.onCodeChange.bind(this)}
onRef={comp => (this.contentWrap = comp)} onRef={comp => (this.contentWrap = comp)}
prefs={this.state.prefs}
/> />
<div class="global-console-container" id="globalConsoleContainerEl" /> <div class="global-console-container" id="globalConsoleContainerEl" />
<Footer <Footer
@ -674,6 +780,9 @@ export default class App extends Component {
items={this.state.savedItems} items={this.state.savedItems}
isOpen={this.state.isSavedItemPaneOpen} isOpen={this.state.isSavedItemPaneOpen}
closeHandler={this.closeSavedItemsPane.bind(this)} closeHandler={this.closeSavedItemsPane.bind(this)}
itemClickHandler={this.itemClickHandler.bind(this)}
itemRemoveBtnClickHandler={this.itemRemoveBtnClickHandler.bind(this)}
itemForkBtnClickHandler={this.itemForkBtnClickHandler.bind(this)}
/> />
<div class="alerts-container" id="js-alerts-container" /> <div class="alerts-container" id="js-alerts-container" />
<form <form
@ -735,7 +844,10 @@ export default class App extends Component {
show={this.state.isProfileModalOpen} show={this.state.isProfileModalOpen}
closeHandler={() => this.setState({ isProfileModalOpen: false })} closeHandler={() => this.setState({ isProfileModalOpen: false })}
> >
<Profile user={this.state.user} /> <Profile
user={this.state.user}
logoutBtnHandler={this.logout.bind(this)}
/>
</Modal> </Modal>
<HelpModal <HelpModal
show={this.state.isHelpModalOpen} show={this.state.isHelpModalOpen}