Added lang design notes from collabedit.

This commit is contained in:
Matija Sosic 2020-05-22 17:33:10 +02:00
parent 64068a2655
commit a542ad2b95
3 changed files with 240 additions and 0 deletions

View File

@ -0,0 +1,105 @@
entity Task {
done : Boolean,
description : String
}
// TODO: Opcenito smisliti kako se mijesa javascript kod sa Wasp kodom.
// Uglavnom se svodimo na to da Wasp-u dajemo funkcije.
// Smisli kako mu ih se sve moze dati, i kako da one mogu raditi vise manje
// bilo sto, te sto je sa dependency injectionim, importovima, constraintovima
// na to sto rade ili vracaju, ... .
routes {
route "/" -> HomePage @default
route "/task/:taskId" -> TaskPage // Ovo je jednostavna deklarativna verzija, parametri se sami salju u TaskPage.
// Ovo je naprednija, ne-deklarativna verzija.
// TODO: Kako znamo da je ova funkcija pozvala page? Ili mozda to niti ne provjeravamo.
// Otkud joj uopce taj goToPage? Da joj to injectamo?
route "/task/:taskId" -> (taskId) => { goToPage("TaskPage", taskId) }
route "/task/bytext/:query" -> ?
route "/home" -> route "/"
route "*" -> Page404()
}
page HomePage {
route = /home @default
component = Main
}
page TaskPage (taskId) {
//route = '/task/:taskId'
component = TaskView(taskId) // HM
}
component TaskView (taskId) {
source: 'asdf.js'
queries: {
task: getTask(taskId)
}
}
goToPage(TaskPage, taskId) -> url := /task/taskId
/task/4
@query @acl admin
getAllTasks = query ...
// Pitanja:
// 1. Moze li query imati argumente (na razini Wasp-a)?
// Teoretski mozemo reci da query nemaju argumente.
// Mislim da to bas i ne bi bilo prakticno ipak, iako bi moglo raditi vjerojatno.
// 2.
@query getAllTasksForUser ~ (Task)
{=js
(Task, user, params) => {
return Task.find({author: user.id})
}
js=}
// TODO(martin): how do we import js stuff?
// Pitanje: Koji je odnos injectanih stvari i argumenata? Ovako sad ne izgleda bas jasno sto je injectano a sto je argument.
// Iako je i to mozda ok posto su injectane stvari i dalje argumenti, ali ipak hm.
@action ~ (Task) // -> Stuff from here gets injected. We love injecting as it enables testing.
{=js
function addNewTask (Task, newTaskData) {
Task.insert(newTask)
}
js=}
// Do we add this to component under "actions"?
// That way it would be inject as prop (we have to do that),
// but that is cool because that makes code decoupled and all.
// Alternative is that user imports it into react component.
// But are they importing directly function then, or are they
// importing an action? If they are importing an action (what does that even mean),
// that needs to be in some special manner.
// What does it even mean that this is action, if we are not aware of any side effect,
// does it make sense to declare it as an action, should it instead just be function?
@action
{=js
function sendAnEmail (text) {
sendgrid.sendEmail(text) // Kako smo importali sendgrid?
}
js=}
//action addNewTask ...
component Main {
source = "mycomp.js"
queries = {tasks: getAllTasksForUser(f)} // This ends up as prop.
actions = [addNewTask] // This ends up as prop.
}
component MainAdmin {
source = "mycomp.js"
queries = {allTasks: getAllTasks}
}
---------------------------------------
Entityi (Wasp) -> Prisma, ... .
Komponente (React)
Operacije (JS) -> query vs akcija, server vs client, custom vs built-in.

View File

@ -0,0 +1,55 @@
onMount = fetchTasksAction()
render () {
button title="refresh" onClick = fetchTasksAction
button title="onlyDoneTasks" onClick = fetchOnlyDoneTasksAction
return tasks
}
connect(state)
tasks: () => getTasksSel(state)
onlyDoneTasks = () => ...
fetchTasksAction: fetchTasksAction
render () {
tasks = if nesto then doQuery(GET_TASKS, args) else doQuery(GET_TASKS, other args)
return tasks
// Problem?: We fetch all queries before component even starts, we don't fetch them lazily. Could we solve that with annotations like @default, @required and similar? So those would say: don't load it upfront, or do load it upfront, or use this as default value until something is loaded, ...
// Another problem: While in Redux and Apollo, dev can choose when and under which condition to fetch certain pieces of state,
// while we say: this is what needs to be fetched upfront for this component and that is it.
// Can we solve this by providing user with actions that can run queries? So if they want to manually refresh certain query from the component,
// they could define an action that calls that query in it (with refetch on true) and then call that action from the component, conditionally or whatever.
queries: {
tasks: getTasks(arg) @default([]) @required
}
render () {
button title="refresh" onClick = this.props.getTasks(otherArg)
button title="onlyDoneTasks" onClick = this.props.getOnlyDoneTasks()
this.props.tasks
}
// Komponenta slusa i koristi u zivotu x querya, kondicionalno ili kako god. Takodjer i radi odredjene akcije.
// Sto ako ona zeli neki query na silu pokrenuti / refetchati / refreshati?
// Sto ako zeli neki query "lazy"/"on demand" izvrsiti -> dakle da se on desi tek kad joj treba, da se ne executa odmah cim se komponenta loada ili nesto.
// Sto ako komponenta zeli "na zivo" promijeniti koje querye slusa (na temelju propova ili necega)? ---> TO SE CINI PROBLEM HM.
// Ostali to rade tako da: ako se promjene propovi komponente, onda imas priliku redefinirati selectore/querye.
// Da napravimo da definicija vezanih querya ovisi o propovima, da je funkcija propova? A sto je s lokalnim stateom?
// This could be solution, but it seems too "black boxed" -> if it is JS black box and it is happening in runtime, how are we going to translate this into smth else?
queries: (props, state) => {
return {
tasks: getTasks(props.taskId)
}
}

View File

@ -0,0 +1,80 @@
// TODO app in Wasp - try #1
// ------- main.wasp
page MainPage {
route: "/",
component: MainPageComponent
}
component MainPageComponent {
source: "MainPageComponent.js",
queries: {
tasks: getAllTasks
}
}
entity Task {
description: String,
isDone: Boolean
}
query getAllTasks {
uses: [Task],
fn: {=js
(Task) => {
return Task.find({})
}
js=}
// OR source: { import: "getAllTasks", from: "queries.js" }
}
// ------- MainPageComponent.js
import React from 'react'
export default class MainPageComponent extends React.Component {
static propTypes = {
tasks: PropTypes.array.object
}
render() {
return <div>
{ this.props.tasks.map(t => (
<div>
<span> { t.isDone } </span>
<span> { t.description } </span>
</div>
))}
</div>
}
}
// -------- CLI
wasp init
wasp install
wasp start
// -------- Ideas
// TODO: When inline JS, figure out how to import. Existing system? Smth new?
query getAllTasks ~ Task {=js
(Task) => {
return Task.find({})
}
js=}
@uses(Task)
query getAllTasks (Task) {
return Task.find({})
}