very WIP
This commit is contained in:
parent
3ce9915469
commit
5cb3eec194
@ -3,7 +3,53 @@ h = require 'maquette' .h
|
|||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
login-widget: (model, socket) ->
|
create-socket: ->
|
||||||
|
self = {}
|
||||||
|
|
||||||
|
# users can record functions to run on events
|
||||||
|
self.user-on-error = []
|
||||||
|
self.user-on-close = []
|
||||||
|
self.user-on-message = []
|
||||||
|
|
||||||
|
self.open-socket = ->
|
||||||
|
console.log "Opening socket to #{socket-url}"
|
||||||
|
self.socket := new WebSocket socket-url
|
||||||
|
|
||||||
|
self.socket.onerror = (event) ->
|
||||||
|
for f in self.user-on-error
|
||||||
|
f event
|
||||||
|
self.socket.close!
|
||||||
|
|
||||||
|
self.socket.onclose = (event) ->
|
||||||
|
for f in self.user-on-close
|
||||||
|
f event
|
||||||
|
|
||||||
|
self.socket.onmessage = (event) ->
|
||||||
|
data = JSON.parse(event.data).payload
|
||||||
|
|
||||||
|
for f in self.user-on-message
|
||||||
|
f data
|
||||||
|
|
||||||
|
self.reopen = ->
|
||||||
|
self.socket.close!
|
||||||
|
self.open-socket!
|
||||||
|
|
||||||
|
self.open-socket!
|
||||||
|
|
||||||
|
self.send = (opts) ->
|
||||||
|
console.log JSON.stringify { mtype: 0, payload: opts }
|
||||||
|
self.socket.send JSON.stringify { mtype: 0, payload: opts }
|
||||||
|
|
||||||
|
self.login = (login, password) ->
|
||||||
|
self.send JSON.stringify {
|
||||||
|
type: "login",
|
||||||
|
login: login
|
||||||
|
password: password
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
|
||||||
|
login-widget: (model) ->
|
||||||
h \div.container [
|
h \div.container [
|
||||||
h \div.box [
|
h \div.box [
|
||||||
if model.login-error
|
if model.login-error
|
||||||
@ -36,13 +82,13 @@ module.exports = {
|
|||||||
e.prevent-default!
|
e.prevent-default!
|
||||||
|
|
||||||
model.login-error = undefined
|
model.login-error = undefined
|
||||||
socket.login model.login, model.password
|
model.authd-ws.login model.login, model.password
|
||||||
} [ "Connexion" ]
|
} [ "Connexion" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
login-page: (model, socket) ->
|
login-page: (model) ->
|
||||||
h \div.container [
|
h \div.container [
|
||||||
h \div.box [
|
h \div.box [
|
||||||
if model.login-error
|
if model.login-error
|
||||||
@ -74,8 +120,7 @@ module.exports = {
|
|||||||
onclick: (e) ->
|
onclick: (e) ->
|
||||||
e.prevent-default!
|
e.prevent-default!
|
||||||
|
|
||||||
model.login-error = undefined
|
model.authd-ws.login model.login, model.password
|
||||||
socket.login model.login, model.password
|
|
||||||
} [ "Connexion" ]
|
} [ "Connexion" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
150
client/index.ls
150
client/index.ls
@ -25,43 +25,48 @@ model = {
|
|||||||
selected: undefined
|
selected: undefined
|
||||||
users: {}
|
users: {}
|
||||||
projects: {}
|
projects: {}
|
||||||
list-todos: []
|
todo-list: []
|
||||||
connection: {
|
|
||||||
port: 9999
|
port: 9999
|
||||||
url: undefined
|
todod-url: undefined
|
||||||
socket: undefined
|
|
||||||
}
|
authd-ws: undefined
|
||||||
|
todod-ws: undefined
|
||||||
|
|
||||||
|
previous-error: undefined
|
||||||
|
error: undefined
|
||||||
|
|
||||||
|
# authentication token
|
||||||
|
jwt: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
# '://' + location.hostname + \: +
|
# '://' + location.hostname + \: +
|
||||||
model.connection.url =
|
model.todod-url =
|
||||||
(if location.protocol == 'https' then 'wss' else 'ws') +
|
(if location.protocol == 'https' then 'wss' else 'ws') +
|
||||||
"://www.junkos.netlib.re:" +
|
"://www.junkos.netlib.re:" +
|
||||||
model.connection.port +
|
model.port +
|
||||||
"/kanban.JSON"
|
"/kanban.JSON"
|
||||||
|
|
||||||
console.log model.connection.url
|
console.log model.todod-url
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# network configuration
|
# network configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
socket = todows.create-socket model.connection.url
|
model.authd-ws = authd.create-socket model.authd-url
|
||||||
|
model.todod-ws = todows.create-socket model.todod-url
|
||||||
|
|
||||||
on-websocket-error = (event) ->
|
on-websocket-error = (event) ->
|
||||||
console.log "WebSocket error.", event
|
console.log "WebSocket error.", event
|
||||||
model.state := "network-error"
|
model.current-view := "network-error"
|
||||||
projector.schedule-render!
|
projector.schedule-render!
|
||||||
|
|
||||||
on-websocket-close = ->
|
on-websocket-close = (event) ->
|
||||||
model.current-view := "login"
|
model.current-view := "login"
|
||||||
# socket.reopen!
|
console.log "WebSocket has been closed.", event
|
||||||
|
# model.todod-ws.reopen!
|
||||||
|
|
||||||
# Exporting the error in case the UI is able to deal with it.
|
|
||||||
model.previous-state := model.state
|
|
||||||
model.state := "network-error"
|
|
||||||
model.websocket-error := event.reason
|
|
||||||
projector.schedule-render!
|
projector.schedule-render!
|
||||||
|
|
||||||
on-websocket-message = (data) ->
|
on-websocket-message = (data) ->
|
||||||
@ -69,13 +74,11 @@ on-websocket-message = (data) ->
|
|||||||
|
|
||||||
switch message.type
|
switch message.type
|
||||||
when "login"
|
when "login"
|
||||||
model.current-view := "list-todos"
|
model.current-view := "todo-list"
|
||||||
when "list-projects"
|
when "list-projects"
|
||||||
for project in message.projects
|
model.todo-list := message.projects || []
|
||||||
model.projects[project.id] = Project.new project, model, socket
|
|
||||||
model.list-todos := message.projects
|
|
||||||
when "project"
|
when "project"
|
||||||
model.projects[message.project.id] = Project.new message.project, model, socket
|
model.projects[message.project.id] = Project.new message.project, model
|
||||||
when "user"
|
when "user"
|
||||||
if message.user
|
if message.user
|
||||||
model.users[message.user.uid] := message.user
|
model.users[message.user.uid] := message.user
|
||||||
@ -89,11 +92,52 @@ on-websocket-message = (data) ->
|
|||||||
console.log message
|
console.log message
|
||||||
|
|
||||||
# record changes that need to happen on a network event
|
# record changes that need to happen on a network event
|
||||||
socket.user-on-error ++= [ on-websocket-error ]
|
model.todod-ws.user-on-error ++= [ on-websocket-error ]
|
||||||
socket.user-on-close ++= [ on-websocket-close ]
|
model.todod-ws.user-on-close ++= [ on-websocket-close ]
|
||||||
socket.user-on-message ++= [ on-websocket-message ]
|
model.todod-ws.user-on-message ++= [ on-websocket-message ]
|
||||||
|
|
||||||
|
|
||||||
|
render-navbar = ->
|
||||||
|
h \div.navbar [
|
||||||
|
h \div.navbar-start [
|
||||||
|
h \a.navbar-item.is-size-1 {
|
||||||
|
onclick: ->
|
||||||
|
model.viewed-project := undefined
|
||||||
|
model.current-view := "todo-list"
|
||||||
|
} [ "⌂" ]
|
||||||
|
]
|
||||||
|
h \div.navbar-end [
|
||||||
|
h \a.navbar-item {
|
||||||
|
onclick: ->
|
||||||
|
model.current-view := "login"
|
||||||
|
model.todod-ws.reopen!
|
||||||
|
} [ "Logout" ]
|
||||||
|
]
|
||||||
|
authd.login-widget model
|
||||||
|
]
|
||||||
|
|
||||||
|
render-todo-list = ->
|
||||||
|
h \div.section model.todo-list.map (project) ->
|
||||||
|
h \a.box {
|
||||||
|
key: project.id
|
||||||
|
onclick: ->
|
||||||
|
model.current-view := "todo"
|
||||||
|
model.viewed-project := project.id
|
||||||
|
model.todod-ws.get-project project.id
|
||||||
|
} [
|
||||||
|
bulma.title 3 project.name
|
||||||
|
]
|
||||||
|
|
||||||
|
render-new-project-button = ->
|
||||||
|
h \div.button.is-primary.is-large.is-fullwidth {
|
||||||
|
onclick: ->
|
||||||
|
model.todod-ws.new-project "New project"
|
||||||
|
} [ "New project! (random atm)" ]
|
||||||
|
|
||||||
|
render-todo = (todo-id) ->
|
||||||
|
if model.projects[todo-id]
|
||||||
|
model.projects[todo-id].render!
|
||||||
|
|
||||||
#
|
#
|
||||||
# Pages:
|
# Pages:
|
||||||
# login
|
# login
|
||||||
@ -102,60 +146,26 @@ socket.user-on-message ++= [ on-websocket-message ]
|
|||||||
# network-error
|
# network-error
|
||||||
#
|
#
|
||||||
|
|
||||||
|
render-body = ->
|
||||||
|
|
||||||
renderer = ->
|
|
||||||
render-navbar = ->
|
|
||||||
h \div.navbar [
|
|
||||||
h \div.navbar-start [
|
|
||||||
h \a.navbar-item.is-size-1 {
|
|
||||||
onclick: ->
|
|
||||||
model.viewed-project := undefined
|
|
||||||
model.current-view := "list-todos"
|
|
||||||
} [ "⌂" ]
|
|
||||||
]
|
|
||||||
h \div.navbar-end [
|
|
||||||
h \a.navbar-item {
|
|
||||||
onclick: ->
|
|
||||||
model.current-view := "login"
|
|
||||||
socket.reopen!
|
|
||||||
} [ "Logout" ]
|
|
||||||
]
|
|
||||||
authd.login-widget model, socket
|
|
||||||
]
|
|
||||||
|
|
||||||
h \div.section [
|
h \div.section [
|
||||||
switch model.current-view
|
switch model.current-view
|
||||||
when "login"
|
when "login"
|
||||||
authd.login-page model, socket
|
authd.login-page model
|
||||||
|
|
||||||
when "list-todos"
|
when "todo-list"
|
||||||
h \div#list-todos [
|
h \div#todo-list [
|
||||||
render-navbar!
|
render-navbar!
|
||||||
|
|
||||||
h \div.section (model.list-todos || []).map (project) ->
|
render-todo-list!
|
||||||
h \a.box {
|
|
||||||
key: project.id
|
|
||||||
onclick: ->
|
|
||||||
model.current-view := "project"
|
|
||||||
model.viewed-project := project.id
|
|
||||||
socket.get-project project.id
|
|
||||||
} [
|
|
||||||
bulma.title 3 project.name
|
|
||||||
]
|
|
||||||
|
|
||||||
h \div.button.is-primary.is-large.is-fullwidth {
|
render-new-project-button!
|
||||||
onclick: ->
|
|
||||||
socket.new-project "Hello, there!"
|
|
||||||
} [ "New project! (random atm)" ]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
when "project"
|
when "todo"
|
||||||
h \div [
|
h \div [
|
||||||
render-navbar!
|
render-navbar!
|
||||||
|
|
||||||
if model.projects[model.viewed-project]
|
render-todo model.viewed-project
|
||||||
model.projects[model.viewed-project].render!
|
|
||||||
]
|
]
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -164,6 +174,12 @@ renderer = ->
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderer = ->
|
||||||
|
render-navbar!
|
||||||
|
|
||||||
|
render-body!
|
||||||
|
|
||||||
document.add-event-listener 'DOMContentLoaded' ->
|
document.add-event-listener 'DOMContentLoaded' ->
|
||||||
projector.append document.body, renderer
|
projector.append document.body, renderer
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ Task = require "./task.ls"
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
new: (self, model, socket) ->
|
new: (self, model) ->
|
||||||
self.tasks = self.tasks.map (e) -> Task.new e, self, model, socket
|
self.tasks = self.tasks.map (e) -> Task.new e, self, model
|
||||||
|
|
||||||
self.render-column = (column) ->
|
self.render-column = (column) ->
|
||||||
h \div.column.is-3 {
|
h \div.column.is-3 {
|
||||||
@ -24,7 +24,7 @@ module.exports = {
|
|||||||
console.log "onchange??"
|
console.log "onchange??"
|
||||||
model.editing := undefined
|
model.editing := undefined
|
||||||
|
|
||||||
socket.edit-column self.id, column.id, {
|
model.todod-ws.edit-column self.id, column.id, {
|
||||||
name: e.target.value
|
name: e.target.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ module.exports = {
|
|||||||
h \div.card-content [
|
h \div.card-content [
|
||||||
h \div.button.is-fullwidth.is-danger {
|
h \div.button.is-fullwidth.is-danger {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.delete-column self.id, column.id
|
model.todod-ws.delete-column self.id, column.id
|
||||||
} [ "Delete me!"]
|
} [ "Delete me!"]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -69,7 +69,7 @@ module.exports = {
|
|||||||
|
|
||||||
h \div.button.is-fullwidth {
|
h \div.button.is-fullwidth {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.new-task self.id, column.id, {
|
model.todod-ws.new-task self.id, column.id, {
|
||||||
title: "General Kenobi…"
|
title: "General Kenobi…"
|
||||||
description: ""
|
description: ""
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ module.exports = {
|
|||||||
h \input.input {
|
h \input.input {
|
||||||
onchange: (e) ->
|
onchange: (e) ->
|
||||||
model.editing := undefined
|
model.editing := undefined
|
||||||
socket.edit-project self.id, {
|
model.todod-ws.edit-project self.id, {
|
||||||
name: e.target.value
|
name: e.target.value
|
||||||
}
|
}
|
||||||
value: self.name
|
value: self.name
|
||||||
@ -113,7 +113,7 @@ module.exports = {
|
|||||||
} [
|
} [
|
||||||
h \div.button.is-fullwidth {
|
h \div.button.is-fullwidth {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.new-column self.id, "Hello, there!"
|
model.todod-ws.new-column self.id, "Hello, there!"
|
||||||
} [ "New Column" ]
|
} [ "New Column" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -32,19 +32,19 @@ get-next = (collection, element) ->
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
new: (self, project, model, socket) ->
|
new: (self, project, model) ->
|
||||||
self.render = ->
|
self.render = ->
|
||||||
author = model.users[self.author]
|
author = model.users[self.author]
|
||||||
if typeof(author) != "object" and author != "request sent"
|
if typeof(author) != "object" and author != "request sent"
|
||||||
model.users[self.author] = "request sent"
|
model.users[self.author] = "request sent"
|
||||||
# FIXME: This should go directly to authd.
|
# FIXME: This should go directly to authd.
|
||||||
socket.get-user self.author
|
model.todod-ws.get-user self.author
|
||||||
|
|
||||||
assigned_to = model.users[self.assigned_to]
|
assigned_to = model.users[self.assigned_to]
|
||||||
if self.assigned_to and typeof(assigned_to) != "object" and assigned_to != "request sent"
|
if self.assigned_to and typeof(assigned_to) != "object" and assigned_to != "request sent"
|
||||||
model.users[self.assigned_to] = "request sent"
|
model.users[self.assigned_to] = "request sent"
|
||||||
# FIXME: This should go directly to authd.
|
# FIXME: This should go directly to authd.
|
||||||
socket.get-user self.assigned_to
|
model.todod-ws.get-user self.assigned_to
|
||||||
|
|
||||||
is-selected = model.selected == self.id
|
is-selected = model.selected == self.id
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ module.exports = {
|
|||||||
value: self.title
|
value: self.title
|
||||||
onchange: (e) ->
|
onchange: (e) ->
|
||||||
model.editing := undefined
|
model.editing := undefined
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
title: e.target.value
|
title: e.target.value
|
||||||
}
|
}
|
||||||
} [ self.title ]
|
} [ self.title ]
|
||||||
@ -133,7 +133,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
h \div.button.is-fullwidth {
|
h \div.button.is-fullwidth {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
description: model.editing-data
|
description: model.editing-data
|
||||||
}
|
}
|
||||||
model.editing-data := undefined
|
model.editing-data := undefined
|
||||||
@ -161,7 +161,7 @@ module.exports = {
|
|||||||
h \input.input {
|
h \input.input {
|
||||||
onchange: (e) ->
|
onchange: (e) ->
|
||||||
model.editing := undefined
|
model.editing := undefined
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
assigned_to: Number e.target.value
|
assigned_to: Number e.target.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ module.exports = {
|
|||||||
h \input.input {
|
h \input.input {
|
||||||
onchange: (e) ->
|
onchange: (e) ->
|
||||||
model.editing := undefined
|
model.editing := undefined
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
color: e.target.value
|
color: e.target.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ module.exports = {
|
|||||||
h \a.card-footer-item {
|
h \a.card-footer-item {
|
||||||
key: "⇐"
|
key: "⇐"
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
column: get-previous project.columns.map((.id)), self.column
|
column: get-previous project.columns.map((.id)), self.column
|
||||||
}
|
}
|
||||||
} [ "⇐" ]
|
} [ "⇐" ]
|
||||||
@ -212,14 +212,14 @@ module.exports = {
|
|||||||
} [
|
} [
|
||||||
h \div.button.is-danger {
|
h \div.button.is-danger {
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.delete-task project.id, self.id
|
model.todod-ws.delete-task project.id, self.id
|
||||||
} [ "Delete! For real!" ]
|
} [ "Delete! For real!" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
h \a.card-footer-item {
|
h \a.card-footer-item {
|
||||||
key: "⇒"
|
key: "⇒"
|
||||||
onclick: ->
|
onclick: ->
|
||||||
socket.edit-task project.id, self.id, {
|
model.todod-ws.edit-task project.id, self.id, {
|
||||||
column: get-next project.columns.map((.id)), self.column
|
column: get-next project.columns.map((.id)), self.column
|
||||||
}
|
}
|
||||||
} [ "⇒" ]
|
} [ "⇒" ]
|
||||||
|
Loading…
Reference in New Issue
Block a user