Changeset View
Changeset View
Standalone View
Standalone View
web/static/js/api.js
import {Socket, LongPoll, Presence} from "phoenix" | import {Socket, LongPoll, Presence} from "phoenix" | ||||
import UserListWidget from "./widgets/userlist" | import UserListWidget from "./widgets/userlist" | ||||
import UserStatusWidget from "./widgets/userstatus" | import UserStatusWidget from "./widgets/userstatus" | ||||
import ChatInputWidget from "./widgets/chatinput" | import ChatInputWidget from "./widgets/chatinput" | ||||
import ChatRoomWidget from "./widgets/chatroom" | import ChatRoomWidget from "./widgets/chatroom" | ||||
class KolabChat | class KolabChat | ||||
{ | { | ||||
/** | /** | ||||
* Configuration parameters: | * Configuration parameters: | ||||
* - token: User session token | * - token: User session token | ||||
* - context: KolabChat instance identifier | |||||
* - roomId: Chat room Id to join in | * - roomId: Chat room Id to join in | ||||
* - userListElement: Id of HTML element where to put userslist widget | * - userListElement: Id of HTML element where to put userslist widget | ||||
* - userStatusElement: Id of HTML element where to put users status widget | * - userStatusElement: Id of HTML element where to put users status widget | ||||
* - chatInputElement: Id of HTML element which is a text chat input | * - chatInputElement: Id of HTML element which is a text chat input | ||||
* - chatRoomElement: Id of HTML element where to put text conversation | * - chatRoomElement: Id of HTML element where to put text conversation | ||||
*/ | */ | ||||
constructor(config) | constructor(config) | ||||
{ | { | ||||
this.config = config || {} | this.config = config || {} | ||||
if (!this.config.context) | |||||
this.config.context = location.hostname; | |||||
} | } | ||||
/** | /** | ||||
* Initialize WebSocket communication | * Initialize WebSocket communication | ||||
*/ | */ | ||||
init(config) | init(config) | ||||
{ | { | ||||
if (config) | if (config) | ||||
this.config = KolabChat.extend(this.config, config) | this.config = KolabChat.extend(this.config, config) | ||||
this.initWidgets() | this.initWidgets() | ||||
// TODO: for integration with external systems we'll use configurable full wss:// url | // TODO: for integration with external systems we'll use configurable full wss:// url | ||||
this.socket = new Socket("/socket", { | this.socket = new Socket("/socket", { | ||||
params: {token: this.config.token}, | params: {token: this.config.token, context: this.config.context}, | ||||
logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }), | logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }), | ||||
}) | }) | ||||
this.socket.onOpen(e => { | this.socket.onOpen(e => { | ||||
// when connected start using 'system' channel | // when connected start using 'system' channel | ||||
// for users' presence | // for users' presence | ||||
this.initPresence() | this.initPresence() | ||||
if (this.config.roomId) { | if (this.config.roomId) { | ||||
Show All 40 Lines | class KolabChat | ||||
} | } | ||||
/** | /** | ||||
* Initialize user presence | * Initialize user presence | ||||
* Create users list and status widgets | * Create users list and status widgets | ||||
*/ | */ | ||||
initPresence() | initPresence() | ||||
{ | { | ||||
this.system = this.socket.channel("system") | this.system = this.socket.channel("system", {context: this.config.context}) | ||||
this.system.on("info", info => { | this.system.on("info", info => { | ||||
this.username = info.user | this.username = info.user | ||||
}) | }) | ||||
this.system.on("presence_state", state => { | this.system.on("presence_state", state => { | ||||
this.presences = Presence.syncState({}, state) | this.presences = Presence.syncState({}, state) | ||||
this.renderPresences(this.presences) | this.renderPresences(this.presences) | ||||
Show All 38 Lines | class KolabChat | ||||
/** | /** | ||||
* Handler for presence responses | * Handler for presence responses | ||||
*/ | */ | ||||
renderPresences(presences) | renderPresences(presences) | ||||
{ | { | ||||
let userPresence | let userPresence | ||||
if (this.userStatusWidget && (userPresence = presences[this.username])) { | if (this.userStatusWidget && (userPresence = presences[this.username])) { | ||||
userPresence = this.listBy(this.username, userPresence) | userPresence = this.listBy(this.username, userPresence, this.config.context) | ||||
this.userStatusWidget.render(userPresence) | this.userStatusWidget.render(userPresence) | ||||
} | } | ||||
if (this.userListWidget) { | if (this.userListWidget) { | ||||
presences = Presence.list(presences, this.listBy) | presences = Presence.list(presences, this.listBy) | ||||
this.userListWidget.render(presences) | this.userListWidget.render(presences) | ||||
} | } | ||||
} | } | ||||
listBy(user, {metas: metas}) | listBy(user, {metas: metas}, context) | ||||
{ | { | ||||
let statusWeights = { | |||||
offline: 0, | |||||
busy: 10, | |||||
away: 20, | |||||
online: 30 | |||||
} | |||||
// Find "best" availability status for the user | |||||
// If set, narrow the result to the current session context | |||||
let mostAvailableStatus = metas.reduce((best, meta) => { | |||||
if (context && context != meta.context) | |||||
return best | |||||
return statusWeights[best] > statusWeights[meta.status] ? best : meta.status | |||||
}, | |||||
"offline") | |||||
return { | return { | ||||
user: user, | user: user, | ||||
status: metas[0].status | status: mostAvailableStatus | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* User status change | * User status change | ||||
*/ | */ | ||||
setStatus(status) | setStatus(status) | ||||
{ | { | ||||
Show All 27 Lines |