mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-27 16:50:11 +02:00
add folders!
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { h, Component } from 'preact';
|
||||
import UserCodeMirror from './UserCodeMirror';
|
||||
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
||||
import { log, loadJS } from '../utils';
|
||||
import { log, loadJS, linearizeFiles } from '../utils';
|
||||
import { SplitPane } from './SplitPane';
|
||||
import { trackEvent } from '../analytics';
|
||||
import CodeMirror from '../CodeMirror';
|
||||
@@ -58,7 +58,7 @@ export default class ContentWrapFiles extends Component {
|
||||
}
|
||||
componentDidUpdate() {
|
||||
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.
|
||||
if (
|
||||
@@ -79,18 +79,7 @@ export default class ContentWrapFiles extends Component {
|
||||
componentDidMount() {
|
||||
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 = '') {
|
||||
let options = {
|
||||
gutters: [
|
||||
@@ -172,6 +161,17 @@ export default class ContentWrapFiles extends Component {
|
||||
}, 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) {
|
||||
// Track if people have written code.
|
||||
if (!trackEvent.hasTrackedCode && (html || css || js)) {
|
||||
@@ -180,12 +180,17 @@ export default class ContentWrapFiles extends Component {
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
this.props.currentItem.files.forEach(file => {
|
||||
obj[`/user/${file.name}`] = file.content || '';
|
||||
const duplicateFiles = JSON.parse(
|
||||
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
|
||||
if (file.name === 'index.html') {
|
||||
obj[`/user/${file.name}`] =
|
||||
obj[file.path] =
|
||||
'<script src="' +
|
||||
(chrome.extension
|
||||
? chrome.extension.getURL('lib/screenlog.js')
|
||||
@@ -193,7 +198,7 @@ export default class ContentWrapFiles extends Component {
|
||||
window.DEBUG ? '' : BASE_PATH
|
||||
}/lib/screenlog.js`) +
|
||||
'"></script>' +
|
||||
obj[`/user/${file.name}`];
|
||||
obj[file.path];
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -170,7 +170,10 @@ function Folder(props) {
|
||||
|
||||
export class SidePane extends Component {
|
||||
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.
|
||||
@@ -194,8 +197,8 @@ export class SidePane extends Component {
|
||||
|
||||
addFile(e) {
|
||||
// This gets called twice when enter is pressed, because blur also fires.
|
||||
// So check `isEditing` before proceeding.
|
||||
if (!this.state.isEditing) {
|
||||
// So check `isAddingFile` before proceeding.
|
||||
if (!this.state.isAddingFile && !this.state.isAddingFolder) {
|
||||
return;
|
||||
}
|
||||
const newFileName = e.target.value;
|
||||
@@ -203,15 +206,15 @@ export class SidePane extends Component {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
if (e.which === ENTER_KEY) {
|
||||
this.addFile(e);
|
||||
} else if (e.which === ESCAPE_KEY) {
|
||||
this.setState({ isEditing: false });
|
||||
this.setState({ isAddingFile: false, isAddingFolder: false });
|
||||
}
|
||||
}
|
||||
removeFileClickHandler(file, e) {
|
||||
@@ -262,7 +265,7 @@ export class SidePane extends Component {
|
||||
<div class="sidebar">
|
||||
<div class="flex jc-sb" style="padding: 5px 4px">
|
||||
Files
|
||||
<div>
|
||||
<div class="flex flex-v-center">
|
||||
<button
|
||||
type="button"
|
||||
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" />
|
||||
</svg>
|
||||
</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>
|
||||
{this.state.isEditing ? (
|
||||
{this.state.isAddingFile || this.state.isAddingFolder ? (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
|
@@ -20,7 +20,8 @@ import {
|
||||
handleDownloadsPermission,
|
||||
downloadFile,
|
||||
getCompleteHtml,
|
||||
getFilenameFromUrl
|
||||
getFilenameFromUrl,
|
||||
linearizeFiles
|
||||
} from '../utils';
|
||||
import { itemService } from '../itemService';
|
||||
import '../db';
|
||||
@@ -711,7 +712,7 @@ export default class App extends Component {
|
||||
}
|
||||
onCodeChange(type, code, isUserChange) {
|
||||
if (this.state.currentItem.files) {
|
||||
this.state.currentItem.files.map(file => {
|
||||
linearizeFiles(this.state.currentItem.files).map(file => {
|
||||
if (file.name === type.name) {
|
||||
file.content = code;
|
||||
}
|
||||
@@ -1187,17 +1188,23 @@ export default class App extends Component {
|
||||
});
|
||||
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({
|
||||
currentItem: {
|
||||
...this.state.currentItem,
|
||||
files: [
|
||||
...this.state.currentItem.files,
|
||||
{ name: fileName, content: '' }
|
||||
]
|
||||
files: [...this.state.currentItem.files, newEntry]
|
||||
}
|
||||
});
|
||||
console.log(11, this.state.currentItem);
|
||||
}
|
||||
removeFileHandler(fileToRemove) {
|
||||
this.setState({
|
||||
|
18
src/utils.js
18
src/utils.js
@@ -465,3 +465,21 @@ if (window.IS_EXTENSION) {
|
||||
} else {
|
||||
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