2019-11-20 19:22:51 +01:00
|
|
|
|
|
|
|
# first:
|
|
|
|
# connection to authd
|
|
|
|
# display the authd widget
|
|
|
|
#
|
|
|
|
# second:
|
|
|
|
# connection to todod
|
|
|
|
# rewrite the whole body component
|
2019-12-03 03:47:27 +01:00
|
|
|
# page 1: (TODO) list of lists (or todos)
|
|
|
|
# display:
|
|
|
|
# navbar
|
2019-11-20 19:22:51 +01:00
|
|
|
#
|
2019-12-03 03:47:27 +01:00
|
|
|
# "element 1" button
|
|
|
|
# "element 2" button
|
|
|
|
# ...
|
|
|
|
# "element x" button
|
|
|
|
#
|
|
|
|
# "new list" button
|
|
|
|
# widgets:
|
|
|
|
# navbar: [return to list button] [logout]
|
|
|
|
# element button:
|
2019-12-05 02:28:17 +01:00
|
|
|
# [project list name]
|
2019-12-03 03:47:27 +01:00
|
|
|
# or
|
2019-12-05 02:28:17 +01:00
|
|
|
# [project list name] [RIGTHS] [DELETE]
|
2019-12-03 03:47:27 +01:00
|
|
|
#
|
|
|
|
# page 2:
|
|
|
|
# display:
|
|
|
|
# (TODO) list of tasks (this client has a kanban display of tasks, with columns)
|
|
|
|
# (TODO) task widget
|
|
|
|
# widgets:
|
|
|
|
# task widget:
|
|
|
|
# TODO
|
|
|
|
#
|
|
|
|
# page 3: (TODO) pages about
|
2019-11-20 19:22:51 +01:00
|
|
|
|
2019-12-05 01:45:21 +01:00
|
|
|
maquette = require "maquette"
|
|
|
|
nmd = require "nano-markdown"
|
|
|
|
authd = require "./authd.ls"
|
|
|
|
todows = require "./todowebsocket.ls"
|
|
|
|
bulma = require "./bulma.ls"
|
|
|
|
Task = require "./task.ls"
|
|
|
|
Project = require "./project.ls"
|
|
|
|
Modal = require "./modal.ls"
|
|
|
|
# ValidationModal = require "./validation-modal.ls"
|
2019-12-05 04:47:29 +01:00
|
|
|
UUID = require "uuid/v4"
|
2019-11-20 19:22:51 +01:00
|
|
|
|
|
|
|
{create-projector, h} = maquette
|
|
|
|
projector = create-projector!
|
|
|
|
|
|
|
|
model = {
|
2019-12-05 02:28:17 +01:00
|
|
|
# view: login, project-list, project, network-error (TODO: other views, such as rights)
|
2019-12-04 04:17:38 +01:00
|
|
|
# XXX FIXME TODO: TESTING THINGS
|
2019-12-05 01:45:21 +01:00
|
|
|
current-view: "login"
|
2019-12-03 03:47:27 +01:00
|
|
|
|
2019-12-05 01:45:21 +01:00
|
|
|
viewed-project: void
|
2019-12-03 03:47:27 +01:00
|
|
|
|
2019-12-05 01:45:21 +01:00
|
|
|
# current-view: "testing-modals"
|
2019-12-04 04:17:38 +01:00
|
|
|
|
2019-12-05 23:53:36 +01:00
|
|
|
# list of Project objects
|
2019-12-05 02:28:17 +01:00
|
|
|
project-list: []
|
2019-11-22 18:42:46 +01:00
|
|
|
|
|
|
|
port: 9999
|
2019-12-03 03:47:27 +01:00
|
|
|
authd-url: undefined
|
2019-11-22 18:42:46 +01:00
|
|
|
todod-url: undefined
|
|
|
|
|
|
|
|
authd-ws: undefined
|
|
|
|
todod-ws: undefined
|
|
|
|
|
|
|
|
previous-error: undefined
|
|
|
|
error: undefined
|
2019-12-10 05:59:52 +01:00
|
|
|
|
|
|
|
# { uid => user data }
|
|
|
|
users: {}
|
2019-11-20 19:22:51 +01:00
|
|
|
}
|
|
|
|
|
2019-12-03 03:47:27 +01:00
|
|
|
model.authd-url =
|
|
|
|
(if location.protocol == 'https' then 'wss' else 'ws') +
|
|
|
|
'://' + location.hostname + \: +
|
|
|
|
model.port +
|
|
|
|
"/auth.JSON"
|
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
model.todod-url =
|
2019-12-03 03:47:27 +01:00
|
|
|
(if location.protocol == 'https' then 'wss' else 'ws') +
|
|
|
|
'://' + location.hostname + \: +
|
2019-11-22 18:42:46 +01:00
|
|
|
model.port +
|
2019-12-03 05:29:09 +01:00
|
|
|
"/todo.JSON"
|
2019-11-20 19:22:51 +01:00
|
|
|
|
2019-12-03 03:47:27 +01:00
|
|
|
console.log "authd url: " + model.authd-url
|
|
|
|
console.log "todod url: " + model.todod-url
|
2019-11-20 19:22:51 +01:00
|
|
|
|
|
|
|
|
2019-11-22 16:52:50 +01:00
|
|
|
#
|
|
|
|
# network configuration
|
|
|
|
#
|
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
model.authd-ws = authd.create-socket model.authd-url
|
|
|
|
model.todod-ws = todows.create-socket model.todod-url
|
2019-11-22 16:52:50 +01:00
|
|
|
|
2019-12-03 03:47:27 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# authd messages management
|
|
|
|
#
|
|
|
|
|
|
|
|
# authd socket errors
|
|
|
|
|
|
|
|
authd-on-websocket-error = (event) ->
|
|
|
|
console.log "WebSocket error.", event
|
|
|
|
model.current-view := "network-error"
|
|
|
|
projector.schedule-render!
|
|
|
|
|
|
|
|
authd-on-websocket-close = (event) ->
|
|
|
|
model.current-view := "login"
|
|
|
|
console.log "WebSocket has been closed.", event
|
|
|
|
# model.todod-ws.reopen!
|
|
|
|
|
|
|
|
projector.schedule-render!
|
|
|
|
|
|
|
|
# record changes that need to happen on a network event
|
|
|
|
model.authd-ws.user-on-socket-error ++= [ authd-on-websocket-error ]
|
2019-12-03 05:29:09 +01:00
|
|
|
model.authd-ws.user-on-socket-close ++= [ authd-on-websocket-close ]
|
2019-12-03 03:47:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
# authd message handlers
|
|
|
|
|
2019-12-03 05:29:09 +01:00
|
|
|
model.authd-ws.add-event-listener \token, (message) ->
|
2019-12-05 02:28:17 +01:00
|
|
|
model.current-view := "project-list"
|
2019-12-10 05:59:52 +01:00
|
|
|
model.authd-ws.token := message.token
|
2019-12-05 02:28:17 +01:00
|
|
|
model.todod-ws.token := message.token
|
|
|
|
model.todod-ws.list-lists!
|
2019-12-10 05:59:52 +01:00
|
|
|
model.authd-ws.list-users!
|
2019-12-03 03:47:27 +01:00
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-03 05:29:09 +01:00
|
|
|
model.authd-ws.add-event-listener \error, (message) ->
|
2019-12-10 05:59:52 +01:00
|
|
|
console.log "authd error", message
|
2019-12-03 03:47:27 +01:00
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-03 05:29:09 +01:00
|
|
|
model.authd-ws.add-event-listener \user, (message) ->
|
2019-12-03 03:47:27 +01:00
|
|
|
model.users[message.user.uid] := message.user
|
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-10 05:59:52 +01:00
|
|
|
model.authd-ws.add-event-listener \users-list, (message) ->
|
|
|
|
console.log "Received users: ", message
|
|
|
|
message.users.map (user) ->
|
|
|
|
model.users[user.uid] := user
|
|
|
|
projector.schedule-render!
|
2019-12-03 03:47:27 +01:00
|
|
|
|
2019-12-10 05:59:52 +01:00
|
|
|
# TODO: user-added, user-edited
|
2019-12-03 03:47:27 +01:00
|
|
|
|
2019-12-04 04:17:38 +01:00
|
|
|
|
2019-12-03 03:47:27 +01:00
|
|
|
#
|
|
|
|
# todod messages management
|
|
|
|
#
|
|
|
|
|
|
|
|
# todod socket errors
|
|
|
|
|
2019-11-22 16:52:50 +01:00
|
|
|
on-websocket-error = (event) ->
|
|
|
|
console.log "WebSocket error.", event
|
2019-11-22 18:42:46 +01:00
|
|
|
model.current-view := "network-error"
|
2019-11-22 16:52:50 +01:00
|
|
|
projector.schedule-render!
|
2019-11-20 19:22:51 +01:00
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
on-websocket-close = (event) ->
|
2019-11-20 19:22:51 +01:00
|
|
|
model.current-view := "login"
|
2019-11-22 18:42:46 +01:00
|
|
|
console.log "WebSocket has been closed.", event
|
|
|
|
# model.todod-ws.reopen!
|
2019-11-20 19:22:51 +01:00
|
|
|
|
2019-11-22 16:52:50 +01:00
|
|
|
projector.schedule-render!
|
|
|
|
|
|
|
|
# record changes that need to happen on a network event
|
2019-12-03 03:47:27 +01:00
|
|
|
model.todod-ws.user-on-socket-error ++= [ on-websocket-error ]
|
2019-12-03 05:29:09 +01:00
|
|
|
model.todod-ws.user-on-socket-close ++= [ on-websocket-close ]
|
|
|
|
|
|
|
|
model.todod-ws.add-event-listener \lists-list, (message) ->
|
2019-12-06 21:46:40 +01:00
|
|
|
console.log "Project list received", message
|
2019-12-07 00:44:02 +01:00
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
model.project-list := message.lists.map (x) ->
|
2019-12-07 00:44:02 +01:00
|
|
|
old-project = model.project-list.find((.id == x.id))
|
2019-12-10 05:59:52 +01:00
|
|
|
new-project = Project x, model.todod-ws, model.users
|
2019-12-07 00:44:02 +01:00
|
|
|
|
|
|
|
if old-project && new-project.id == old-project.id
|
|
|
|
new-project.tasks = old-project.tasks
|
|
|
|
|
|
|
|
new-project
|
2019-12-05 01:45:21 +01:00
|
|
|
|
2019-12-04 04:17:38 +01:00
|
|
|
projector.schedule-render!
|
2019-11-22 18:42:46 +01:00
|
|
|
|
2019-12-04 04:17:38 +01:00
|
|
|
model.todod-ws.add-event-listener \new-list, (message) ->
|
2019-12-06 21:46:40 +01:00
|
|
|
console.log "New project", message
|
2019-12-07 00:44:02 +01:00
|
|
|
|
2019-12-10 05:59:52 +01:00
|
|
|
model.project-list := model.project-list ++ [ (Project message.list, model.todod-ws, model.users) ]
|
2019-12-04 04:17:38 +01:00
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-06 21:07:39 +01:00
|
|
|
model.todod-ws.add-event-listener \list-updated, (message) ->
|
2019-12-06 21:46:40 +01:00
|
|
|
console.log "Project updated", message
|
2019-12-06 21:07:39 +01:00
|
|
|
|
2019-12-10 05:59:52 +01:00
|
|
|
new-project = Project message.list, model.todod-ws, model.users
|
2019-12-06 21:07:39 +01:00
|
|
|
|
2019-12-08 04:08:21 +01:00
|
|
|
model.project-list := model.project-list.map (project) ->
|
2019-12-06 21:07:39 +01:00
|
|
|
if project.id == message.list.id
|
|
|
|
new-project
|
|
|
|
else
|
|
|
|
project
|
|
|
|
|
|
|
|
if model.viewed-project && model.viewed-project.id == message.list.id
|
2019-12-08 18:37:14 +01:00
|
|
|
# create tasks in order to have the updated project properties
|
|
|
|
new-project.tasks = model.viewed-project.tasks.map (task) -> Task task, new-project, model.todod-ws
|
2019-12-06 21:07:39 +01:00
|
|
|
model.viewed-project = new-project
|
|
|
|
|
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-05 01:45:21 +01:00
|
|
|
model.todod-ws.add-event-listener \list-removed, (message) ->
|
2019-12-05 23:53:36 +01:00
|
|
|
console.log "A list has been removed", message
|
2019-12-07 00:44:02 +01:00
|
|
|
|
2019-12-06 21:46:40 +01:00
|
|
|
if model.current-view == "project" && model.viewed-project.id == message.list
|
2019-12-05 02:28:17 +01:00
|
|
|
model.current-view := "project-list"
|
2019-12-05 01:45:21 +01:00
|
|
|
model.viewed-project := void
|
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
model.project-list := model.project-list.filter((.id != message.list))
|
2019-12-05 01:45:21 +01:00
|
|
|
|
2019-12-07 00:44:02 +01:00
|
|
|
|
|
|
|
# tasks
|
|
|
|
|
|
|
|
model.todod-ws.add-event-listener \tasks, (message) ->
|
|
|
|
console.log "Tasks received", message
|
|
|
|
|
|
|
|
project = model.project-list.find((.id == message.list))
|
|
|
|
project.tasks := message.tasks.map (e) -> Task e, project, model.todod-ws
|
|
|
|
|
|
|
|
if model.viewed-project.id == project.id
|
|
|
|
model.viewed-project := project
|
|
|
|
|
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-05 04:47:29 +01:00
|
|
|
model.todod-ws.add-event-listener \task-created, (message) ->
|
2019-12-05 23:53:36 +01:00
|
|
|
console.log "A task has been created", message
|
2019-12-05 04:47:29 +01:00
|
|
|
|
|
|
|
task = message.task
|
|
|
|
list = model.project-list.find((.id == task.list))
|
2019-12-07 00:44:02 +01:00
|
|
|
if list.id == model.viewed-project.id
|
|
|
|
model.viewed-project := list
|
2019-12-05 04:47:29 +01:00
|
|
|
|
|
|
|
if list
|
2019-12-06 01:56:32 +01:00
|
|
|
list.tasks ++= [ Task task, list, model.todod-ws ]
|
|
|
|
projector.schedule-render!
|
|
|
|
|
|
|
|
|
|
|
|
model.todod-ws.add-event-listener \task-updated, (message) ->
|
|
|
|
console.log "A task has been updated", message
|
|
|
|
|
|
|
|
task = message.task
|
|
|
|
list = model.project-list.find((.id == task.list))
|
|
|
|
|
|
|
|
if list
|
|
|
|
list.tasks = list.tasks.map (e) ->
|
|
|
|
if e.id == task.id
|
|
|
|
Task task, list, model.todod-ws
|
|
|
|
else
|
|
|
|
e
|
2019-12-05 04:47:29 +01:00
|
|
|
projector.schedule-render!
|
|
|
|
|
2019-12-06 04:07:19 +01:00
|
|
|
model.todod-ws.add-event-listener \task-removed, (message) ->
|
|
|
|
console.log "A task has been removed", message
|
|
|
|
|
|
|
|
task = message.task
|
|
|
|
for project in model.project-list
|
|
|
|
if project.tasks.find((.id == task))
|
|
|
|
project.tasks := project.tasks.filter((.id != task))
|
|
|
|
projector.schedule-render!
|
|
|
|
|
|
|
|
|
2019-12-07 00:44:02 +01:00
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
render-navbar = ->
|
2019-12-07 00:44:02 +01:00
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
h \div.navbar [
|
|
|
|
h \div.navbar-start [
|
2019-12-03 03:47:27 +01:00
|
|
|
h \a.navbar-item.is-size-2 {
|
2019-11-22 18:42:46 +01:00
|
|
|
onclick: ->
|
2019-12-06 03:16:48 +01:00
|
|
|
model.todod-ws.unsubscribe model.viewed-project.id
|
2019-12-06 21:46:40 +01:00
|
|
|
model.todod-ws.list-lists!
|
2019-12-05 01:45:21 +01:00
|
|
|
model.viewed-project := void
|
2019-12-05 02:28:17 +01:00
|
|
|
model.current-view := "project-list"
|
2019-11-22 18:42:46 +01:00
|
|
|
} [ "⌂" ]
|
|
|
|
]
|
2019-12-07 00:44:02 +01:00
|
|
|
|
|
|
|
if model.viewed-project
|
|
|
|
model.viewed-project.inner-nav-render!
|
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
h \div.navbar-end [
|
2019-12-07 00:44:02 +01:00
|
|
|
|
|
|
|
if model.viewed-project
|
|
|
|
model.viewed-project.right-nav-render!
|
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
h \a.navbar-item {
|
|
|
|
onclick: ->
|
|
|
|
model.current-view := "login"
|
2019-12-03 03:47:27 +01:00
|
|
|
# TODO: remove anything related to the old session on the client
|
2019-11-22 18:42:46 +01:00
|
|
|
model.todod-ws.reopen!
|
|
|
|
} [ "Logout" ]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
render-project-list = ->
|
|
|
|
h \div.section model.project-list.map (project) ->
|
2019-12-05 04:47:29 +01:00
|
|
|
h \div.box {
|
|
|
|
key: project.id
|
|
|
|
onclick: ->
|
|
|
|
model.current-view := "project"
|
2019-12-06 21:46:40 +01:00
|
|
|
model.viewed-project := project
|
2019-12-06 03:16:48 +01:00
|
|
|
model.todod-ws.subscribe project.id
|
2019-12-05 04:47:29 +01:00
|
|
|
model.todod-ws.get-list project.id
|
|
|
|
model.todod-ws.get-tasks project.id
|
|
|
|
} [
|
|
|
|
bulma.title 4 project.title
|
|
|
|
]
|
|
|
|
|
|
|
|
Column = (title) ->
|
|
|
|
{
|
|
|
|
title: title
|
|
|
|
id: UUID! # TODO FIXME XXX
|
|
|
|
}
|
2019-11-22 16:52:50 +01:00
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
render-new-project-button = ->
|
|
|
|
h \div.button.is-primary.is-large.is-fullwidth {
|
|
|
|
onclick: ->
|
2019-12-05 02:28:17 +01:00
|
|
|
model.todod-ws.add-list "New project", {
|
2019-12-05 04:47:29 +01:00
|
|
|
extra_properties: {
|
|
|
|
columns: [
|
|
|
|
Column "Unassigned"
|
|
|
|
Column "Work in progress"
|
|
|
|
Column "To be checked"
|
|
|
|
Column "Being checked"
|
|
|
|
Column "Done"
|
|
|
|
]
|
|
|
|
}
|
2019-12-04 04:17:38 +01:00
|
|
|
}
|
2019-12-03 03:47:27 +01:00
|
|
|
} [ "New project!" ]
|
2019-11-22 18:42:46 +01:00
|
|
|
|
2019-12-06 21:46:40 +01:00
|
|
|
render-project = (project) ->
|
2019-12-05 02:28:17 +01:00
|
|
|
if project
|
|
|
|
project.render!
|
2019-12-03 03:47:27 +01:00
|
|
|
else
|
|
|
|
h \div.notification.is-error [
|
2019-12-06 21:46:40 +01:00
|
|
|
bulma.title 3 "Error, we did not get the project id " + project.id
|
2019-12-03 03:47:27 +01:00
|
|
|
]
|
2019-11-22 16:52:50 +01:00
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
render-body = ->
|
2019-11-20 19:22:51 +01:00
|
|
|
h \div.section [
|
|
|
|
switch model.current-view
|
|
|
|
when "login"
|
2019-11-22 18:42:46 +01:00
|
|
|
authd.login-page model
|
2019-11-20 19:22:51 +01:00
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
when "project-list"
|
|
|
|
h \div#project-list [
|
2019-11-20 19:22:51 +01:00
|
|
|
render-navbar!
|
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
render-project-list!
|
2019-11-22 18:42:46 +01:00
|
|
|
|
|
|
|
render-new-project-button!
|
2019-11-20 19:22:51 +01:00
|
|
|
]
|
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
when "project"
|
2019-11-20 19:22:51 +01:00
|
|
|
h \div [
|
|
|
|
render-navbar!
|
|
|
|
|
2019-12-05 02:28:17 +01:00
|
|
|
render-project model.viewed-project
|
2019-11-20 19:22:51 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
else
|
|
|
|
h \div.notification.is-error [
|
|
|
|
"Wait, what? Internal error!"
|
|
|
|
]
|
2019-12-05 01:45:21 +01:00
|
|
|
|
|
|
|
if model.modal
|
|
|
|
model.modal.render!
|
2019-11-20 19:22:51 +01:00
|
|
|
]
|
|
|
|
|
2019-11-22 18:42:46 +01:00
|
|
|
|
|
|
|
renderer = ->
|
|
|
|
render-navbar!
|
|
|
|
|
|
|
|
render-body!
|
|
|
|
|
2019-11-20 19:22:51 +01:00
|
|
|
document.add-event-listener 'DOMContentLoaded' ->
|
|
|
|
projector.append document.body, renderer
|
|
|
|
|