Skip to content

Commit 3b86ed0

Browse files
committed
Finalizing MLE Exploration
SQUASHED: AUTO-COMMIT-demos-markdown-mle-workspaces.md,
1 parent 3f1b8aa commit 3b86ed0

File tree

1 file changed

+151
-1
lines changed

1 file changed

+151
-1
lines changed

demos/markdown/mle-workspaces.md

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,154 @@
11
# Workspace Example
22

33
This is an Example of a workspace embedded in HTML/Markdown that will persist it's code in browser local storage.
4-
<lively-script><script>import focalStorage from 'src/external/focalStorage.js'; import {SocketSingleton} from 'src/components/mle/socket.js'; const idMap = new Map(); const enclosingDiv = <div />; var mle = {}; async function startUp(){ await SocketSingleton.get(); let i = 0; while(await focalStorage.getItem(`markdown_workspace_${i}`)){ await new Pane(i, await focalStorage.getItem(`markdown_workspace_${i}_kind`)).create(); i++; } } class Pane { constructor(id, kind){ if(id !== undefined){ this._id = id; this.kind = kind; } else { this._id = idMap.size; } idMap.set(this.textStorageId, this); } onDoIt() { this.saveText() this.workspace.tryBoundEval(this.workspace.value) } async onReset() { if(this.kind) this.socket = await SocketSingleton.reset(); this.logarea.value = "LOGS"; this.drawarea.innerHTML = ""; } get defaultText() { return "sql`SELECT * FROM students`" } get textStorageId() { return `markdown_workspace_${this._id}` } async loadText() { var loaded = await focalStorage.getItem(this.textStorageId); if (loaded) return loaded; return this.defaultText; } async saveText() { focalStorage.setItem(this.textStorageId, this.workspace.value); focalStorage.setItem(`${this.textStorageId}_kind`, this.kind); } log(s) { this.logarea.value += s + ""; } async create() { // #TODO #META style and pre tags are problematic in Markdown scripts this.kind = this.kind === undefined ? await lively.confirm("MLE Workspace? Ok for yes, Cancel for No.") : this.kind; var style = document.createElement("style"); style.textContent = ` lively-code-mirror { border: 1px solid gray; flex: 4; }`; var buttons = <div> <button click={() => {this.onDoIt()} }>DoIt</button> <button click={() => {this.onReset()} }>reset</button> </div>; this.workspace = await (<lively-code-mirror></lively-code-mirror>); this.workspace.value = await this.loadText(); this.workspace.doitContext = this; this.logarea = <textarea disabled style="flex: 2;"/>; this.logarea.value = "LOGS"; this.drawarea = <div></div>; if(this.kind){ this.workspace.boundEval = async function(s) { this.socket = this.socket || await SocketSingleton.get(); this.socket.emit("test", {id: this.textStorageId, func: "evaluate", parameters: [s]}); const value = await new Promise((res) => { this.socket.on("result", r => { if(!r) return; if(r.id !== this.textStorageId) return; console.log(r.data) res(JSON.parse(r.data)); }); }); this.outData = value; Object.defineProperty(window, `$${this._id}`, {configurable: true, value}); this.log(JSON.stringify(value)); this.saveText(); return {value}; } this.workspace.boundEval = this.workspace.boundEval.bind(this); } enclosingDiv.appendChild( <div style="padding: 10px; width:90%;"> {style} <h4>{this.kind ? "MLE" : "DOM"} Workspace ${this._id}</h4> {buttons} <div style="display: flex;"> {this.workspace} {this.logarea} </div> {this.drawarea} </div> ); } } startUp().then(t => <div> <button click={() => new Pane().create()}>New workspace</button> {enclosingDiv} </div>)</script> </lively-script>
4+
<script>
5+
import focalStorage from 'src/external/focalStorage.js';
6+
import {SocketSingleton} from 'src/components/mle/socket.js';
7+
const idMap = new Map();
8+
const enclosingDiv = <div />;
9+
var mle = {};
10+
async function startUp(){
11+
await SocketSingleton.get();
12+
let i = 0;
13+
while(await focalStorage.getItem(`markdown_workspace_${i}`)){
14+
await new Pane(i, await focalStorage.getItem(`markdown_workspace_${i}_kind`)).create();
15+
i++;
16+
}
17+
}
18+
class Pane {
19+
constructor(id, kind){
20+
if(id !== undefined){
21+
this._id = id;
22+
this.kind = kind;
23+
} else {
24+
this._id = idMap.size;
25+
}
26+
idMap.set(this.textStorageId, this);
27+
}
28+
29+
onDoIt() {
30+
this.saveText();
31+
this.workspace.tryBoundEval(this.workspace.value);
32+
}
33+
34+
async onReset() {
35+
if(this.kind) this.socket = await SocketSingleton.reset();
36+
this.logarea.value = "LOGS";
37+
this.drawarea.innerHTML = "";
38+
}
39+
40+
get defaultText() {
41+
return "sql`SELECT * FROM students`"
42+
}
43+
44+
get textStorageId() {
45+
return `markdown_workspace_${this._id}`
46+
}
47+
48+
async loadText() {
49+
var loaded = await focalStorage.getItem(this.textStorageId);
50+
if (loaded) return loaded;
51+
return this.defaultText;
52+
}
53+
54+
async saveText() {
55+
focalStorage.setItem(this.textStorageId, this.workspace.value);
56+
focalStorage.setItem(`${this.textStorageId}_kind`, this.kind);
57+
}
58+
59+
log(s) {
60+
this.logarea.value += s + "";
61+
}
62+
63+
async create() {
64+
// #TODO #META style and pre tags are problematic in Markdown scripts
65+
this.kind = this.kind === undefined ? await lively.confirm("MLE Workspace? Ok for yes, Cancel for No.") : this.kind;
66+
var style = document.createElement("style");
67+
style.textContent = ` lively-code-mirror { border: 1px solid gray; flex: 4; }`;
68+
var buttons = <div>
69+
<button click={() => {this.onDoIt()} }>DoIt</button>
70+
<button click={() => {this.onReset()} }>reset</button>
71+
</div>;
72+
this.workspace = await (<lively-code-mirror></lively-code-mirror>);
73+
this.workspace.value = await this.loadText();
74+
this.workspace.doitContext = this;
75+
this.logarea = <textarea disabled style="flex: 2;"/>;
76+
this.logarea.value = "LOGS";
77+
this.drawarea = <div></div>;
78+
if(this.kind){
79+
this.workspace.boundEval = async function(s) {
80+
this.socket = this.socket || await SocketSingleton.get();
81+
this.socket.emit("test", {
82+
id: this.textStorageId,
83+
func: "evaluate",
84+
parameters: [s]
85+
});
86+
const value = await new Promise((res) => {
87+
this.socket.on("result", r => {
88+
if(!r) return;
89+
if(r.id !== this.textStorageId) return;
90+
res(JSON.parse(r.data));
91+
});
92+
});
93+
this.outData = value;
94+
Object.defineProperty(window, `$${this._id}`, {configurable: true, value});
95+
this.log(JSON.stringify(value));
96+
this.saveText();
97+
return {value};
98+
}
99+
this.workspace.boundEval = this.workspace.boundEval.bind(this);
100+
}
101+
102+
enclosingDiv.appendChild(<div style="padding: 10px; width:90%;">
103+
{style}
104+
<h4>{this.kind ? "MLE" : "DOM"} Workspace ${this._id}</h4>
105+
{buttons}
106+
<div style="display: flex;">
107+
{this.workspace}
108+
{this.logarea}
109+
</div>
110+
{this.drawarea}
111+
</div>);
112+
}
113+
}
114+
115+
startUp().then(t => <div>
116+
<button click={() => new Pane().create()}>New workspace</button>
117+
{enclosingDiv}
118+
</div>)
119+
</script>
120+
121+
Example Query:
122+
```
123+
const projects = sql`SELECT * FROM projects where id < 20`.map(
124+
({id, url}) => {
125+
const prs = sql`SELECT * FROM pull_requests where head_repo_id=${id}`.map(({id}) => {
126+
const events = sql`SELECT * FROM pull_request_history where pull_request_id=${id}`.reduce(
127+
({opened, last}, {created_at, action}) => {
128+
if(action.startsWith("opened")){
129+
if(!opened || opened > created_at) {
130+
return {opened: created_at, last};
131+
}
132+
}
133+
if(action.startsWith("closed") || action.startsWith("merged")){
134+
if(!last || last < created_at){
135+
return {opened, last: created_at}
136+
}
137+
}
138+
return {opened, last};
139+
}, {opened: false, last: false});
140+
return events.last - events.opened;
141+
}).reduce(({count, sum}, curr) => ({count: count+1, sum: sum+curr}), {count: 0, sum: 0});
142+
return {repo: url, avg: prs.sum/prs.count};
143+
}
144+
).reduce((prev, curr) => {
145+
if(!curr.avg || curr.avg <0) return prev;
146+
if(prev.length < 3) return [...prev, curr];
147+
const t = prev.sort((a, b) => a.avg-b.avg);
148+
if(t[0].avg < curr.avg){
149+
[...t.slice(1), curr]
150+
}
151+
return t;
152+
}, []).map(({repo, ...t}) => ({...t, repo:repo.split("/").slice(4).join("/")}));
153+
projects
154+
```

0 commit comments

Comments
 (0)