Commit 6ac1ba0c authored by Sirat Ahmadi's avatar Sirat Ahmadi
Browse files

Move over from mono repo

parents
> 1%
last 2 versions
not dead
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# serverless-editor
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff is collapsed.
{
"name": "serverless-editor",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.4",
"file-saver": "^2.0.2",
"jquery": "^1.9.1",
"jszip": "^3.4.0",
"lodash": "^4.17.20",
"monaco-editor": "^0.20.0",
"popper.js": "^1.16.1",
"vue": "^2.6.11",
"vuex": "^3.1.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.3.0",
"@vue/cli-plugin-eslint": "~4.3.0",
"@vue/cli-plugin-vuex": "~4.3.0",
"@vue/cli-service": "~4.3.0",
"babel-eslint": "^10.1.0",
"bootstrap": "^4.4.1",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"monaco-editor-webpack-plugin": "^1.9.0",
"sass": "^1.26.3",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<icon-bar class="icon-bar" />
<file-tree :tree-data="fileTree" :models="models" class="file-tree" />
<div ref="editor" class="editor" id="container"></div>
<console />
</div>
</template>
<script>
import IconBar from './components/IconBar.vue';
import FileTree from './components/FileTree.vue';
import Console from './components/Console';
import * as monaco from 'monaco-editor';
import _ from 'lodash';
import { defaultGradleProject } from './defaultGradleProject.js';
import { createModels, updateModels } from './utils.js';
export default {
name: 'App',
components: {
Console,
IconBar,
FileTree,
},
data: () => ({
// tree: {
// children: [
// {
// id: 1,
// path: '',
// name: 'Main.java',
// model: {
// value: '// This is your main file...',
// language: 'java',
// },
// },
// ],
// },
tree: defaultGradleProject,
editor: null,
activeNode: null,
// fileIndexStack: [],
}),
methods: {
// Updates content of current file model and saves models in Store
storeModelUpdate: _.debounce(function() {
// Get current model values
let newModel = {
id: this.$store.getters.activeNode.id,
path: this.$store.getters.activeNode.path,
name: this.$store.getters.activeNode.name,
language: this.$store.getters.activeNode.model.language,
value: this.editor.getValue(),
};
// Find current model in models array and update it
let _models = this.models;
// for (let i = 0; i < _models.length; i++) {
// if (_models[i].id === newModel.id) {
// _models[i] = newModel;
// break;
// }
// }
// // Save updated models array in Store
// this.$store.dispatch('updateAllModels', _models);
updateModels(newModel, _models, this.$store);
}, 500),
},
computed: {
fileTree() {
return {
children: this.$store.getters.fileTreeChildren,
};
},
models() {
return this.$store.getters.models;
},
},
watch: {
// Set new active model on new active node
'$store.state.activeNodeId': function() {
// If new active node is directory, no work needed
if (this.$store.getters.activeNode.children) return;
// Find model that belongs to current active node
let activeModel;
for (let i = 0; i < this.models.length; i++) {
if (this.models[i].id === this.$store.getters.activeNodeId) {
activeModel = this.models[i];
break;
}
}
this.editor.setModel(
monaco.editor.createModel(
activeModel.value,
activeModel.language,
)
);
},
},
mounted() {
// Save default gradle project in Store
this.$store.dispatch('updateFileTree', this.tree.children);
this.$store.dispatch('updateNewFileCounter', 20);
//this.createModels(this.fileTree.children);
createModels(this.fileTree.children, this.$store);
// Create Monaco-Editor and set active model
this.editor = monaco.editor.create(document.getElementById('container'), {
language: 'java'
});
this.editor.setModel(monaco.editor.createModel(
this.models[0].value,
this.models[0].language,
));
this.$store.dispatch('updateActiveNode', this.fileTree.children[0]);
this.activeNode = this.$store.getters.activeNode;
// Set editor notifiers
this.editor.onDidChangeModelContent(() => {
this.storeModelUpdate();
});
},
}
</script>
<style lang="scss">
@import "~bootstrap/dist/css/bootstrap.min.css";
body {
margin: 0;
padding: 0;
}
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-bar {
min-width: 70px;
max-width: 70px;
}
.file-tree {
width: 14%;
margin-left: 70px;
}
.editor {
height: 100%;
/*margin-left: 370px;*/
margin-left: 17%;
width: 60%;
position: absolute;
}
.monaco-editor {
margin-top: 20px;
}
.console {
height: 100%;
background: #f0f0f5;
right: 0;
width: 23.5%;
position: absolute;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 128 128" viewBox="0 0 128 128"><path fill="#02303a" d="M99.5,112.5c-0.3,0-0.5,0-0.7,0c-4.5,0-9,0-13.5,0c-0.5,0-0.8-0.2-1.1-0.5c-3.2-4-6.7-7.7-10.9-10.6
c-2.1-1.5-4.3-2.8-6.8-3.5c-2-0.6-4.1-0.9-6.2-0.4c-2.1,0.5-3.9,1.7-5.4,3.2c-1.9,1.9-3.2,4.2-4.2,6.7c-0.6,1.5-1.1,3-1.6,4.5
c-0.1,0.2-0.1,0.4-0.2,0.6c-3.8,0-7.5,0-11.4,0c-0.1-0.6-0.2-1.2-0.3-1.9c-0.4-2-1-4-2-5.8c-0.7-1.4-1.6-2.6-2.8-3.6
c-1.3-1.1-2.8-1.7-4.5-1.7c-1.3,0-2.4,0.5-3.5,1.2c-1.5,1-2.7,2.3-3.6,3.8c-1.4,2.2-2.2,4.7-2.9,7.2c-0.1,0.2-0.1,0.5-0.2,0.8
c-5,0-9.9,0-14.9,0c-0.1-0.7-0.2-1.5-0.3-2.2c-0.5-4.7-0.8-9.4-0.7-14.1c0.1-5.5,0.7-10.9,2-16.3C5,75,6.7,70.4,9.3,66.2
c3.6-5.7,8.4-9.8,14.7-12.3c0.2-0.1,0.3-0.1,0.5-0.2c0,0,0.1,0,0.2,0c0.1,0.2,0.2,0.4,0.3,0.6c1.8,4,3.7,7.9,6,11.5
c1.4,2.3,3.4,4,5.9,4.8c2.7,0.9,5.3,0.6,7.9-0.5c2.3-1,4.2-2.5,6-4.2c2.1-2,3.8-4.2,5.5-6.6c0.1-0.1,0.1-0.2,0.1-0.3
c-0.2,0.2-0.4,0.4-0.7,0.6c-2.5,2.5-5.2,4.7-8.3,6.4c-1.5,0.9-3.2,1.6-4.9,1.9c-2.5,0.5-4.8,0.2-6.8-1.6c-0.8-0.7-1.4-1.5-2-2.3
c-3-4.7-5.6-9.6-8-14.6c-0.5-1-0.9-2-1-3.2c-0.2-1.7,0.3-3.2,1.5-4.5c0.9-0.9,1.9-1.6,3.1-2.2c2.2-1.1,4.5-1.9,6.8-2.7
c3.4-1.1,6.9-1.9,10.5-2.4c4.1-0.6,8.3-0.7,12.5-0.2c9,0.9,17,4.2,24.3,9.5c2.5,1.8,5.1,3.3,8.1,4.2c11.9,3.8,21.4-4.4,23.6-12.8
c0.6-2.3,0.8-4.6-0.1-6.8c-1.3-3.4-3.6-6-7.3-7c-2.8-0.7-5.5-0.4-8.1,1c-0.5,0.3-1,0.5-1.5,0.7c-1.2,0.4-2,0.1-2.6-1
c-0.8-1.4-1.4-2.8-2.1-4.3c-0.3-0.6-0.2-1.1,0.1-1.6c0.3-0.7,0.8-1.2,1.4-1.7c1.5-1.2,3.3-2,5.3-2.4c4.9-1.1,9.5-0.4,13.9,1.8
c3.5,1.7,6.2,4.3,8.2,7.7c1.9,3.2,3.2,6.6,3.8,10.3c0.4,2.9,0.4,5.7,0.1,8.6c-0.6,5-2,9.7-4,14.3c-2.6,6-5.6,11.8-9.3,17.2
c-1.8,2.6-3.7,5.1-5.5,7.6c-1.9,2.7-3.8,5.4-5.2,8.4c-1.9,3.9-3,7.9-3.4,12.2c-0.3,3.7-0.1,7.3,0.5,11
C99.4,111.7,99.5,112.1,99.5,112.5z M91.3,61.1c0.3,2.4-0.5,4-2.7,4.9C87,66.6,85,66.1,84,64.7c-1.6-2.1-1.1-4,0.7-5.8
c-1.8-0.6-3.6-1.2-5.3-1.7c-0.4,1-0.6,2.5-0.5,3.7c0.2,2.4,1.1,4.4,3.1,5.7c2.1,1.4,4.5,2,7,1.5c2.6-0.5,4.6-2,6-4.2
c0.3-0.4,0.5-0.8,0.5-1.4C94.1,62.1,92.7,61.6,91.3,61.1z"/></svg>
\ No newline at end of file
<template>
<div class="console">
<div class="loader" id="loader"></div>
{{ consoleText }}
</div>
</template>
<script>
export default {
name: "console",
props: {},
data: function() {
return {
};
},
mounted() {
},
methods: {
},
computed: {
consoleText() {
return this.$store.getters.consoleText;
},
},
watch: {
'$store.state.isWaiting': function() {
console.log(this.$store.state.isWaiting);
if (this.$store.state.isWaiting) {
document.getElementById('loader').style.display = 'block';
}
else {
document.getElementById('loader').style.display = 'none';
}
},
},
};
</script>
<style lang="scss" scoped>
.console {
padding: 16px;
font-family: 'JetBrains Mono', 'Fira Code', Menlo, Monaco, Consolas, monospace;
height: 100%;
background: #f0f0f5;
white-space: pre;
/* (see https://www.w3schools.com/howto/howto_css_loader.asp) */
.loader {
display: none;
border: 4px solid #bbb;
border-top: 4px solid black;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
}
</style>
\ No newline at end of file
<template>
<div class="tree">
<div class="tree-header">
FILES
</div>
<ul class="tree-list">
<node-tree :node="tree"></node-tree>
</ul>
<div class="action-btn" @click="addNewFile" style="width:100px;">
<span>+ NEW FILE</span>
</div>
<div class="action-btn" @click="addNewDirectory">
<span>+ NEW DIRECTORY</span>
</div>
</div>
</template>
<script>
import NodeTree from "./NodeTree";
export default {
name: 'file-tree',
props: {
treeData: Object,
models: Array,
},
components: {
NodeTree
},
data: function() {
return {
};
},
computed: {
tree() {
return {
children: this.$store.getters.fileTreeChildren,
};
},
},
methods: {
addNewFile() {
// Determine path of new file
let currActiveNode = this.$store.getters.activeNode;
let newFilePath = ''; // set to root folder
if (currActiveNode.children) {
// if active node is directory get its path
newFilePath = `${currActiveNode.path}/${currActiveNode.name}/`;
}
let fileCounter = this.$store.getters.newFileCounter;
let file = {
id: fileCounter,
path: newFilePath,
name: 'NewFile' + fileCounter + '.java',
model: {
value: '// Enter your code here...',
language: 'java'
},
};
this.$store.dispatch('updateNewFileCounter', fileCounter + 1);
// Create Model
let model = {
id: file.id,
path: file.path,
name: file.name,
value: file.model.value,
language: file.model.language,
};
this.$store.dispatch('updateModels', model);
if (currActiveNode.children) {
// If active node is directory add new file to it
currActiveNode.children.push(file);
}
else {
// Otherwise add new file to root folder
let newTreeData = this.$store.getters.fileTreeChildren;
newTreeData.push(file);
this.$store.dispatch('updateFileTree', newTreeData);
}
},
addNewDirectory() {
// Determine path of new file
let currActiveNode = this.$store.getters.activeNode;
let newDirPath = ''; // set to root folder
if (currActiveNode.children) {
// if active node is directory get its path
newDirPath = `${currActiveNode.path}/${currActiveNode.name}/`;
}
let fileCounter = this.$store.getters.newFileCounter;
let dir = {
id: fileCounter,
path: newDirPath,
name: 'new_dir_' + fileCounter,
children: [],
};
this.$store.dispatch('updateNewFileCounter', fileCounter + 1);
if (currActiveNode.children) {
currActiveNode.children.push(dir);
}
else {
let newTreeData = this.$store.getters.fileTreeChildren;
newTreeData.push(dir);
this.$store.dispatch('updateFileTree', newTreeData);
}
},
},
};
</script>
<style lang="scss">
.tree {
/*width: 300px;*/
height: 100%;
position: absolute;
background: #f0f0f5;
}
.tree-header {
width: 100%;
height: 30px;
background: #e0e0e5;
font-weight: bold;
padding-top: 3px;
padding-left: 16px;
border-bottom: solid 1px #ccc;
}
.tree-list {
padding: 0;
}
.action-btn {
width: 150px;
font-size: 14px;
font-weight: bold;
background: #ddd;
margin-left: 20px;
margin-bottom: 10px;
border-radius: 2px;
span {
line-height: 190%;
padding-left: 9px;
}
}
.action-btn:hover {
background: #ccc;
cursor: pointer;
}
</style>
\ No newline at end of file
<template>
<div class="icon-bar">
<div id="runBtn" type="button" class="btn btn-icon" @click="runProgram" :disabled="isDisabled">
<svg id="runBtnIcon" class="bi bi-play" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M10.804 8L5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 010 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z" clip-rule="evenodd"/>
</svg>
</div>
<div id="testBtn" type="button" class="btn btn-icon" @click="testProgram">
<svg id="testBtnIcon" class="bi bi-lightning" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M11.251.068a.5.5 0 01.227.58L9.677 6.5H13a.5.5 0 01.364.843l-8 8.5a.5.5 0 01-.842-.49L6.323 9.5H3a.5.5 0 01-.364-.843l8-8.5a.5.5 0 01.615-.09zM4.157 8.5H7a.5.5 0 01.478.647L6.11 13.59l5.732-6.09H9a.5.5 0 01-.478-.647L9.89 2.41 4.157 8.5z" clip-rule="evenodd"/>
</svg>
</div>
<div type="button" class="btn btn-icon" @click="generateGradleProject" :disabled="isDisabled">
<img src="../assets/gradle.svg"
alt="Gradle Icon"
style="width:36px; margin-top:10px;">
</div>
</div>
</template>
<script>
import JSZip from 'jszip';
import axios from 'axios';
import { saveAs } from 'file-saver';
export default {
name: 'icon-bar',
data: () => ({
fileIndexStack: [],
editor: null,
activeNode: null,
isGradleProject: false,
isDisabled: false,
gradleFileTree: {
children: [
{
id: 1,
path: '',
name: 'build-JITPACK.gradle',
model: {
value: 'plugins {\n' +
'\tid \'java\'\n' +
'}\n' +
'\n' +
'ext.jitpackGroup = \'com.github.junit-team.junit5\'\n' +
'ext.jitpackVersion = \'master-SNAPSHOT\'\n' +
'// ext.jitpackVersion = \'experiments~parallel-execution-SNAPSHOT\'\n' +
'\n' +
'repositories {\n' +
'\tmavenCentral()\n' +
'\tmaven { url \'https://jitpack.io\' }\n' +
'}\n' +
'\n' +
'dependencies {\n' +
'\ttestImplementation("${jitpackGroup}:junit-jupiter:${jitpackVersion}")\n' +
'}\n' +
'\n' +
'test {\n' +
'\tuseJUnitPlatform()\n' +
'\ttestLogging {\n' +
'\t\tevents "passed", "skipped", "failed"\n' +
'\t}\n' +