diff --git a/waspc/lang-design/todo-22-May-20/1st-brainstorming.wasp b/waspc/lang-design/todo-22-May-20/1st-brainstorming.wasp new file mode 100644 index 000000000..00cd8580d --- /dev/null +++ b/waspc/lang-design/todo-22-May-20/1st-brainstorming.wasp @@ -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. + diff --git a/waspc/lang-design/todo-22-May-20/refreshing.wasp b/waspc/lang-design/todo-22-May-20/refreshing.wasp new file mode 100644 index 000000000..61260af27 --- /dev/null +++ b/waspc/lang-design/todo-22-May-20/refreshing.wasp @@ -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) + } +} + diff --git a/waspc/lang-design/todo-22-May-20/step-by-step.wasp b/waspc/lang-design/todo-22-May-20/step-by-step.wasp new file mode 100644 index 000000000..70d9c282b --- /dev/null +++ b/waspc/lang-design/todo-22-May-20/step-by-step.wasp @@ -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
+ { this.props.tasks.map(t => ( +
+ { t.isDone } + { t.description } +
+ ))} +
+ } +} + + + + + + +// -------- 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({}) +}