Merge branch 'dev' of ssh://git.karchnu.fr:2202/WeirdOS/todo-webclient into dev
commit
6f53a71e02
|
@ -6,12 +6,23 @@ module.exports = {
|
||||||
create-socket: (socket-url) ->
|
create-socket: (socket-url) ->
|
||||||
self = {}
|
self = {}
|
||||||
|
|
||||||
|
self.token = ""
|
||||||
|
|
||||||
request-types = {
|
request-types = {
|
||||||
"get-token": 0
|
"get-token": 0
|
||||||
"add-user": 1
|
"add-user": 1
|
||||||
"get-user": 2
|
"get-user": 2
|
||||||
"get-user-by-credentials": 3
|
"get-user-by-credentials": 3
|
||||||
"mod-user": 4
|
"mod-user": 4
|
||||||
|
|
||||||
|
# TODO: code these messages
|
||||||
|
"register": 5
|
||||||
|
"get-extra": 6
|
||||||
|
"set-extra": 7
|
||||||
|
"update-password": 8
|
||||||
|
|
||||||
|
"list-users": 9
|
||||||
|
"set-permissions": 10
|
||||||
}
|
}
|
||||||
|
|
||||||
response-types = {
|
response-types = {
|
||||||
|
@ -20,6 +31,9 @@ module.exports = {
|
||||||
"user": 2
|
"user": 2
|
||||||
"user-added": 3
|
"user-added": 3
|
||||||
"user-edited": 4
|
"user-edited": 4
|
||||||
|
"extra": 5
|
||||||
|
"extra-updated": 6
|
||||||
|
"users-list": 7
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: naming convention
|
# TODO: naming convention
|
||||||
|
@ -92,6 +106,23 @@ module.exports = {
|
||||||
uid: uid
|
uid: uid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.list-users = ->
|
||||||
|
self.send request-types[\list-users], JSON.stringify {
|
||||||
|
token: self.token
|
||||||
|
# FIXME: this will be removed once the authd program will accept
|
||||||
|
# any list-users requests from any user
|
||||||
|
# which is the only logical choice since any user can create projects and assign people to it
|
||||||
|
key: "nico-nico-nii"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set-permissions = (list-id, user-id, permission) ->
|
||||||
|
self.send request-types[\set-permissions], JSON.stringify {
|
||||||
|
token: self.token
|
||||||
|
list: list-id
|
||||||
|
uid: user-id
|
||||||
|
permission: permission
|
||||||
|
}
|
||||||
|
|
||||||
# TODO: authd overhaul
|
# TODO: authd overhaul
|
||||||
#self.add-user = (login, password) ->
|
#self.add-user = (login, password) ->
|
||||||
# self.send request-types[\add-user], JSON.stringify {
|
# self.send request-types[\add-user], JSON.stringify {
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
|
|
||||||
# first:
|
|
||||||
# connection to authd
|
|
||||||
# display the authd widget
|
|
||||||
#
|
|
||||||
# second:
|
|
||||||
# connection to todod
|
|
||||||
# rewrite the whole body component
|
|
||||||
# page 1: (TODO) list of lists (or todos)
|
|
||||||
# display:
|
|
||||||
# navbar
|
|
||||||
#
|
|
||||||
# "element 1" button
|
|
||||||
# "element 2" button
|
|
||||||
# ...
|
|
||||||
# "element x" button
|
|
||||||
#
|
|
||||||
# "new list" button
|
|
||||||
# widgets:
|
|
||||||
# navbar: [return to list button] [logout]
|
|
||||||
# element button:
|
|
||||||
# [project list name]
|
|
||||||
# or
|
|
||||||
# [project list name] [RIGTHS] [DELETE]
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
|
|
||||||
maquette = require "maquette"
|
maquette = require "maquette"
|
||||||
nmd = require "nano-markdown"
|
nmd = require "nano-markdown"
|
||||||
authd = require "./authd.ls"
|
authd = require "./authd.ls"
|
||||||
|
LoginForm = require "../lib/authd/client/login-form.ls"
|
||||||
todows = require "./todowebsocket.ls"
|
todows = require "./todowebsocket.ls"
|
||||||
bulma = require "./bulma.ls"
|
bulma = require "./bulma.ls"
|
||||||
Task = require "./task.ls"
|
Task = require "./task.ls"
|
||||||
|
@ -49,16 +16,10 @@ projector = create-projector!
|
||||||
|
|
||||||
model = {
|
model = {
|
||||||
# view: login, project-list, project, 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"
|
current-view: "login"
|
||||||
|
|
||||||
viewed-project: void
|
viewed-project: void
|
||||||
|
|
||||||
# current-view: "testing-modals"
|
|
||||||
|
|
||||||
# { uid => user data }
|
|
||||||
users: {}
|
|
||||||
|
|
||||||
# list of Project objects
|
# list of Project objects
|
||||||
project-list: []
|
project-list: []
|
||||||
|
|
||||||
|
@ -71,6 +32,9 @@ model = {
|
||||||
|
|
||||||
previous-error: undefined
|
previous-error: undefined
|
||||||
error: undefined
|
error: undefined
|
||||||
|
|
||||||
|
# { uid => user data }
|
||||||
|
users: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
model.authd-url =
|
model.authd-url =
|
||||||
|
@ -122,22 +86,30 @@ model.authd-ws.user-on-socket-close ++= [ authd-on-websocket-close ]
|
||||||
|
|
||||||
# authd message handlers
|
# authd message handlers
|
||||||
|
|
||||||
model.authd-ws.add-event-listener \token, (message) ->
|
# HANDLED with the "on-login" callback in the LoginForm component
|
||||||
model.current-view := "project-list"
|
# model.authd-ws.add-event-listener \token, (message) ->
|
||||||
model.todod-ws.token := message.token
|
# model.current-view := "project-list"
|
||||||
model.todod-ws.list-lists!
|
# model.authd-ws.token := message.token
|
||||||
projector.schedule-render!
|
# model.todod-ws.token := message.token
|
||||||
|
# model.todod-ws.list-lists!
|
||||||
|
# model.authd-ws.list-users!
|
||||||
|
# projector.schedule-render!
|
||||||
|
|
||||||
model.authd-ws.add-event-listener \error, (message) ->
|
model.authd-ws.add-event-listener \error, (message) ->
|
||||||
# console.log "authd error", message
|
console.log "authd error", message
|
||||||
projector.schedule-render!
|
projector.schedule-render!
|
||||||
|
|
||||||
model.authd-ws.add-event-listener \user, (message) ->
|
model.authd-ws.add-event-listener \user, (message) ->
|
||||||
model.users[message.user.uid] := message.user
|
model.users[message.user.uid] := message.user
|
||||||
projector.schedule-render!
|
projector.schedule-render!
|
||||||
|
|
||||||
# TODO: user-added, user-edited
|
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!
|
||||||
|
|
||||||
|
# TODO: user-added, user-edited
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -167,7 +139,7 @@ model.todod-ws.add-event-listener \lists-list, (message) ->
|
||||||
|
|
||||||
model.project-list := message.lists.map (x) ->
|
model.project-list := message.lists.map (x) ->
|
||||||
old-project = model.project-list.find((.id == x.id))
|
old-project = model.project-list.find((.id == x.id))
|
||||||
new-project = Project x, model.todod-ws
|
new-project = Project x, model.todod-ws, model.users
|
||||||
|
|
||||||
if old-project && new-project.id == old-project.id
|
if old-project && new-project.id == old-project.id
|
||||||
new-project.tasks = old-project.tasks
|
new-project.tasks = old-project.tasks
|
||||||
|
@ -179,13 +151,13 @@ model.todod-ws.add-event-listener \lists-list, (message) ->
|
||||||
model.todod-ws.add-event-listener \new-list, (message) ->
|
model.todod-ws.add-event-listener \new-list, (message) ->
|
||||||
console.log "New project", message
|
console.log "New project", message
|
||||||
|
|
||||||
model.project-list := model.project-list ++ [ (Project message.list, model.todod-ws) ]
|
model.project-list := model.project-list ++ [ (Project message.list, model.todod-ws, model.users) ]
|
||||||
projector.schedule-render!
|
projector.schedule-render!
|
||||||
|
|
||||||
model.todod-ws.add-event-listener \list-updated, (message) ->
|
model.todod-ws.add-event-listener \list-updated, (message) ->
|
||||||
console.log "Project updated", message
|
console.log "Project updated", message
|
||||||
|
|
||||||
new-project = Project message.list, model.todod-ws
|
new-project = Project message.list, model.todod-ws, model.users
|
||||||
|
|
||||||
model.project-list := model.project-list.map (project) ->
|
model.project-list := model.project-list.map (project) ->
|
||||||
if project.id == message.list.id
|
if project.id == message.list.id
|
||||||
|
@ -268,6 +240,7 @@ render-navbar = ->
|
||||||
h \div.navbar-start [
|
h \div.navbar-start [
|
||||||
h \a.navbar-item.is-size-2 {
|
h \a.navbar-item.is-size-2 {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
|
if model.viewed-project
|
||||||
model.todod-ws.unsubscribe model.viewed-project.id
|
model.todod-ws.unsubscribe model.viewed-project.id
|
||||||
model.todod-ws.list-lists!
|
model.todod-ws.list-lists!
|
||||||
model.viewed-project := void
|
model.viewed-project := void
|
||||||
|
@ -275,15 +248,16 @@ render-navbar = ->
|
||||||
} [ "⌂" ]
|
} [ "⌂" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
if model.viewed-project
|
if model.current-view == "project" && model.viewed-project
|
||||||
model.viewed-project.inner-nav-render!
|
model.viewed-project.inner-nav-render!
|
||||||
|
|
||||||
h \div.navbar-end [
|
h \div.navbar-end [
|
||||||
|
|
||||||
if model.viewed-project
|
if model.current-view == "project" && model.viewed-project
|
||||||
model.viewed-project.right-nav-render!
|
model.viewed-project.right-nav-render!
|
||||||
|
|
||||||
h \a.navbar-item {
|
h \a.navbar-item {
|
||||||
|
key: "logout"
|
||||||
onclick: ->
|
onclick: ->
|
||||||
model.current-view := "login"
|
model.current-view := "login"
|
||||||
# TODO: remove anything related to the old session on the client
|
# TODO: remove anything related to the old session on the client
|
||||||
|
@ -336,11 +310,23 @@ render-project = (project) ->
|
||||||
bulma.title 3 "Error, we did not get the project id " + project.id
|
bulma.title 3 "Error, we did not get the project id " + project.id
|
||||||
]
|
]
|
||||||
|
|
||||||
|
model.login-form = LoginForm {
|
||||||
|
authws-url: model.authd-url
|
||||||
|
on-login: (user, token) ->
|
||||||
|
model.current-view := "project-list"
|
||||||
|
model.authd-ws.token := token
|
||||||
|
model.todod-ws.token := token
|
||||||
|
model.todod-ws.list-lists!
|
||||||
|
model.authd-ws.list-users!
|
||||||
|
projector.schedule-render!
|
||||||
|
}
|
||||||
|
|
||||||
render-body = ->
|
render-body = ->
|
||||||
h \div.section [
|
h \div.section [
|
||||||
switch model.current-view
|
switch model.current-view
|
||||||
when "login"
|
when "login"
|
||||||
authd.login-page model
|
# authd.login-page model
|
||||||
|
model.login-form.render!
|
||||||
|
|
||||||
when "project-list"
|
when "project-list"
|
||||||
h \div#project-list [
|
h \div#project-list [
|
||||||
|
|
|
@ -24,18 +24,37 @@ col-to-lines = (column, self) ->
|
||||||
} [ "DELETE" ]
|
} [ "DELETE" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
# <div class="field has-addons">
|
user-form-selection = (self, user) ->
|
||||||
# <p class="control">
|
h \option {
|
||||||
# <input class="input" type="text" placeholder="Your email">
|
value: user.uid
|
||||||
# </p>
|
} [ user.login ]
|
||||||
# <p class="control">
|
|
||||||
# <a class="button is-static">
|
|
||||||
# @gmail.com
|
|
||||||
# </a>
|
|
||||||
# </p>
|
|
||||||
# </div>
|
|
||||||
|
|
||||||
ProjectCreationModal = (project, todod-ws) ->
|
permission-groups =
|
||||||
|
"read"
|
||||||
|
"post"
|
||||||
|
"edit"
|
||||||
|
"admin"
|
||||||
|
|
||||||
|
permissions-add = (self, permission, user-id) ->
|
||||||
|
perm-list = self.permissions[permission]
|
||||||
|
if perm-list
|
||||||
|
is-already-there = perm-list.find (e) -> (""+ e) == ("" + user-id)
|
||||||
|
if is-already-there
|
||||||
|
console.log "user #{user-id} already in #{perm-list}"
|
||||||
|
else
|
||||||
|
perm-list ++= [ parseInt(user-id) ]
|
||||||
|
self.permissions[permission] := perm-list
|
||||||
|
# console.log "adding user #{user-id} to #{perm-list[0]}: #{perm-list}"
|
||||||
|
else
|
||||||
|
console.log "Cannot find #{permission} permissions, creating it"
|
||||||
|
self.permissions[permission] := user-id
|
||||||
|
|
||||||
|
permission-to-form-selection = (self, permission) ->
|
||||||
|
h \option {
|
||||||
|
value: permission
|
||||||
|
} [ permission ]
|
||||||
|
|
||||||
|
ProjectCreationModal = (project, todod-ws, users) ->
|
||||||
|
|
||||||
# work on a copy of the columns
|
# work on a copy of the columns
|
||||||
# in case of cancelled modifications, only the copies are changed
|
# in case of cancelled modifications, only the copies are changed
|
||||||
|
@ -48,11 +67,15 @@ ProjectCreationModal = (project, todod-ws) ->
|
||||||
|
|
||||||
self = {
|
self = {
|
||||||
title: project.title || ""
|
title: project.title || ""
|
||||||
permissions: project.permissions || [[]]
|
permissions: project.permissions || {admin: [], edit: [], post: [], read: []}
|
||||||
new-user: "New user"
|
|
||||||
new-column-input: {
|
tmp:
|
||||||
|
new-user-permission:
|
||||||
|
id: void
|
||||||
|
permission: permission-groups[0]
|
||||||
|
new-column-input:
|
||||||
title: "New column !"
|
title: "New column !"
|
||||||
}
|
users: users || []
|
||||||
|
|
||||||
extra_properties:
|
extra_properties:
|
||||||
columns: columns-copy
|
columns: columns-copy
|
||||||
|
@ -73,29 +96,30 @@ ProjectCreationModal = (project, todod-ws) ->
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
h \hr []
|
# h \hr []
|
||||||
|
|
||||||
bulma.field [
|
# bulma.field [
|
||||||
bulma.label "Adding a user"
|
# bulma.label "Adding a user"
|
||||||
bulma.input {
|
# bulma.input {
|
||||||
value: self.new-user
|
# value: self.new-user
|
||||||
oninput: (e) ->
|
# oninput: (e) ->
|
||||||
self.new-user := e.target.value
|
# self.new-user := e.target.value
|
||||||
|
# name: \new-user
|
||||||
name: \new-user
|
# id: \user-add
|
||||||
id: \user-add
|
# }
|
||||||
}
|
# ]
|
||||||
]
|
|
||||||
|
|
||||||
h \hr []
|
h \hr []
|
||||||
|
|
||||||
h \aside.menu [
|
h \aside.menu [
|
||||||
h \p.menu-label [ "Permissions" ]
|
h \p.menu-label [ "Permissions" ]
|
||||||
h \ul.menu-list self.permissions.map (permission) ->
|
h \ul.menu-list Object.keys(self.permissions).map (permission) ->
|
||||||
h \li [
|
h \li {
|
||||||
h \p permission.map (e, index) ->
|
key: "permission" + permission
|
||||||
|
} [
|
||||||
|
h \p self.permissions[permission].map (e, index) ->
|
||||||
if index == 0
|
if index == 0
|
||||||
"Permissions '" + e + "': "
|
"Permissions '" + permission + "': " + e + ", "
|
||||||
else
|
else
|
||||||
"" + e + ", "
|
"" + e + ", "
|
||||||
]
|
]
|
||||||
|
@ -103,6 +127,43 @@ ProjectCreationModal = (project, todod-ws) ->
|
||||||
|
|
||||||
h \hr []
|
h \hr []
|
||||||
|
|
||||||
|
h \p [ "Adding new user" ]
|
||||||
|
|
||||||
|
h \div.field.has-addons {
|
||||||
|
key: "adding-user"
|
||||||
|
} [
|
||||||
|
h \div.select.control [
|
||||||
|
h \select {
|
||||||
|
onchange: (e) ->
|
||||||
|
self.tmp.new-user-permission.permission := e.target.value
|
||||||
|
} permission-groups.map (permission) -> permission-to-form-selection self, permission
|
||||||
|
]
|
||||||
|
|
||||||
|
h \div.select.control.is-expanded [
|
||||||
|
h \select {
|
||||||
|
onchange: (e) ->
|
||||||
|
self.tmp.new-user-permission.uid := e.target.value
|
||||||
|
} [
|
||||||
|
user-form-selection self, { login: "Choose a user", uid: "-" }
|
||||||
|
for user-id, user of self.tmp.users
|
||||||
|
user-form-selection self, user
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
h \div.control.button.is-success.is-outlined {
|
||||||
|
onclick: ->
|
||||||
|
if self.tmp.new-user-permission.uid == void || self.tmp.new-user-permission.uid == "-"
|
||||||
|
console.log "adding an user permission on the kanban: failed, no user selected"
|
||||||
|
else
|
||||||
|
# TODO:
|
||||||
|
# adding the permissions in self.permissions
|
||||||
|
# then editing the project in the db via todod-ws
|
||||||
|
permissions-add self, self.tmp.new-user-permission.permission, self.tmp.new-user-permission.uid
|
||||||
|
} [ "+" ]
|
||||||
|
]
|
||||||
|
|
||||||
|
h \hr []
|
||||||
|
|
||||||
h \p [ "Choose the columns" ]
|
h \p [ "Choose the columns" ]
|
||||||
|
|
||||||
for dom in (self.extra_properties.columns.map (column) -> col-to-lines column, self)
|
for dom in (self.extra_properties.columns.map (column) -> col-to-lines column, self)
|
||||||
|
@ -115,9 +176,9 @@ ProjectCreationModal = (project, todod-ws) ->
|
||||||
} [
|
} [
|
||||||
h \p.control.is-expanded [
|
h \p.control.is-expanded [
|
||||||
h \input.input {
|
h \input.input {
|
||||||
value: self.new-column-input.title
|
value: self.tmp.new-column-input.title
|
||||||
oninput: (e) ->
|
oninput: (e) ->
|
||||||
self.new-column-input.title := e.target.value
|
self.tmp.new-column-input.title := e.target.value
|
||||||
} [ ]
|
} [ ]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -125,20 +186,21 @@ ProjectCreationModal = (project, todod-ws) ->
|
||||||
onclick: ->
|
onclick: ->
|
||||||
new-col = {
|
new-col = {
|
||||||
id: UUID!
|
id: UUID!
|
||||||
title: self.new-column-input.title
|
title: self.tmp.new-column-input.title
|
||||||
}
|
}
|
||||||
self.extra_properties.columns ++= [ new-col ]
|
self.extra_properties.columns ++= [ new-col ]
|
||||||
self.new-column-input.title := "New column !"
|
self.tmp.new-column-input.title := "New column !"
|
||||||
} [ "+" ]
|
} [ "+" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
on-validation: ->
|
on-validation: ->
|
||||||
|
tmp = delete self.tmp
|
||||||
if project.id
|
if project.id
|
||||||
todod-ws.edit-list project.id, self
|
todod-ws.edit-list project.id, self
|
||||||
else
|
else
|
||||||
todod-ws.add-list self.title, self
|
todod-ws.add-list self.title, self
|
||||||
|
self.tmp := tmp
|
||||||
}, self
|
}, self
|
||||||
|
|
||||||
self.render = ->
|
self.render = ->
|
||||||
|
|
|
@ -4,7 +4,7 @@ bulma = require "./bulma.ls"
|
||||||
Task = require "./task.ls"
|
Task = require "./task.ls"
|
||||||
Modal = require './modal.ls'
|
Modal = require './modal.ls'
|
||||||
TaskCreationModal = require './task-creation-modal.ls'
|
TaskCreationModal = require './task-creation-modal.ls'
|
||||||
ProjectCreationModal = require "./project-creation-modal.ls"
|
ProjectCreationModal = require './project-creation-modal.ls'
|
||||||
|
|
||||||
is-right-column = (task, column-id) ->
|
is-right-column = (task, column-id) ->
|
||||||
task.extra_properties && task.extra_properties.column && task.extra_properties.column == column-id
|
task.extra_properties && task.extra_properties.column && task.extra_properties.column == column-id
|
||||||
|
@ -20,9 +20,10 @@ orphan-tasks = (tasks, columns) ->
|
||||||
tasks.filter (task) -> (! has-column) || inexistant-column task, columns
|
tasks.filter (task) -> (! has-column) || inexistant-column task, columns
|
||||||
|
|
||||||
|
|
||||||
Project = (self, todod-ws) ->
|
Project = (self, todod-ws, users) ->
|
||||||
self.todod-ws = todod-ws
|
self.todod-ws = todod-ws
|
||||||
self.tasks = []
|
self.tasks = []
|
||||||
|
self.users = users || []
|
||||||
|
|
||||||
modal = void
|
modal = void
|
||||||
|
|
||||||
|
@ -33,6 +34,10 @@ Project = (self, todod-ws) ->
|
||||||
if first
|
if first
|
||||||
tasks-to-display ++= orphan-tasks self.tasks, self.extra_properties.columns
|
tasks-to-display ++= orphan-tasks self.tasks, self.extra_properties.columns
|
||||||
|
|
||||||
|
#
|
||||||
|
# COLUMNS
|
||||||
|
#
|
||||||
|
|
||||||
h \div.column {
|
h \div.column {
|
||||||
key: column.id
|
key: column.id
|
||||||
} [
|
} [
|
||||||
|
@ -52,21 +57,27 @@ Project = (self, todod-ws) ->
|
||||||
|
|
||||||
self.right-nav-render = ->
|
self.right-nav-render = ->
|
||||||
[
|
[
|
||||||
h \div.navbar-item [
|
h \div.navbar-item {
|
||||||
|
key: "navbar-new-task"
|
||||||
|
} [
|
||||||
h \div.button.is-success.is-outlined {
|
h \div.button.is-success.is-outlined {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
modal := TaskCreationModal self, self.todod-ws
|
modal := TaskCreationModal self, self.todod-ws, void, self.users
|
||||||
} [ "New task" ]
|
} [ "New task" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
h \div.navbar-item [
|
h \div.navbar-item {
|
||||||
|
key: "navbar-edit-project"
|
||||||
|
} [
|
||||||
h \div.button.is-outlined {
|
h \div.button.is-outlined {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
modal := ProjectCreationModal self, self.todod-ws
|
modal := ProjectCreationModal self, self.todod-ws, self.users
|
||||||
} [ "Edit this project" ]
|
} [ "Edit this project" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
h \div.navbar-item [
|
h \div.navbar-item {
|
||||||
|
key: "navbar-delete-project"
|
||||||
|
} [
|
||||||
h \div.button.is-danger.is-outlined {
|
h \div.button.is-danger.is-outlined {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
modal := Modal {
|
modal := Modal {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
@charset "utf-8"
|
@charset "utf-8"
|
||||||
|
|
||||||
@import "../node_modules/bulmaswatch/superhero/_variables.scss"
|
// @import "../node_modules/bulmaswatch/superhero/_variables.scss"
|
||||||
|
|
||||||
// Import Bulma core
|
// Import Bulma core
|
||||||
@import "../node_modules/bulma/bulma"
|
@import "../node_modules/bulma/bulma"
|
||||||
|
|
||||||
@import "../node_modules/bulmaswatch/superhero/_overrides.scss"
|
// @import "../node_modules/bulmaswatch/superhero/_overrides.scss"
|
||||||
|
|
||||||
.project>.columns
|
.project>.columns
|
||||||
overflow-x: scroll
|
overflow-x: auto
|
||||||
|
|
||||||
.avatar
|
.avatar
|
||||||
border-radius: 4px
|
border-radius: 4px
|
||||||
|
|
|
@ -1,7 +1,30 @@
|
||||||
|
|
||||||
|
# TODO: on modification, the description isn't updated on the client
|
||||||
|
|
||||||
h = require 'maquette' .h
|
h = require 'maquette' .h
|
||||||
Modal = require './modal.ls'
|
Modal = require './modal.ls'
|
||||||
|
|
||||||
|
colors = [
|
||||||
|
"white"
|
||||||
|
"black"
|
||||||
|
"light"
|
||||||
|
"dark"
|
||||||
|
"primary"
|
||||||
|
"info"
|
||||||
|
"link"
|
||||||
|
"success"
|
||||||
|
"warning"
|
||||||
|
"danger"
|
||||||
|
"black-bis"
|
||||||
|
"black-ter"
|
||||||
|
"grey-darker"
|
||||||
|
"grey-dark"
|
||||||
|
"grey"
|
||||||
|
"grey-light"
|
||||||
|
"grey-lighter"
|
||||||
|
"white-ter"
|
||||||
|
"white-bis"
|
||||||
|
]
|
||||||
|
|
||||||
column-form-selection = (self, column) ->
|
column-form-selection = (self, column) ->
|
||||||
h \option {
|
h \option {
|
||||||
|
@ -9,32 +32,57 @@ column-form-selection = (self, column) ->
|
||||||
selected: self.extra_properties && self.extra_properties.column == column.id
|
selected: self.extra_properties && self.extra_properties.column == column.id
|
||||||
} [ column.title ]
|
} [ column.title ]
|
||||||
|
|
||||||
|
color-to-form-selection = (self, color, current-color) ->
|
||||||
|
h \option {
|
||||||
|
value: color
|
||||||
|
selected: current-color && current-color == color
|
||||||
|
} [ color ]
|
||||||
|
|
||||||
TaskCreationModal = (project, todod-ws, task) ->
|
user-form-selection = (self, user) ->
|
||||||
|
h \option {
|
||||||
|
value: user.uid
|
||||||
|
} [ user.login ]
|
||||||
|
|
||||||
|
TaskCreationModal = (project, todod-ws, task, users) ->
|
||||||
task ||= {}
|
task ||= {}
|
||||||
|
|
||||||
# copy not to override anything on cancel
|
# copy not to override anything on cancel
|
||||||
self = {
|
self = {
|
||||||
title: task.title || ""
|
title: task.title || ""
|
||||||
description: task.description || ""
|
description: task.description || ""
|
||||||
extra_properties: {
|
extra_properties:
|
||||||
column: ""
|
column: ""
|
||||||
}
|
background-color: ""
|
||||||
|
assignee-id: task.assignee-id || void
|
||||||
|
tmp:
|
||||||
|
users: users || []
|
||||||
}
|
}
|
||||||
|
|
||||||
if task.extra_properties && task.extra_properties.column
|
# copy extra properties
|
||||||
self.extra_properties.column = task.extra_properties.column
|
# currently: column + background-color + assignee + expected duration time
|
||||||
|
for k,v of task.extra_properties
|
||||||
|
self.extra_properties[k] = v
|
||||||
|
|
||||||
modal = Modal {
|
modal = Modal {
|
||||||
+visible
|
+visible
|
||||||
content-render: (self) ->
|
content-render: (self) ->
|
||||||
h \div.form [
|
h \div.form [
|
||||||
|
|
||||||
|
#
|
||||||
|
# TITLE
|
||||||
|
#
|
||||||
|
|
||||||
h \input.input {
|
h \input.input {
|
||||||
value: self.title
|
value: self.title
|
||||||
oninput: (e) ->
|
oninput: (e) ->
|
||||||
self.title := e.target.value
|
self.title := e.target.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
|
||||||
h \textarea {
|
h \textarea {
|
||||||
value: self.description
|
value: self.description
|
||||||
oninput: (e) ->
|
oninput: (e) ->
|
||||||
|
@ -51,13 +99,52 @@ TaskCreationModal = (project, todod-ws, task) ->
|
||||||
} project.extra_properties.columns.map (column) -> column-form-selection self, column
|
} project.extra_properties.columns.map (column) -> column-form-selection self, column
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# USER MANAGEMENT
|
||||||
|
#
|
||||||
|
|
||||||
|
h \hr []
|
||||||
|
|
||||||
|
h \p [ "Assign someone to the task" ]
|
||||||
|
|
||||||
|
h \div.field.has-addons {
|
||||||
|
key: "assign-someone-to-task"
|
||||||
|
} [
|
||||||
|
h \div.select.control [
|
||||||
|
h \select {
|
||||||
|
onchange: (e) ->
|
||||||
|
self.extra_properties.assignee-id := e.target.value
|
||||||
|
} [
|
||||||
|
user-form-selection self, { login: "Choose a user", uid: "-" }
|
||||||
|
for user-id, user of self.tmp.users
|
||||||
|
user-form-selection self, user
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BACKGROUND COLOR
|
||||||
|
#
|
||||||
|
|
||||||
|
h \p [ "Choose the background color" ]
|
||||||
|
|
||||||
|
h \div.select [
|
||||||
|
h \select {
|
||||||
|
onchange: (e) ->
|
||||||
|
self.extra_properties.background-color := e.target.value
|
||||||
|
} colors.map (color) -> color-to-form-selection self, color, self.extra_properties.background-color
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
on-validation: ->
|
on-validation: ->
|
||||||
|
tmp = delete self.tmp
|
||||||
if task.id
|
if task.id
|
||||||
todod-ws.edit-task task.id, self
|
todod-ws.edit-task task.id, self
|
||||||
else
|
else
|
||||||
todod-ws.add-task project.id, self.title, self
|
todod-ws.add-task project.id, self.title, self
|
||||||
|
self.tmp = tmp
|
||||||
}, self
|
}, self
|
||||||
|
|
||||||
self.render = ->
|
self.render = ->
|
||||||
|
|
|
@ -1,62 +1,53 @@
|
||||||
#
|
|
||||||
# Tasks, previous version of todos
|
|
||||||
#
|
|
||||||
|
|
||||||
h = require 'maquette' .h
|
h = require 'maquette' .h
|
||||||
bulma = require "./bulma.ls"
|
bulma = require "./bulma.ls"
|
||||||
nmd = require "nano-markdown"
|
nmd = require "nano-markdown"
|
||||||
TaskCreationModal = require './task-creation-modal.ls'
|
TaskCreationModal = require './task-creation-modal.ls'
|
||||||
TaskRemovalModal = require './task-removal-modal.ls'
|
TaskRemovalModal = require './task-removal-modal.ls'
|
||||||
|
|
||||||
#
|
display-login = (task, users) ->
|
||||||
# generic functions
|
if task.extra_properties && task.extra_properties.assignee-id && users && users[task.extra_properties.assignee-id] && users[task.extra_properties.assignee-id].login
|
||||||
#
|
h \p [ '@' + users[task.extra_properties.assignee-id].login ]
|
||||||
|
else
|
||||||
get-previous = (collection, element) ->
|
h \p [ '-' ]
|
||||||
var previous
|
|
||||||
|
|
||||||
for item in collection
|
|
||||||
if item == element
|
|
||||||
return previous
|
|
||||||
|
|
||||||
previous = item
|
|
||||||
|
|
||||||
get-next = (collection, element) ->
|
|
||||||
var found-element
|
|
||||||
|
|
||||||
for item in collection
|
|
||||||
if found-element
|
|
||||||
return item
|
|
||||||
|
|
||||||
if item == element
|
|
||||||
found-element := true
|
|
||||||
|
|
||||||
|
|
||||||
Task = (self, project, todod-ws) ->
|
Task = (self, project, todod-ws) ->
|
||||||
modal = void
|
modal = void
|
||||||
|
|
||||||
self.render = ->
|
self.render = ->
|
||||||
h \div.card { key: self.id } [
|
background-color = "grey"
|
||||||
|
if self.extra_properties && self.extra_properties.background-color
|
||||||
|
background-color = self.extra_properties.background-color
|
||||||
|
|
||||||
|
h "div.card.has-background-#{background-color}" {
|
||||||
|
key: self.id
|
||||||
|
} [
|
||||||
h \div.card-content [
|
h \div.card-content [
|
||||||
h \div.media [
|
h \div.media [
|
||||||
h \div.media-left [
|
h \div.media-left [
|
||||||
|
# FIXME: assignee card image
|
||||||
"LEFT"
|
"LEFT"
|
||||||
|
display-login self, project.users
|
||||||
]
|
]
|
||||||
h \div.media-content [
|
|
||||||
self.title
|
h \div.media-content [ self.title ]
|
||||||
]
|
|
||||||
h \div.button {
|
h \div.button {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
modal := TaskCreationModal project, todod-ws, self
|
modal := TaskCreationModal project, todod-ws, self, project.users
|
||||||
} [ "Edit" ]
|
} [ "Edit" ]
|
||||||
h \div.button {
|
|
||||||
|
h \div.button.is-danger {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
modal := TaskRemovalModal project.id, todod-ws, self
|
modal := TaskRemovalModal project.id, todod-ws, self
|
||||||
} [ "X" ]
|
} [ "X" ]
|
||||||
]
|
]
|
||||||
h \div.content [
|
|
||||||
self.description
|
h \div.content {
|
||||||
]
|
key: "task-description-#{self.id}"
|
||||||
|
after-create: (dom) ->
|
||||||
|
dom.innerHTML = nmd self.description
|
||||||
|
} [ ]
|
||||||
]
|
]
|
||||||
if modal
|
if modal
|
||||||
modal.render!
|
modal.render!
|
||||||
|
|
|
@ -68,10 +68,11 @@ module.exports = {
|
||||||
|
|
||||||
self.socket.onmessage = (event) ->
|
self.socket.onmessage = (event) ->
|
||||||
message = JSON.parse(event.data)
|
message = JSON.parse(event.data)
|
||||||
console.log "todod message received: ", message
|
parsed-message = JSON.parse(message.payload)
|
||||||
|
console.log "todod message #{message.mtype} received: ", parsed-message
|
||||||
|
|
||||||
for f in self.callbacks[message.mtype]
|
for f in self.callbacks[message.mtype]
|
||||||
f JSON.parse(message.payload)
|
f parsed-message
|
||||||
|
|
||||||
self.reopen = ->
|
self.reopen = ->
|
||||||
self.socket.close!
|
self.socket.close!
|
||||||
|
@ -80,37 +81,43 @@ module.exports = {
|
||||||
self.open-socket!
|
self.open-socket!
|
||||||
|
|
||||||
self.send = (type, opts) ->
|
self.send = (type, opts) ->
|
||||||
console.log JSON.stringify { mtype: type, payload: opts }
|
console.log "sending message #{type} to todod: ", opts
|
||||||
|
# console.log JSON.stringify { mtype: type, payload: opts }
|
||||||
self.socket.send JSON.stringify { mtype: type, payload: opts }
|
self.socket.send JSON.stringify { mtype: type, payload: opts }
|
||||||
|
|
||||||
|
|
||||||
self.list-lists = ->
|
self.list-lists = ->
|
||||||
self.send request-types[\list-lists], JSON.stringify {
|
self.send request-types[\list-lists], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
|
id: "list-lists"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get-list = (list-id) ->
|
self.get-list = (list-id) ->
|
||||||
self.send request-types[\get-list], JSON.stringify {
|
self.send request-types[\get-list], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "get-list"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get-tasks = (list-id) ->
|
self.get-tasks = (list-id) ->
|
||||||
self.send request-types[\get-tasks], JSON.stringify {
|
self.send request-types[\get-tasks], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "get-tasks"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get-task = (task-id) ->
|
self.get-task = (task-id) ->
|
||||||
self.send request-types[\get-task], JSON.stringify {
|
self.send request-types[\get-task], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
task: task-id
|
task: task-id
|
||||||
|
id: "get-task"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.remove-list = (list-id) ->
|
self.remove-list = (list-id) ->
|
||||||
self.send request-types[\remove-list], JSON.stringify {
|
self.send request-types[\remove-list], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "remove-list"
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: extra properties
|
# TODO: extra properties
|
||||||
|
@ -118,6 +125,7 @@ module.exports = {
|
||||||
payload = {
|
payload = {
|
||||||
token: self.token
|
token: self.token
|
||||||
title: title
|
title: title
|
||||||
|
id: "add-list"
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value of opts
|
for key, value of opts
|
||||||
|
@ -129,6 +137,7 @@ module.exports = {
|
||||||
payload = {
|
payload = {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "edit-list"
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value of opts
|
for key, value of opts
|
||||||
|
@ -140,6 +149,7 @@ module.exports = {
|
||||||
self.send request-types[\remove-task], JSON.stringify {
|
self.send request-types[\remove-task], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
task: task-id
|
task: task-id
|
||||||
|
id: "remove-task"
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: extra properties
|
# TODO: extra properties
|
||||||
|
@ -148,6 +158,7 @@ module.exports = {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
title: title
|
title: title
|
||||||
|
id: "add-task"
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value of opts
|
for key, value of opts
|
||||||
|
@ -159,6 +170,7 @@ module.exports = {
|
||||||
payload = {
|
payload = {
|
||||||
token: self.token
|
token: self.token
|
||||||
task: task-id
|
task: task-id
|
||||||
|
id: "edit-task"
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value of opts
|
for key, value of opts
|
||||||
|
@ -170,12 +182,14 @@ module.exports = {
|
||||||
self.send request-types[\subscribe], JSON.stringify {
|
self.send request-types[\subscribe], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "subscribe"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.unsubscribe = (list-id) ->
|
self.unsubscribe = (list-id) ->
|
||||||
self.send request-types[\unsubscribe], JSON.stringify {
|
self.send request-types[\unsubscribe], JSON.stringify {
|
||||||
token: self.token
|
token: self.token
|
||||||
list: list-id
|
list: list-id
|
||||||
|
id: "unsubscribe"
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
Loading…
Reference in New Issue