From 038e2151fd2325a32d5432b53fa6f73374d2d781 Mon Sep 17 00:00:00 2001 From: Philippe PITTOLI Date: Thu, 5 Dec 2019 02:28:17 +0100 Subject: [PATCH] better architecture lol --- client/index.ls | 80 ++++----- client/project.ls | 150 ++++------------- client/task.ls | 349 ++++++++++++++++++++-------------------- client/todowebsocket.ls | 40 ++--- 4 files changed, 254 insertions(+), 365 deletions(-) diff --git a/client/index.ls b/client/index.ls index c71bf05..ee84ac2 100644 --- a/client/index.ls +++ b/client/index.ls @@ -19,9 +19,9 @@ # widgets: # navbar: [return to list button] [logout] # element button: -# [todo list name] +# [project list name] # or -# [todo list name] [RIGTHS] [DELETE] +# [project list name] [RIGTHS] [DELETE] # # page 2: # display: @@ -47,7 +47,7 @@ Modal = require "./modal.ls" projector = create-projector! model = { - # view: login, todo-list, todo, network-error (TODO: other views, such as rights) + # view: login, project-list, project, network-error (TODO: other views, such as rights) # XXX FIXME TODO: TESTING THINGS current-view: "login" @@ -58,7 +58,7 @@ model = { # { uid => user data } users: {} - todo-list: [] + project-list: [] port: 9999 authd-url: undefined @@ -69,9 +69,6 @@ model = { previous-error: undefined error: undefined - - # TODO: authentication token - jwt: undefined } model.authd-url = @@ -124,9 +121,9 @@ model.authd-ws.user-on-socket-close ++= [ authd-on-websocket-close ] # authd message handlers model.authd-ws.add-event-listener \token, (message) -> - model.jwt := message.token - model.current-view := "todo-list" - model.todod-ws.list-lists model.jwt + model.current-view := "project-list" + model.todod-ws.token := message.token + model.todod-ws.list-lists! projector.schedule-render! model.authd-ws.add-event-listener \error, (message) -> @@ -165,29 +162,29 @@ model.todod-ws.user-on-socket-close ++= [ on-websocket-close ] model.todod-ws.add-event-listener \lists-list, (message) -> console.log message - model.todo-list := message.lists.map (x) -> - Project.new x, model + model.project-list := message.lists.map (x) -> + Project x, model.todod-ws projector.schedule-render! model.todod-ws.add-event-listener \new-list, (message) -> console.log message - model.todo-list := model.todo-list ++ [ (Project.new message.list, model) ] + model.project-list := model.project-list ++ [ (Project message.list, model.todod-ws) ] projector.schedule-render! model.todod-ws.add-event-listener \tasks, (message) -> console.log message - model.todo-list.find((.id == message.list)).tasks := message.tasks + model.project-list.find((.id == message.list)).tasks := message.tasks projector.schedule-render! model.todod-ws.add-event-listener \list-removed, (message) -> console.log message - if model.current-view == "todo" && model.viewed-project == message.list - model.current-view := "todo-list" + if model.current-view == "project" && model.viewed-project == message.list + model.current-view := "project-list" model.viewed-project := void projector.schedule-render! - model.todo-list := model.todo-list.filter((.id != message.list)) + model.project-list := model.project-list.filter((.id != message.list)) render-navbar = -> h \div.navbar [ @@ -195,7 +192,7 @@ render-navbar = -> h \a.navbar-item.is-size-2 { onclick: -> model.viewed-project := void - model.current-view := "todo-list" + model.current-view := "project-list" } [ "⌂" ] ] h \div.navbar-end [ @@ -208,15 +205,15 @@ render-navbar = -> ] ] -render-todo-list = -> - h \div.section model.todo-list.map (project) -> +render-project-list = -> + h \div.section model.project-list.map (project) -> if project h \div.box { key: project.id onclick: -> - model.current-view := "todo" + model.current-view := "project" model.viewed-project := project.id - model.todod-ws.get-list model.jwt, project.id + model.todod-ws.get-list project.id } [ bulma.title 4 project.title ] @@ -224,39 +221,26 @@ render-todo-list = -> render-new-project-button = -> h \div.button.is-primary.is-large.is-fullwidth { onclick: -> - model.todod-ws.add-list model.jwt, "New project", { + model.todod-ws.add-list "New project", { columns: ["Unassigned", "Work in progress", "To be checked", "Being checked", "Done"] } } [ "New project!" ] -render-todo = (todo-id) -> - todo = model.todo-list.find((.id == todo-id)) - if todo - todo.render! - h \div.button.is-danger.is-outlined { - onclick: -> - console.log "La modal est crée" - model.modal := Modal { - +visible - content: - h \p [ "Are you sure you want to remove board #{todo.title}?" ] - on-validation: -> - model.todod-ws.remove-list model.jwt, todo.id - } - console.log "La modal est crée 2 le retour", model.modal +render-project = (project-id) -> + project = model.project-list.find((.id == project-id)) - projector.schedule-render! - } [ "X" ] + if project + project.render! else h \div.notification.is-error [ - bulma.title 3 "Error, we did not get the todo id " + todo-id + bulma.title 3 "Error, we did not get the project id " + project-id ] # # Pages: # login -# todo-list -# todo +# project-list +# project # network-error # @@ -266,11 +250,11 @@ render-body = -> when "login" authd.login-page model - when "todo-list" - h \div#todo-list [ + when "project-list" + h \div#project-list [ render-navbar! - render-todo-list! + render-project-list! render-new-project-button! ] @@ -288,11 +272,11 @@ render-body = -> render-new-project-button! ] - when "todo" + when "project" h \div [ render-navbar! - render-todo model.viewed-project + render-project model.viewed-project ] else diff --git a/client/project.ls b/client/project.ls index 50cf09f..5601148 100644 --- a/client/project.ls +++ b/client/project.ls @@ -2,136 +2,42 @@ h = require 'maquette' .h bulma = require "./bulma.ls" Task = require "./task.ls" +Modal = require './modal.ls' -module.exports = { +Project = (self, todod-ws) -> + self.todod-ws = todod-ws + self.tasks = self.tasks.map (e) -> Task e, self, model - new: (self, model) -> - self.tasks = self.tasks.map (e) -> Task.new e, self, model + modal = void - self.render-column = (column) -> - console.log "render column: ", column - # bulma.modal {} [(h \div {} [ "rendering " + column ])] - # h \div.column.is-3 { - # key: column - # } [ - # h \div.card.is-column-header { - # key: column - # } [ - # h \div.card-header [ - # if model.editing == column.id + ".title" - # h \input.input { - # type: "text", - # value: column - # onchange: (e) -> - # console.log "onchange??" - # model.editing := undefined + self.render-column = (column) -> - # # FIXME: columns = extra properties - # # model.todod-ws.edit-column self.id, column, { - # # name: e.target.value - # # } - # } - # else - # h \div.card-header-title [ - # bulma.title 3 column - # ] + self.render = -> - # h \a.card-header-icon { - # key: "edit" - # onclick: -> + # console.log "Project to render: ", self + h \div.project {} [ + h \div.button.is-danger.is-outlined { + onclick: -> + modal := Modal { + +visible + content: + h \p [ "Are you sure you want to remove board #{self.title}?" ] + on-validation: -> + self.todod-ws.remove-list self.id + } + } [ "X" ] - # # FIXME: columns = extra properties - # # if model.editing == column + ".title" - # # model.editing := undefined - # # else - # # model.editing := column + ".title" - # } [ - # "Edit" - # ] - - # if self.tasks.filter((.column == column)).length == 0 - # h \a.card-header-icon { - # key: "delete" - # onclick: -> - # # FIXME - # # model.editing := column + ".delete" - # } [ - # "Delete" - # ] - # ] - # if model.editing == column.id + ".delete" - # h \div.card-content [ - # h \div.button.is-fullwidth.is-danger { - # onclick: -> - # model.todod-ws.delete-column self.id, column.id - # } [ "Delete me!"] - # ] - # ] - - # for task in self.tasks - # continue if task.column != column - - # task.render! - - # h \div.button.is-fullwidth { - # onclick: -> - # model.todod-ws.new-task self.id, column.id, { - # title: "General Kenobi…" - # description: "" - # } - # } [ "New task" ] - # ] - - self.render = -> - - console.log "Project to render: ", self - h \div.list {} [ - h \div.columns [ - if self.extra_properties.columns - for dom in self.extra_properties.columns.map((column) -> self.render-column(column)) - dom - ] + h \div.columns [ + if self.extra_properties.columns + for dom in self.extra_properties.columns.map((column) -> self.render-column(column)) + dom ] - # h \div.column.is-2 { - # key: "new-column" - # } [ - # h \div.button.is-fullwidth { - # onclick: -> - # model.todod-ws.new-column self.id, "Hello, there!" - # } [ "New Column" ] - # ] - # ] - # ] + if modal + modal.render! + ] - # h \div.project { - # key: self.id - # } [ - # h \div.hero.is-dark { key: "title" } [ - # h \div.hero-body [ - # # FIXME: Consider using a .level for this. - # h \div.is-pulled-right { - # onclick: -> - # model.editing := self.id + ".name" - # } [ - # "Edit" - # ] + self - # if model.editing == self.id + ".name" - # h \input.input { - # onchange: (e) -> - # model.editing := undefined - # model.todod-ws.edit-project self.id, { - # name: e.target.value - # } - # value: self.name - # } - # else - # h \div.title [ self.name ] - # ] - # ] - - - self -} +module.exports = Project diff --git a/client/task.ls b/client/task.ls index 7433cf2..4edf69a 100644 --- a/client/task.ls +++ b/client/task.ls @@ -30,201 +30,200 @@ get-next = (collection, element) -> found-element := true -module.exports = { +Task = (self, project, model) -> + self.render = -> + author = model.users[self.author] + if typeof(author) != "object" and author != "request sent" + model.users[self.author] = "request sent" + # FIXME: This should go directly to authd. + model.todod-ws.get-user self.author - new: (self, project, model) -> - self.render = -> - author = model.users[self.author] - if typeof(author) != "object" and author != "request sent" - model.users[self.author] = "request sent" - # FIXME: This should go directly to authd. - model.todod-ws.get-user self.author + assigned_to = model.users[self.assigned_to] + if self.assigned_to and typeof(assigned_to) != "object" and assigned_to != "request sent" + model.users[self.assigned_to] = "request sent" + # FIXME: This should go directly to authd. + model.todod-ws.get-user self.assigned_to - assigned_to = model.users[self.assigned_to] - if self.assigned_to and typeof(assigned_to) != "object" and assigned_to != "request sent" - model.users[self.assigned_to] = "request sent" - # FIXME: This should go directly to authd. - model.todod-ws.get-user self.assigned_to + is-selected = model.selected == self.id - is-selected = model.selected == self.id - - h (\div.card.is- + (self.color || "dark")), { - key: self.id - classes: { - "is-selected": is-selected - } - onclick: -> - model.selected := self.id - } [ - h \div.card-content [ - h \div.media [ - h \div.media-left [ - h \img.image.is-48x48.avatar { - alt: "user image" - src: if typeof(assigned_to) == "object" - assigned_to.avatar - else - "https://bulma.io/images/placeholders/96x96.png" - } - ] - h \div.media-content [ - if model.editing == self.id + ".title" - h \input.input { - value: self.title - onchange: (e) -> - model.editing := undefined - model.todod-ws.edit-task project.id, self.id, { - title: e.target.value - } - } [ self.title ] + h (\div.card.is- + (self.color || "dark")), { + key: self.id + classes: { + "is-selected": is-selected + } + onclick: -> + model.selected := self.id + } [ + h \div.card-content [ + h \div.media [ + h \div.media-left [ + h \img.image.is-48x48.avatar { + alt: "user image" + src: if typeof(assigned_to) == "object" + assigned_to.avatar else - h \a [ - bulma.title 4 self.title - ] - - if typeof(model.users[self.assigned_to]) == "object" - user = model.users[self.assigned_to] - - h \div.subtitle.is-6 [ - "@" + (user.full_name || user.login) - ] - ] - if ! is-selected && self.description != "" - h \div.media-right {key: "description-icon"} [ - h \span.icon.is-size-1 [ "🗎" ] + "https://bulma.io/images/placeholders/96x96.png" + } + ] + h \div.media-content [ + if model.editing == self.id + ".title" + h \input.input { + value: self.title + onchange: (e) -> + model.editing := undefined + model.todod-ws.edit-task project.id, self.id, { + title: e.target.value + } + } [ self.title ] + else + h \a [ + bulma.title 4 self.title ] - if is-selected - h \div.media-right {key: "edit"} [ - h \a.small { - onclick: -> - if model.editing == self.id + ".title" - model.editing := undefined - else - model.editing := self.id + ".title" - } [ - "Edit" - ] - ] + if typeof(model.users[self.assigned_to]) == "object" + user = model.users[self.assigned_to] - if is-selected - h \div.media-right {key: "delete"} [ - h \a.small { - onclick: -> - model.editing := self.id + ".delete" - } [ - "Delete" - ] + h \div.subtitle.is-6 [ + "@" + (user.full_name || user.login) ] ] - - if is-selected - h \div.content { - key: self.description - after-create: (dom) -> - dom.innerHTML = nmd self.description - } [ - if model.editing == self.id + ".description" - h \form.form [ - h \textarea.textarea { - value: model.editing-data - oninput: (e) -> - model.editing-data := e.target.value - } - h \div.button.is-fullwidth { - onclick: -> - model.todod-ws.edit-task project.id, self.id, { - description: model.editing-data - } - model.editing-data := undefined - model.editing := undefined - } [ "Update" ] - ] + if ! is-selected && self.description != "" + h \div.media-right {key: "description-icon"} [ + h \span.icon.is-size-1 [ "🗎" ] ] if is-selected - h \span.button.is-small { - onclick: -> - model.editing-data := self.description - model.editing := self.id + ".description" - } [ - "edit" + h \div.media-right {key: "edit"} [ + h \a.small { + onclick: -> + if model.editing == self.id + ".title" + model.editing := undefined + else + model.editing := self.id + ".title" + } [ + "Edit" + ] + ] + + if is-selected + h \div.media-right {key: "delete"} [ + h \a.small { + onclick: -> + model.editing := self.id + ".delete" + } [ + "Delete" + ] ] ] if is-selected - h \div.card-footer {key: "assign"} [ - if model.editing == self.id + ".assigned_to" - h \div.card-footer-item { - key: "assign.clicked" - } [ - h \input.input { - onchange: (e) -> - model.editing := undefined - model.todod-ws.edit-task project.id, self.id, { - assigned_to: Number e.target.value - } + h \div.content { + key: self.description + after-create: (dom) -> + dom.innerHTML = nmd self.description + } [ + if model.editing == self.id + ".description" + h \form.form [ + h \textarea.textarea { + value: model.editing-data + oninput: (e) -> + model.editing-data := e.target.value } - ] - else - h \a.card-footer-item { - key: "assign" - onclick: -> - model.editing := self.id + ".assigned_to" - } [ "Assign" ] - ] - - if is-selected - h \div.card-footer {key: "color"} [ - if model.editing == self.id + ".color" - h \div.card-footer-item { - key: "color.clicked" - } [ - h \input.input { - onchange: (e) -> - model.editing := undefined - model.todod-ws.edit-task project.id, self.id, { - color: e.target.value - } - } - ] - else - h \a.card-footer-item { - key: "assign" - onclick: -> - model.editing := self.id + ".color" - } [ "Change Color" ] - ] - - if is-selected - h \div.card-footer {key: "move"} [ - h \a.card-footer-item { - key: "⇐" - onclick: -> - model.todod-ws.edit-task project.id, self.id, { - column: get-previous project.columns.map((.id)), self.column - } - } [ "⇐" ] - - if model.editing == self.id + ".delete" - h \a.card-footer-item { - key: "delete" - } [ - h \div.button.is-danger { + h \div.button.is-fullwidth { onclick: -> - model.todod-ws.delete-task project.id, self.id - } [ "Delete! For real!" ] + model.todod-ws.edit-task project.id, self.id, { + description: model.editing-data + } + model.editing-data := undefined + model.editing := undefined + } [ "Update" ] ] + ] - h \a.card-footer-item { - key: "⇒" - onclick: -> - model.todod-ws.edit-task project.id, self.id, { - column: get-next project.columns.map((.id)), self.column - } - } [ "⇒" ] + if is-selected + h \span.button.is-small { + onclick: -> + model.editing-data := self.description + model.editing := self.id + ".description" + } [ + "edit" ] ] - self -} + if is-selected + h \div.card-footer {key: "assign"} [ + if model.editing == self.id + ".assigned_to" + h \div.card-footer-item { + key: "assign.clicked" + } [ + h \input.input { + onchange: (e) -> + model.editing := undefined + model.todod-ws.edit-task project.id, self.id, { + assigned_to: Number e.target.value + } + } + ] + else + h \a.card-footer-item { + key: "assign" + onclick: -> + model.editing := self.id + ".assigned_to" + } [ "Assign" ] + ] + + if is-selected + h \div.card-footer {key: "color"} [ + if model.editing == self.id + ".color" + h \div.card-footer-item { + key: "color.clicked" + } [ + h \input.input { + onchange: (e) -> + model.editing := undefined + model.todod-ws.edit-task project.id, self.id, { + color: e.target.value + } + } + ] + else + h \a.card-footer-item { + key: "assign" + onclick: -> + model.editing := self.id + ".color" + } [ "Change Color" ] + ] + + if is-selected + h \div.card-footer {key: "move"} [ + h \a.card-footer-item { + key: "⇐" + onclick: -> + model.todod-ws.edit-task project.id, self.id, { + column: get-previous project.columns.map((.id)), self.column + } + } [ "⇐" ] + + if model.editing == self.id + ".delete" + h \a.card-footer-item { + key: "delete" + } [ + h \div.button.is-danger { + onclick: -> + model.todod-ws.delete-task project.id, self.id + } [ "Delete! For real!" ] + ] + + h \a.card-footer-item { + key: "⇒" + onclick: -> + model.todod-ws.edit-task project.id, self.id, { + column: get-next project.columns.map((.id)), self.column + } + } [ "⇒" ] + ] + ] + + self + +module.exports = Task diff --git a/client/todowebsocket.ls b/client/todowebsocket.ls index a07a851..c9d24f1 100644 --- a/client/todowebsocket.ls +++ b/client/todowebsocket.ls @@ -80,39 +80,39 @@ module.exports = { self.socket.send JSON.stringify { mtype: type, payload: opts } - self.list-lists = (token) -> + self.list-lists = -> self.send request-types[\list-lists], JSON.stringify { - token: token + token: self.token } - self.get-list = (token, list-id) -> + self.get-list = (list-id) -> self.send request-types[\get-list], JSON.stringify { - token: token + token: self.token list: list-id } - self.get-tasks = (token, list-id) -> + self.get-tasks = (list-id) -> self.send request-types[\get-tasks], JSON.stringify { - token: token + token: self.token list: list-id } - self.get-task = (token, task-id) -> + self.get-task = (task-id) -> self.send request-types[\get-task], JSON.stringify { - token: token + token: self.token task: task-id } - self.remove-list = (token, list-id) -> + self.remove-list = (list-id) -> self.send request-types[\remove-list], JSON.stringify { - token: token + token: self.token list: list-id } # TODO: extra properties - self.add-list = (token, title, opts) -> + self.add-list = (title, opts) -> payload = { - token: token + token: self.token title: title } @@ -121,9 +121,9 @@ module.exports = { self.send request-types[\add-list], JSON.stringify payload - self.edit-list = (token, list-id, opts) -> + self.edit-list = (list-id, opts) -> payload = { - token: token + token: self.token list: list-id } @@ -132,16 +132,16 @@ module.exports = { self.send request-types[\edit-list], JSON.stringify payload - self.remove-task = (token, task-id) -> + self.remove-task = (task-id) -> self.send request-types[\remove-task], JSON.stringify { - token: token + token: self.token task: task-id } # TODO: extra properties - self.add-task = (token, list-id, title, opts) -> + self.add-task = (list-id, title, opts) -> payload = { - token: token + token: self.token list: list-id title: title } @@ -151,9 +151,9 @@ module.exports = { self.send request-types[\add-task], JSON.stringify payload - self.edit-task = (token, id, opts) -> + self.edit-task = (id, opts) -> payload = { - token: token + token: self.token list: list-id }