🎁 feat: create starter file for lesson

This commit is contained in:
ysandler 2020-09-12 17:14:51 -05:00 committed by Joshua Shoemaker
parent 30b6094619
commit bd2ca64f9c
16 changed files with 218 additions and 100 deletions

View File

@ -1,24 +0,0 @@
{
"courseName": "Test Lesson",
"documentationUrl": "https://brightScreen.io/courses/Test-Lesson/",
"lessons": [
{
"name": "Lesson One",
"location": "lessonOne/indexTest.js",
"description": "Test Description for Lesson 1",
"executionPrefix": "node",
"fileExtention": "js",
"replacementSubstring": "USER_CODE",
"documentationUrl": "https://brightScreen.io/courses/Test-Lesson/lesson-One/"
},
{
"name": "Lesson Two",
"location": "lessonTwo/indexTest.js",
"description": "Test Description for Lesson 2",
"executionPrefix": "node",
"fileExtention": "js",
"replacementSubstring": "USER_CODE",
"documentationUrl": "https://brightScreen.io/courses/Test-Lesson/lesson-Two/"
}
]
}

View File

@ -1,23 +0,0 @@
const codeFromUser = USER_CODE
const test = () => {
const input = 'yo'
const expectedOutput = 'yo'
const testedValue = codeFromUser(input)
if (testedValue === expectedOutput) {
const message = {
didPass: true,
message: 'Passed Test 1'
}
console.log(JSON.stringify(message))
} else {
const message = {
didPass: false,
message: 'Did not return expected value'
}
console.log(JSON.stringify(message))
}
}
test()

View File

@ -1,18 +0,0 @@
const codeFromUser = USER_CODE || function() { console.log('No User code Provided') }
const test = () => {
const input = 'yo'
const expectedOutput = 'yo'
const testedValue = codeFromUser(input)
if (testedValue === expectedOutput) {
console.log('Passed Test 2')
return true
} else {
console.log('Failed Test Two')
return false
}
}
test()

View File

@ -1,25 +0,0 @@
const codeFromUser = function (props) {
return props
}
const test = () => {
const input = 'yo'
const expectedOutput = 'yo'
const testedValue = codeFromUser(input)
if (testedValue === expectedOutput) {
const message = {
didPass: true,
message: 'Passed Test 1'
}
console.log(JSON.stringify(message))
} else {
const message = {
didPass: false,
message: 'Did not return expected value'
}
console.log(JSON.stringify(message))
}
}
test()

View File

@ -1,3 +0,0 @@
function (props) {
return props
}

13
package-lock.json generated
View File

@ -275,6 +275,14 @@
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true
},
"axios": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
"integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@ -789,6 +797,11 @@
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"follow-redirects": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
"integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",

View File

@ -30,37 +30,83 @@
"name": "brightScreen",
"icon": "src/media/logoBlue.svg",
"contextualTitle": "brightScreen"
},
{
"id": "brightScreenCourses",
"name": "brightScreen Courses",
"contextualTitle": "courses"
}
]
},
"commands": [
{
"command": "brightscreen.startBrightScreen",
"title": "Start Bright Screen",
"title": "BrightScreen: Start BrightScreen",
"icon": {
"light": "src/media/logoBlue.svg",
"dark": "src/media/logoBlue.svg"
}
},
{
"command": "brightscreen.searchForCourses",
"title": "BrightScreen: Search For Courses",
"icon": {
"light": "src/media/searchIcon.svg",
"dark": "src/media/searchIcon.svg"
}
},
{
"command": "brightscreen.runTests",
"title": "Run Tests",
"title": "BrightScreen: Run Tests",
"icon": {
"light": "src/media/runCommand.svg",
"dark": "src/media/runCommand.svg"
}
},
{
"command": "brightscreen.createStarterFileForLesson",
"title": "BrightScreen: Create Start File For Lesson",
"icon": {
"light": "src/media/createIcon.svg",
"dark": "src/media/createIcon.svg"
}
},
{
"command": "brightscreen.downloadCourse",
"title": "BrightScreen: Download Course",
"icon": {
"light": "src/media/downloadIcon.svg",
"dark": "src/media/downloadIcon.svg"
}
}
],
"menus": {
"view/title": [
{
"command": "brightscreen.startBrightScreen",
"when": "view == brightScreen",
"group": "navigation"
},
{
"command": "brightscreen.searchForCourses",
"when": "view == brightScreenCourses",
"group": "navigation"
}
],
"view/item/context": [
{
"command": "brightscreen.runTests",
"when": "view == brightScreen",
"group": "inline"
},
{
"command": "brightscreen.createStarterFileForLesson",
"when": "view == brightScreen",
"group": "inline"
},
{
"command": "brightscreen.downloadCourse",
"when": "view == brightScreenCourses",
"group": "inline"
}
]
@ -68,7 +114,7 @@
"viewsWelcome": [
{
"view": "brightScreen",
"contents": "No Course Selected\n[Find Them Here](https://brightScreen.io/)"
"contents": "Start brightScreen or Search for Courses\n[Documentation](https://brightScreen.io/)"
}
]
},
@ -92,5 +138,8 @@
"mocha": "^8.0.1",
"typescript": "^3.8.3",
"vscode-test": "^1.4.0"
},
"dependencies": {
"axios": "^0.20.0"
}
}

