1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-04-26 13:47:12 +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

@ -25,17 +25,29 @@ export default class ContentWrap extends Component {
onHtmlCodeChange(editor, change) {
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);
}
onCssCodeChange(editor, change) {
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);
}
onJsCodeChange(editor, change) {
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);
}
onCodeChange(editor, change) {
@ -51,25 +63,11 @@ export default class ContentWrap extends Component {
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.
// trackEvent.previewCount = (trackEvent.previewCount || 0) + 1;
// if (trackEvent.previewCount === 4) {
// trackEvent('fn', 'usingPreview');
// }
trackEvent.previewCount = (trackEvent.previewCount || 0) + 1;
if (trackEvent.previewCount === 4) {
trackEvent('fn', 'usingPreview');
}
}
}, this.updateDelay);
}
@ -292,17 +290,26 @@ export default class ContentWrap extends Component {
this.codeInPreview.js = currentCode.js;
}
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.css = this.props.currentItem.css;
this.cmCodes.js = this.props.currentItem.js;
this.cm.html.setValue(this.cmCodes.html || '');
this.cm.css.setValue(this.cmCodes.css || '');
this.cm.js.setValue(this.cmCodes.js || '');
// this.setPreviewContent(true);
// console.log('componentdidupdate', this.props.currentItem);
}
componentDidMount() {
this.props.onRef(this);
this.cm.html.refresh();
this.cm.css.refresh();
this.cm.js.refresh();
this.setPreviewContent(true);
}
applyCodemirrorSettings(prefs) {
if (!this.cm) {

@ -9,18 +9,6 @@ export default class Login extends Component {
trackEvent('ui', 'loginProviderClick', 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() {
return (
<div>

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

@ -5,6 +5,17 @@ export default class SavedItemPane extends Component {
onCloseIntent() {
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() {
return (
<div
@ -60,17 +71,20 @@ export default class SavedItemPane extends Component {
<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>

@ -21,6 +21,7 @@ import { alertsService } from '../notifications';
import firebase from 'firebase/app';
import 'firebase/auth';
import Profile from './Profile';
import { auth } from '../auth';
if (module.hot) {
require('preact/debug');
@ -30,6 +31,7 @@ const LocalStorageKeys = {
LOGIN_AND_SAVE_MESSAGE_SEEN: 'loginAndsaveMessageSeen',
ASKED_TO_IMPORT_CREATIONS: 'askedToImportCreations'
};
const UNSAVED_WARNING_COUNT = 15;
export default class App extends Component {
constructor() {
@ -71,7 +73,8 @@ export default class App extends Component {
preserveConsoleLogs: true,
lightVersion: false,
lineWrap: true,
infiniteLoopTimeout: 1000
infiniteLoopTimeout: 1000,
layoutMode: 2
};
this.prefs = {};
@ -131,7 +134,7 @@ export default class App extends Component {
},
result => {
// this.toggleLayout(result.layoutMode);
this.prefs.layoutMode = result.layoutMode;
this.state.prefs.layoutMode = result.layoutMode;
if (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() {
var d = new Date();
this.setCurrentItem({
@ -196,8 +223,43 @@ export default class App extends Component {
this.refreshEditor();
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) {
this.state.currentItem = item;
this.setState({ currentItem: item });
log('Current Item set', item);
// Reset auto-saving flag
@ -373,8 +435,8 @@ export default class App extends Component {
d.getSeconds()
].join('-');
if (currentItem.title) {
fileName = currentItem.title;
if (this.state.currentItem.title) {
fileName = this.state.currentItem.title;
}
fileName += '.html';
@ -440,8 +502,8 @@ export default class App extends Component {
}
layoutBtnClickHandler(layoutId) {
// saveSetting('layoutMode', mode);
trackEvent('ui', 'toggleLayoutClick', mode);
this.saveSetting('layoutMode', layoutId);
trackEvent('ui', 'toggleLayoutClick', layoutId);
this.toggleLayout(layoutId);
}
saveSetting(setting, value) {
@ -454,8 +516,6 @@ export default class App extends Component {
}
saveCode(key) {
this.state.currentItem.title = window.titleInput.value;
// currentItem.htmlMode = htmlMode;
// currentItem.cssMode = cssMode;
// currentItem.jsMode = jsMode;
@ -466,10 +526,6 @@ export default class App extends Component {
}
this.state.currentItem.updatedOn = Date.now();
this.state.currentItem.layoutMode = this.state.currentLayoutMode;
// this.state.currentItem.externalLibs = {
// js: externalJsTextarea.value,
// css: externalCssTextarea.value
// };
// currentItem.sizes = getCodePaneSizes();
// currentItem.mainSizes = getMainPaneSizes();
@ -537,11 +593,28 @@ export default class App extends Component {
itemService.setItemForUser(this.state.currentItem.id);
}
}
onCodeChange(type, code) {
onCodeChange(type, code, isUserChange) {
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) {
this.saveItem();
trackEvent('ui', 'titleChanged');
@ -622,9 +695,8 @@ export default class App extends Component {
this.setState({ isProfileModalOpen: true });
}
logout(e) {
e.preventDefault();
if (unsavedEditCount) {
logout() {
if (this.state.unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to logout?'
);
@ -633,7 +705,36 @@ export default class App extends Component {
}
}
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() {
@ -643,19 +744,24 @@ export default class App extends Component {
<MainHeader
externalLibCount={this.state.externalLibCount}
openBtnHandler={this.openSavedItemsPane.bind(this)}
newBtnHandler={this.newBtnClickHandler.bind(this)}
saveBtnHandler={this.saveBtnClickHandler.bind(this)}
loginBtnHandler={this.loginBtnClickHandler.bind(this)}
profileBtnHandler={this.profileBtnClickHandler.bind(this)}
addLibraryBtnHandler={this.openAddLibrary.bind(this)}
isFetchingItems={this.state.isFetchingItems}
isSaving={this.state.isSaving}
title={this.state.currentItem.title}
titleInputBlurHandler={this.titleInputBlurHandler.bind(this)}
user={this.state.user}
unsavedEditCount={this.state.unsavedEditCount}
/>
<ContentWrap
currentLayoutMode={this.state.currentLayoutMode}
currentItem={this.state.currentItem}
onCodeChange={this.onCodeChange.bind(this)}
onRef={comp => (this.contentWrap = comp)}
prefs={this.state.prefs}
/>
<div class="global-console-container" id="globalConsoleContainerEl" />
<Footer
@ -674,6 +780,9 @@ export default class App extends Component {
items={this.state.savedItems}
isOpen={this.state.isSavedItemPaneOpen}
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" />
<form
@ -735,7 +844,10 @@ export default class App extends Component {
show={this.state.isProfileModalOpen}
closeHandler={() => this.setState({ isProfileModalOpen: false })}
>
<Profile user={this.state.user} />
<Profile
user={this.state.user}
logoutBtnHandler={this.logout.bind(this)}
/>
</Modal>
<HelpModal
show={this.state.isHelpModalOpen}