mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-27 00:30:09 +02:00
add folders!
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { h, Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import UserCodeMirror from './UserCodeMirror';
|
import UserCodeMirror from './UserCodeMirror';
|
||||||
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
||||||
import { log, loadJS } from '../utils';
|
import { log, loadJS, linearizeFiles } from '../utils';
|
||||||
import { SplitPane } from './SplitPane';
|
import { SplitPane } from './SplitPane';
|
||||||
import { trackEvent } from '../analytics';
|
import { trackEvent } from '../analytics';
|
||||||
import CodeMirror from '../CodeMirror';
|
import CodeMirror from '../CodeMirror';
|
||||||
@@ -58,7 +58,7 @@ export default class ContentWrapFiles extends Component {
|
|||||||
}
|
}
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { currentItem } = this.props;
|
const { currentItem } = this.props;
|
||||||
const linearFiles = this.linearizeFiles(currentItem.files);
|
const linearFiles = linearizeFiles(currentItem.files);
|
||||||
|
|
||||||
// Select a new file if nothing is selected already or the selected file exists no more.
|
// Select a new file if nothing is selected already or the selected file exists no more.
|
||||||
if (
|
if (
|
||||||
@@ -79,18 +79,7 @@ export default class ContentWrapFiles extends Component {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.onRef(this);
|
this.props.onRef(this);
|
||||||
}
|
}
|
||||||
linearizeFiles(files) {
|
|
||||||
function reduceToLinearFiles(files) {
|
|
||||||
return files.reduce((list, currentFile) => {
|
|
||||||
if (currentFile.isFolder) {
|
|
||||||
return [...list, ...reduceToLinearFiles(currentFile.children)];
|
|
||||||
} else {
|
|
||||||
return [...list, currentFile];
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
return reduceToLinearFiles(files);
|
|
||||||
}
|
|
||||||
getEditorOptions(fileName = '') {
|
getEditorOptions(fileName = '') {
|
||||||
let options = {
|
let options = {
|
||||||
gutters: [
|
gutters: [
|
||||||
@@ -172,6 +161,17 @@ export default class ContentWrapFiles extends Component {
|
|||||||
}, this.updateDelay);
|
}, this.updateDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructFilePaths(files, parentPath = '/user') {
|
||||||
|
files.forEach(file => {
|
||||||
|
if (file.isFolder) {
|
||||||
|
this.constructFilePaths(file.children, `${parentPath}/${file.name}`);
|
||||||
|
} else {
|
||||||
|
file.path = `${parentPath}/${file.name}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
createPreviewFile(html, css, js) {
|
createPreviewFile(html, css, js) {
|
||||||
// Track if people have written code.
|
// Track if people have written code.
|
||||||
if (!trackEvent.hasTrackedCode && (html || css || js)) {
|
if (!trackEvent.hasTrackedCode && (html || css || js)) {
|
||||||
@@ -180,12 +180,17 @@ export default class ContentWrapFiles extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var obj = {};
|
var obj = {};
|
||||||
this.props.currentItem.files.forEach(file => {
|
const duplicateFiles = JSON.parse(
|
||||||
obj[`/user/${file.name}`] = file.content || '';
|
JSON.stringify(this.props.currentItem.files)
|
||||||
|
);
|
||||||
|
const files = linearizeFiles(this.constructFilePaths(duplicateFiles));
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
obj[file.path] = file.content || '';
|
||||||
|
|
||||||
// Add screenlog to index.html
|
// Add screenlog to index.html
|
||||||
if (file.name === 'index.html') {
|
if (file.name === 'index.html') {
|
||||||
obj[`/user/${file.name}`] =
|
obj[file.path] =
|
||||||
'<script src="' +
|
'<script src="' +
|
||||||
(chrome.extension
|
(chrome.extension
|
||||||
? chrome.extension.getURL('lib/screenlog.js')
|
? chrome.extension.getURL('lib/screenlog.js')
|
||||||
@@ -193,7 +198,7 @@ export default class ContentWrapFiles extends Component {
|
|||||||
window.DEBUG ? '' : BASE_PATH
|
window.DEBUG ? '' : BASE_PATH
|
||||||
}/lib/screenlog.js`) +
|
}/lib/screenlog.js`) +
|
||||||
'"></script>' +
|
'"></script>' +
|
||||||
obj[`/user/${file.name}`];
|
obj[file.path];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -170,7 +170,10 @@ function Folder(props) {
|
|||||||
|
|
||||||
export class SidePane extends Component {
|
export class SidePane extends Component {
|
||||||
addFileButtonClickHandler() {
|
addFileButtonClickHandler() {
|
||||||
this.setState({ isEditing: true });
|
this.setState({ isAddingFile: true });
|
||||||
|
}
|
||||||
|
addFolderButtonClickHandler() {
|
||||||
|
this.setState({ isAddingFolder: true });
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if the passed filename already exists and if so, warns the user.
|
* Checks if the passed filename already exists and if so, warns the user.
|
||||||
@@ -194,8 +197,8 @@ export class SidePane extends Component {
|
|||||||
|
|
||||||
addFile(e) {
|
addFile(e) {
|
||||||
// This gets called twice when enter is pressed, because blur also fires.
|
// This gets called twice when enter is pressed, because blur also fires.
|
||||||
// So check `isEditing` before proceeding.
|
// So check `isAddingFile` before proceeding.
|
||||||
if (!this.state.isEditing) {
|
if (!this.state.isAddingFile && !this.state.isAddingFolder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newFileName = e.target.value;
|
const newFileName = e.target.value;
|
||||||
@@ -203,15 +206,15 @@ export class SidePane extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newFileName) {
|
if (newFileName) {
|
||||||
this.props.onAddFile(newFileName);
|
this.props.onAddFile(newFileName, this.state.isAddingFolder);
|
||||||
}
|
}
|
||||||
this.setState({ isEditing: false });
|
this.setState({ isAddingFile: false, isAddingFolder: false });
|
||||||
}
|
}
|
||||||
newFileNameInputKeyDownHandler(e) {
|
newFileNameInputKeyDownHandler(e) {
|
||||||
if (e.which === ENTER_KEY) {
|
if (e.which === ENTER_KEY) {
|
||||||
this.addFile(e);
|
this.addFile(e);
|
||||||
} else if (e.which === ESCAPE_KEY) {
|
} else if (e.which === ESCAPE_KEY) {
|
||||||
this.setState({ isEditing: false });
|
this.setState({ isAddingFile: false, isAddingFolder: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeFileClickHandler(file, e) {
|
removeFileClickHandler(file, e) {
|
||||||
@@ -262,7 +265,7 @@ export class SidePane extends Component {
|
|||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="flex jc-sb" style="padding: 5px 4px">
|
<div class="flex jc-sb" style="padding: 5px 4px">
|
||||||
Files
|
Files
|
||||||
<div>
|
<div class="flex flex-v-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn--dark"
|
class="btn--dark"
|
||||||
@@ -275,9 +278,21 @@ export class SidePane extends Component {
|
|||||||
<path d="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M11,15V12H9V15H6V17H9V20H11V17H14V15H11Z" />
|
<path d="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M11,15V12H9V15H6V17H9V20H11V17H14V15H11Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn--dark"
|
||||||
|
onClick={this.addFolderButtonClickHandler.bind(this)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
style="vertical-align:middle;width:14px;height:14px"
|
||||||
|
>
|
||||||
|
<path d="M10,4L12,6H20A2,2 0 0,1 22,8V18A2,2 0 0,1 20,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10M15,9V12H12V14H15V17H17V14H20V12H17V9H15Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.state.isEditing ? (
|
{this.state.isAddingFile || this.state.isAddingFolder ? (
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
@@ -20,7 +20,8 @@ import {
|
|||||||
handleDownloadsPermission,
|
handleDownloadsPermission,
|
||||||
downloadFile,
|
downloadFile,
|
||||||
getCompleteHtml,
|
getCompleteHtml,
|
||||||
getFilenameFromUrl
|
getFilenameFromUrl,
|
||||||
|
linearizeFiles
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { itemService } from '../itemService';
|
import { itemService } from '../itemService';
|
||||||
import '../db';
|
import '../db';
|
||||||
@@ -711,7 +712,7 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
onCodeChange(type, code, isUserChange) {
|
onCodeChange(type, code, isUserChange) {
|
||||||
if (this.state.currentItem.files) {
|
if (this.state.currentItem.files) {
|
||||||
this.state.currentItem.files.map(file => {
|
linearizeFiles(this.state.currentItem.files).map(file => {
|
||||||
if (file.name === type.name) {
|
if (file.name === type.name) {
|
||||||
file.content = code;
|
file.content = code;
|
||||||
}
|
}
|
||||||
@@ -1187,17 +1188,23 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
this.setState({ isCreateNewModalOpen: false });
|
this.setState({ isCreateNewModalOpen: false });
|
||||||
}
|
}
|
||||||
addFileHandler(fileName) {
|
addFileHandler(fileName, isFolder) {
|
||||||
|
let newEntry = { name: fileName, content: '' };
|
||||||
|
if (isFolder) {
|
||||||
|
newEntry = {
|
||||||
|
...newEntry,
|
||||||
|
isFolder: true,
|
||||||
|
children: [],
|
||||||
|
isCollapsed: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
currentItem: {
|
currentItem: {
|
||||||
...this.state.currentItem,
|
...this.state.currentItem,
|
||||||
files: [
|
files: [...this.state.currentItem.files, newEntry]
|
||||||
...this.state.currentItem.files,
|
|
||||||
{ name: fileName, content: '' }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(11, this.state.currentItem);
|
|
||||||
}
|
}
|
||||||
removeFileHandler(fileToRemove) {
|
removeFileHandler(fileToRemove) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
18
src/utils.js
18
src/utils.js
@@ -465,3 +465,21 @@ if (window.IS_EXTENSION) {
|
|||||||
} else {
|
} else {
|
||||||
document.body.classList.add('is-app');
|
document.body.classList.add('is-app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a linear file list from a nested file strcuture.
|
||||||
|
* It excludes the folders from the returned list.
|
||||||
|
* @param {array} files Nested file structure
|
||||||
|
*/
|
||||||
|
export function linearizeFiles(files) {
|
||||||
|
function reduceToLinearFiles(files) {
|
||||||
|
return files.reduce((list, currentFile) => {
|
||||||
|
if (currentFile.isFolder) {
|
||||||
|
return [...list, ...reduceToLinearFiles(currentFile.children)];
|
||||||
|
} else {
|
||||||
|
return [...list, currentFile];
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
return reduceToLinearFiles(files);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user