View File

@ -5,6 +5,7 @@ interface LessonInterface {
executionPrefix: string,
fileExtention: string,
replacementSubstring: string,
starterFileLocation: string,
documentationUrl: string
}

View File

@ -0,0 +1,44 @@
import * as vscode from 'vscode'
class CourseProvider implements vscode.TreeDataProvider<CourseTreeItem> {
courses: {_id: string, name:string, repo: string}[]
constructor(courses: {_id: string, name:string, repo: string}[] ) {
this.courses = courses
}
getTreeItem (element: CourseTreeItem): vscode.TreeItem {
return element
}
getChildren (): CourseTreeItem[] {
const treeItems: CourseTreeItem[] = this.courses.map(c => {
return new CourseTreeItem(
c.name,
vscode.TreeItemCollapsibleState.None,
c.repo,
)
})
return treeItems || []
}
}
class CourseTreeItem extends vscode.TreeItem {
constructor (
public readonly label: string,
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
public readonly repo: string,
) {
super(label, collapsibleState)
}
get tooltip (): string {
return this.repo
}
iconPath = {
light: `../media/downloadIcon.svg`,
dark: '../media/downloadIcon.svg'
}
}
export default CourseProvider

View File

@ -19,7 +19,8 @@ class LessonsProvider implements vscode.TreeDataProvider<LessonTreeItem> {
l.executionPrefix,
l.fileExtention,
l.replacementSubstring,
l.location
l.location,
l.starterFileLocation
)
})
return treeItems
@ -34,7 +35,8 @@ class LessonTreeItem extends vscode.TreeItem {
public readonly executionPrefix: string,
public readonly fileExtention: string,
public readonly replacementSubstring: string,
public readonly location: string
public readonly location: string,
public readonly starterFileLocation: string
) {
super(label, collapsibleState)
}

View File

@ -0,0 +1,29 @@
import * as vscode from 'vscode'
import { exec } from 'child_process'
function installCourse (workspaceFolder: string, repo: string, outputChannel: vscode.OutputChannel): void {
const executionString = `git clone ${repo} ${workspaceFolder}/.brightScreen`
outputChannel.show()
const gitInstallProcess = exec(executionString, (error, stdout, stderr) => {
if (stderr) {
console.log('stderr: ', stderr)
outputChannel.appendLine(stderr)
return
}
if (error !== null) {
console.log('stderr: ', error)
outputChannel.appendLine('error')
return
}
outputChannel.append(stdout)
})
gitInstallProcess.on('close', () => {
console.log('Git Clone Process Closed')
vscode.window.showInformationMessage('Course successfully installed ot .brightScreen')
})
}
export default installCourse

View File

