mirror of
https://github.com/chinchang/web-maker.git
synced 2025-05-06 18:45:31 +02:00
Add a readonly github intergration
This commit is contained in:
parent
fb4fc6b37e
commit
d127720a1f
@ -1,37 +1,68 @@
|
|||||||
import { h } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import { ItemTile } from './ItemTile';
|
import { ItemTile } from './ItemTile';
|
||||||
import templates from '../templateList';
|
import templates from '../templateList';
|
||||||
|
|
||||||
export function CreateNewModal({
|
export class CreateNewModal extends Component {
|
||||||
show,
|
render() {
|
||||||
closeHandler,
|
const {
|
||||||
onBlankTemplateSelect,
|
show,
|
||||||
onBlankFileTemplateSelect,
|
closeHandler,
|
||||||
onTemplateSelect
|
onBlankTemplateSelect,
|
||||||
}) {
|
onBlankFileTemplateSelect,
|
||||||
return (
|
onImportGithubRepoSelect,
|
||||||
<Modal show={show} closeHandler={closeHandler} smll>
|
onTemplateSelect
|
||||||
<div class="tac">
|
} = this.props;
|
||||||
<button className="btn" onClick={onBlankTemplateSelect}>
|
return (
|
||||||
Start a blank creation
|
<Modal show={show} closeHandler={closeHandler}>
|
||||||
</button>
|
<div class="tac">
|
||||||
<button className="btn" onClick={onBlankFileTemplateSelect}>
|
<button className="btn" onClick={onBlankTemplateSelect}>
|
||||||
Start a blank files creation
|
Start a blank creation
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<button className="btn" onClick={onBlankFileTemplateSelect}>
|
||||||
<hr />
|
Start a blank files creation
|
||||||
Or choose from a template:
|
</button>
|
||||||
<div class="saved-items-pane__container">
|
|
||||||
{templates.map(template => (
|
<p>
|
||||||
<ItemTile
|
<button
|
||||||
inline
|
className="btn"
|
||||||
item={template}
|
onClick={() =>
|
||||||
focusable
|
this.setState({
|
||||||
onClick={onTemplateSelect.bind(null, template)}
|
isGhRepoInputVisible: true
|
||||||
/>
|
})
|
||||||
))}
|
}
|
||||||
</div>
|
>
|
||||||
</Modal>
|
Import Github Repository
|
||||||
);
|
</button>
|
||||||
|
|
||||||
|
{this.state.isGhRepoInputVisible ? (
|
||||||
|
<div>
|
||||||
|
<input ref={el => (this.ghRepoInput = el)} />
|
||||||
|
<button
|
||||||
|
className="btn"
|
||||||
|
onClick={() => {
|
||||||
|
onImportGithubRepoSelect(this.ghRepoInput.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Import
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
Or choose from a template:
|
||||||
|
<div class="saved-items-pane__container">
|
||||||
|
{templates.map(template => (
|
||||||
|
<ItemTile
|
||||||
|
inline
|
||||||
|
item={template}
|
||||||
|
focusable
|
||||||
|
onClick={onTemplateSelect.bind(null, template)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,14 @@ export function FileIcon({ file }) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'ts':
|
||||||
|
path: <path
|
||||||
|
fill="#2874C1"
|
||||||
|
d="M3,3H21V21H3V3M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86M13,11.25H8V12.75H9.5V20H11.25V12.75H13V11.25Z"
|
||||||
|
/>;
|
||||||
|
break;
|
||||||
case 'css':
|
case 'css':
|
||||||
|
case 'less':
|
||||||
path = (
|
path = (
|
||||||
<path
|
<path
|
||||||
fill="rgb(95, 158, 160)"
|
fill="rgb(95, 158, 160)"
|
||||||
@ -53,7 +59,15 @@ export function FileIcon({ file }) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'scss':
|
||||||
|
case 'sass':
|
||||||
|
path = (
|
||||||
|
<path
|
||||||
|
fill="#CF649A"
|
||||||
|
d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M10,15.33C10.16,15.87 10.14,16.37 10,16.83C10,16.88 9.96,16.93 9.94,17C9.92,17 9.9,17.07 9.87,17.12C9.76,17.36 9.6,17.59 9.41,17.79C8.83,18.43 8,18.67 7.67,18.47C7.29,18.25 7.5,17.35 8.16,16.64C8.88,15.88 9.92,15.38 9.92,15.38V15.38L10,15.33M18.27,6.28C17.82,4.5 14.87,3.92 12.09,4.91C10.43,5.5 8.63,6.42 7.34,7.63C5.81,9.07 5.56,10.32 5.66,10.84C6,12.68 8.54,13.89 9.58,14.78V14.79C9.28,14.94 7.04,16.07 6.5,17.23C5.96,18.45 6.6,19.33 7,19.45C8.34,19.81 9.69,19.16 10.41,18.07C11.11,17.03 11.06,15.68 10.75,15C11.17,14.9 11.66,14.85 12.28,14.92C14.04,15.13 14.38,16.22 14.31,16.68C14.25,17.14 13.88,17.39 13.76,17.47C13.64,17.54 13.6,17.57 13.61,17.63C13.62,17.71 13.68,17.71 13.78,17.69C13.93,17.66 14.71,17.32 14.74,16.47C14.78,15.39 13.75,14.19 11.93,14.22C11.18,14.24 10.71,14.31 10.37,14.44L10.29,14.35C9.16,13.15 7.08,12.3 7.17,10.68C7.2,10.09 7.4,8.55 11.17,6.67C14.25,5.13 16.72,5.55 17.15,6.5C17.76,7.83 15.83,10.32 12.63,10.68C11.41,10.82 10.76,10.34 10.6,10.17C10.43,10 10.41,9.97 10.35,10C10.24,10.07 10.31,10.23 10.35,10.33C10.44,10.58 10.84,11 11.5,11.24C12.09,11.43 13.53,11.54 15.26,10.87C17.2,10.12 18.72,8.03 18.27,6.28Z"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
case 'md':
|
case 'md':
|
||||||
case 'markdown':
|
case 'markdown':
|
||||||
path = (
|
path = (
|
||||||
|
@ -28,7 +28,8 @@ import {
|
|||||||
assignFilePaths,
|
assignFilePaths,
|
||||||
getFileFromPath,
|
getFileFromPath,
|
||||||
removeFileAtPath,
|
removeFileAtPath,
|
||||||
doesFileExistInFolder
|
doesFileExistInFolder,
|
||||||
|
importGithubRepo
|
||||||
} from '../fileUtils';
|
} from '../fileUtils';
|
||||||
|
|
||||||
import { itemService } from '../itemService';
|
import { itemService } from '../itemService';
|
||||||
@ -319,7 +320,7 @@ export default class App extends Component {
|
|||||||
alertsService.add(`"${sourceItem.title}" was forked`);
|
alertsService.add(`"${sourceItem.title}" was forked`);
|
||||||
trackEvent('fn', 'itemForked');
|
trackEvent('fn', 'itemForked');
|
||||||
}
|
}
|
||||||
createNewItem(isFileMode = false) {
|
createNewItem(isFileMode = false, files) {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
let item = {
|
let item = {
|
||||||
title:
|
title:
|
||||||
@ -337,24 +338,26 @@ export default class App extends Component {
|
|||||||
if (isFileMode) {
|
if (isFileMode) {
|
||||||
item = {
|
item = {
|
||||||
...item,
|
...item,
|
||||||
files: assignFilePaths([
|
files: assignFilePaths(
|
||||||
{
|
files || [
|
||||||
name: 'index.html',
|
{
|
||||||
content:
|
name: 'index.html',
|
||||||
'hello\n<link rel="stylesheet" href="styles/style.css">\n<script src="script.js"></script>'
|
content:
|
||||||
},
|
'hello\n<link rel="stylesheet" href="styles/style.css">\n<script src="script.js"></script>'
|
||||||
{
|
},
|
||||||
name: 'styles',
|
{
|
||||||
isFolder: true,
|
name: 'styles',
|
||||||
children: [{ name: 'style.css', content: '' }]
|
isFolder: true,
|
||||||
},
|
children: [{ name: 'style.css', content: '' }]
|
||||||
{ name: 'script.js', content: '' },
|
},
|
||||||
{
|
{ name: 'script.js', content: '' },
|
||||||
name: 'tempo',
|
{
|
||||||
isFolder: true,
|
name: 'tempo',
|
||||||
children: [{ name: 'main.css', content: '' }]
|
isFolder: true,
|
||||||
}
|
children: [{ name: 'main.css', content: '' }]
|
||||||
])
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
item = {
|
item = {
|
||||||
@ -1311,6 +1314,12 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
this.setState({ isCreateNewModalOpen: false });
|
this.setState({ isCreateNewModalOpen: false });
|
||||||
}
|
}
|
||||||
|
importGithubRepoSelectHandler(repoUrl) {
|
||||||
|
importGithubRepo(repoUrl).then(files => {
|
||||||
|
this.createNewItem(true, files);
|
||||||
|
this.setState({ isCreateNewModalOpen: false });
|
||||||
|
});
|
||||||
|
}
|
||||||
addFileHandler(fileName, isFolder) {
|
addFileHandler(fileName, isFolder) {
|
||||||
let newEntry = { name: fileName, content: '' };
|
let newEntry = { name: fileName, content: '' };
|
||||||
if (isFolder) {
|
if (isFolder) {
|
||||||
@ -1634,6 +1643,9 @@ export default class App extends Component {
|
|||||||
this
|
this
|
||||||
)}
|
)}
|
||||||
onTemplateSelect={this.templateSelectHandler.bind(this)}
|
onTemplateSelect={this.templateSelectHandler.bind(this)}
|
||||||
|
onImportGithubRepoSelect={this.importGithubRepoSelectHandler.bind(
|
||||||
|
this
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CommandPalette
|
<CommandPalette
|
||||||
|
@ -116,3 +116,57 @@ export function getParentPath(path) {
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the files from a github repo and returns a suitable file structure.
|
||||||
|
* @param {Promise} Promise of completition. Resolves to the files structure.
|
||||||
|
*/
|
||||||
|
export function importGithubRepo(repoUrl) {
|
||||||
|
let repoSlug, match;
|
||||||
|
if ((match = repoUrl.match(/github\.com\/([^\/]*\/[^\/]*)/))) {
|
||||||
|
repoSlug = match[1];
|
||||||
|
} else {
|
||||||
|
repoSlug = 'chinchang/github';
|
||||||
|
}
|
||||||
|
const queryString = '';
|
||||||
|
function fetchFile(filepath) {
|
||||||
|
return fetch(
|
||||||
|
`https://api.github.com/repos/${repoSlug}/contents/${filepath}${queryString}`
|
||||||
|
).then(response => response.json());
|
||||||
|
}
|
||||||
|
function fetchDir(path, currentDir) {
|
||||||
|
return fetch(
|
||||||
|
`https://api.github.com/repos/${repoSlug}/contents/${path}${queryString}`
|
||||||
|
)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(response => {
|
||||||
|
if (!response) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return Promise.all(
|
||||||
|
response.map(file => {
|
||||||
|
if (file.type === 'file') {
|
||||||
|
return fetchFile(`${file.path}`).then(actualFile => {
|
||||||
|
currentDir.push({
|
||||||
|
name: file.name,
|
||||||
|
content: atob(actualFile.content)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (file.type === 'dir') {
|
||||||
|
const newEntry = {
|
||||||
|
name: file.name,
|
||||||
|
children: [],
|
||||||
|
isFolder: true
|
||||||
|
};
|
||||||
|
currentDir.push(newEntry);
|
||||||
|
return fetchDir(`${file.path}`, newEntry.children);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const files = [];
|
||||||
|
return fetchDir('', files).then(() => {
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user