@ -0,0 +1,28 @@
import * as vscode from 'vscode'
import axios from 'axios'
import CourseProvider from './CourseProvider'
function setupCoursesTree (): void {
let courses: any
try {
axios.get('http://localhost:5000/api/courses')
.then(response => {
console.log(response.data)
courses = response.data
try {
vscode.window.registerTreeDataProvider('brightScreenCourses', new CourseProvider(courses))
} catch (err) {
console.log(err)
vscode.window.showErrorMessage('Could Not Create BrightScreen Course List')
return
}
})
} catch (err) {
console.log(err)
vscode.window.showErrorMessage('Could Not Access BrightScreen Course List')
return
}
}
export default setupCoursesTree

View File

@ -2,17 +2,21 @@ import * as vscode from 'vscode'
import * as fs from 'fs'
import BrightScreen from './Entities/BrightScreen'
import setupBrightScreen from './UseCases/setupBrightScreen'
import setupCoursesTree from './UseCases/setupCoursesTree'
import LessonInterface from './Interfaces/LessonInterface'
import { exec } from 'child_process'
import installCourse from './UseCases/installCourse'
export function activate(context: vscode.ExtensionContext) {
console.log('brightscreen is now active')
let brightScreen: BrightScreen
let workspaceFolder: string
let workspaceFolder: string = vscode.workspace.rootPath || ''
let lessons: LessonInterface[]
const outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel('brightScreen')
setupCoursesTree()
const startupBrightScreenCommand = vscode.commands.registerCommand('brightscreen.startBrightScreen', () => {
setupBrightScreen()
brightScreen = BrightScreen.getInstance()
@ -20,6 +24,44 @@ export function activate(context: vscode.ExtensionContext) {
lessons = brightScreen.lessons
})
const searchForCoursesComand = vscode.commands.registerCommand('brightscreen.searchForCourses', async () => {
// console.log(await vscode.window.showInputBox())
setupCoursesTree()
})
const downloadCourseComand = vscode.commands.registerCommand('brightscreen.downloadCourse', async (treeItemContext) => {
console.log(treeItemContext)
const repo = treeItemContext.repo
// console.log(await vscode.window.showInputBox())
if (brightScreen) {
vscode.window.showErrorMessage('brightScreen Course is already installed')
return
}
installCourse(workspaceFolder, repo, outputChannel)
// setupBrightScreen()
})
const createStarterFileForLesson = vscode.commands.registerCommand('brightscreen.createStarterFileForLesson', treeItemContext => {
let starterFileAsString :string
try{
starterFileAsString = fs.readFileSync(`${workspaceFolder}/.brightScreen/${treeItemContext.starterFileLocation}`, 'utf-8')
} catch (err) {
console.log(err)
vscode.window.showErrorMessage('Issue reading starter file provided by course.')
return
}
try {
vscode.window.activeTextEditor?.edit(builder => {
builder.insert(new vscode.Position(0, 0), starterFileAsString)
// builder.replace(vscode.window?.activeTextEditor.selection, starterFileAsString);
})
} catch (err) {
console.log(err)
vscode.window.showErrorMessage('Coule Not create starter file for the lesson.')
return
}
})
const runTestCommand = vscode.commands.registerCommand('brightscreen.runTests', (treeItemContext) => {
let lessonCodeAsString: string
try {
@ -96,7 +138,7 @@ export function activate(context: vscode.ExtensionContext) {
})
})
context.subscriptions.push(...[runTestCommand, startupBrightScreenCommand])
context.subscriptions.push(...[runTestCommand, startupBrightScreenCommand, searchForCoursesComand, downloadCourseComand])
}
export function deactivate() {}

1
src/media/createIcon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><linearGradient id="MfgCt4CrXjLjJcV7OI1rra" x1="6" x2="42" y1="24" y2="24" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#33bef0"/><stop offset="1" stop-color="#0a85d9"/></linearGradient><path fill="url(#MfgCt4CrXjLjJcV7OI1rra)" d="M40,6H8C6.895,6,6,6.895,6,8v32c0,1.105,0.895,2,2,2h32c1.105,0,2-0.895,2-2V8 C42,6.895,41.105,6,40,6z"/><path d="M42,8c0-1.105-0.895-2-2-2h-3.89L18.812,23.302c-0.136,0.136-0.233,0.307-0.28,0.494l-1.69,6.707 c-0.1,0.395,0.259,0.754,0.654,0.654l6.708-1.688c0.187-0.047,0.358-0.144,0.495-0.281L42,11.884V8z" opacity=".05"/><path d="M42,8c0-1.105-0.895-2-2-2h-3.183L19.226,23.595c-0.112,0.112-0.192,0.252-0.23,0.406l-1.504,5.97 c-0.082,0.325,0.213,0.619,0.537,0.537l5.97-1.503c0.154-0.039,0.294-0.118,0.406-0.23L42,11.177V8z" opacity=".07"/><path fill="#c94f60" d="M47.671,3.211l-2.882-2.882c-0.438-0.439-1.152-0.439-1.591,0l-1.356,1.358l4.472,4.472l1.358-1.356 C48.11,4.363,48.11,3.651,47.671,3.211"/><path fill="#f0f0f0" d="M19.504,24.024L18,30l5.977-1.505l0.627-5.185L19.504,24.024z"/><path fill="#edbe00" d="M42.499,9.972L23.978,28.494l-4.472-4.472L38.027,5.5L42.499,9.972z"/><linearGradient id="MfgCt4CrXjLjJcV7OI1rrb" x1="42.168" x2="42.168" y1="1.968" y2="10.201" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#dedede"/><stop offset="1" stop-color="#d6d6d6"/></linearGradient><path fill="url(#MfgCt4CrXjLjJcV7OI1rrb)" d="M38.023,5.501l3.814-3.816l4.475,4.472l-3.814,3.816L38.023,5.501z"/><path fill="#575757" d="M18.762,26.978L18,30l3.021-0.762L18.762,26.978z"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#BBDEFB" d="M37,17C37,17,37,17,37,17c0-0.2,0-0.3,0-0.5c0-3.6-2.9-6.5-6.5-6.5c-1.7,0-3.2,0.7-4.4,1.7C24.7,8.9,21.8,7,18.5,7c-4.7,0-8.5,3.8-8.5,8.5c0,0.5,0.1,1,0.1,1.5C6.7,17.4,4,20.3,4,23.9c0,3.9,3.1,7,7,7c0,0,0.1,0,0.1,0C11.4,31,11.7,31,12,31h25c3.9,0,7-3.1,7-7C44,20.1,40.9,17,37,17z"/><path fill="#3F51B5" d="M27 33L27 19 21 19 21 33 16 33 24 42 32 33z"/></svg>

After

Width:  |  Height:  |  Size: 462 B

1
src/media/searchIcon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="16px" height="16px"><path fill="#b6c9d6" d="M6.998,77.5c-1.202,0-2.331-0.468-3.181-1.317c-1.753-1.753-1.753-4.607,0-6.36l36.828-35.11 l4.656,4.661L10.17,76.191C9.329,77.032,8.199,77.5,6.998,77.5z"/><path fill="#788b9c" d="M40.636,35.411l3.966,3.97L9.825,75.829C9.069,76.584,8.066,77,6.998,77 c-1.068,0-2.072-0.416-2.827-1.171c-1.559-1.559-1.559-4.095-0.017-5.637L40.636,35.411 M40.654,34.013L3.464,69.469 c-1.952,1.952-1.951,5.116,0,7.068C4.44,77.512,5.719,78,6.998,78c1.279,0,2.558-0.488,3.534-1.464L46,39.366L40.654,34.013 L40.654,34.013z"/><g><path fill="#d1edff" d="M52,53.5c-14.061,0-25.5-11.439-25.5-25.5S37.939,2.5,52,2.5S77.5,13.939,77.5,28 S66.061,53.5,52,53.5z"/><path fill="#788b9c" d="M52,3c13.785,0,25,11.215,25,25S65.785,53,52,53S27,41.785,27,28S38.215,3,52,3 M52,2 C37.641,2,26,13.641,26,28s11.641,26,26,26s26-11.641,26-26S66.359,2,52,2L52,2z"/></g></svg>

After

Width:  |  Height:  |  Size: 937 B