templates_talk_DATA = \
src/templates/talk/base.html \
src/templates/talk/index.html \
- src/templates/talk/registrations.html
+ src/templates/talk/registrations.html \
+ src/templates/talk/user.html \
+ src/templates/talk/users.html
templates_talkdir = $(templatesdir)/talk
templates_talk_modules_DATA = \
+ src/templates/talk/modules/accounts-list.html \
src/templates/talk/modules/channels.html \
src/templates/talk/modules/registrations.html
# Connect to FreeSWITCH
self.freeswitch = Freeswitch(self.backend)
+ @property
+ def accounts(self):
+ for account in self.backend.accounts:
+ if not account.is_talk_enabled():
+ continue
+
+ yield account
+
def get_lines(self, account=None):
accounts_cache = {}
{% block main %}{% end block %}
</div>
- <div class="col-md-3 text-center">
- <img class="img-fluid rounded-circle mb-4" src="{{ current_user.avatar_url(160) }}" alt="{{ current_user }}" />
-
- <p>{{ current_user.name }}</p>
+ {% block right %}
+ <div class="col-md-3 text-center">
+ <img class="img-fluid rounded-circle mb-4" src="{{ current_user.avatar_url(160) }}" alt="{{ current_user }}" />
- <p>
- {% if current_user.sip_registrations %}
- <a class="text-success" href="/users/{{ current_user.uid }}/registrations">
- {{ _("Online") }} ({{ len(current_user.sip_registrations) }})
- </a>
- {% else %}
- <span class="text-danger">{{ _("Offline") }}</span>
- {% end %}
- </p>
- </div>
+ <p>{{ current_user.name }}</p>
+
+ <p>
+ {% if current_user.sip_registrations %}
+ <a class="text-success" href="/users/{{ current_user.uid }}/registrations">
+ {{ _("Online") }} ({{ len(current_user.sip_registrations) }})
+ </a>
+ {% else %}
+ <span class="text-danger">{{ _("Offline") }}</span>
+ {% end %}
+ </p>
+ </div>
+ {% end block %}
</div>
{% end block %}
--- /dev/null
+{% for group in grouper(accounts, 2) %}
+ <div class="row">
+ {% for account in group %}
+ <div class="col-12 col-lg-6 mb-3">
+ <div class="card">
+ <div class="card-body">
+ <h6 class="card-title mb-0">
+ <img class="img-fluid rounded-circle" src="{{ account.avatar_url(23) }}" alt="{{ account }}" />
+
+ <a href="/users/{{ account.uid }}">{{ account }}</a>
+ </h6>
+ </div>
+ </div>
+ </div>
+ {% end %}
+ </div>
+{% end %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ account }}{% end block %}
+
+{% block main %}
+ <div class="row justify-content-center">
+ <div class="col col-md-6 col-lg-4 mb-5">
+ <img class="img-fluid rounded-circle my-5" src="{{ account.avatar_url(512) }}" alt="{{ account }}" />
+
+ <h3 class="text-center mb-0">{{ account }}</h3>
+
+ {% if account.sip_id %}
+ <h5 class="text-center mb-0">{{ account.sip_id }}</h5>
+ {% end %}
+ </div>
+ </div>
+
+ <div class="row justify-content-center">
+ <div class="col col-md-8">
+ <div class="card p-3">
+ <div class="card-body">
+ <div class="row">
+ <div class="col">
+ <a class="btn btn-dark btn-block" href="mailto:{{ account.email }}">
+ {{ _("Email %s") % account.first_name }}
+ </a>
+ </div>
+ </div>
+
+ <div class="row">
+ {% if account.address %}
+ <div class="col-md-6 mt-5">
+ <h6>{{ _("Postal Address") }}</h6>
+
+ <address>
+ <strong>{{ account.name }}</strong>
+ <br>
+ {% for line in account.address.splitlines() %}
+ {{ line }}<br>
+ {% end %}
+ </address>
+ </div>
+ {% end %}
+
+ {% if account.telephone_numbers %}
+ <div class="col-md-6 mt-5">
+ <h6>{{ _("Telephone Numbers") }}</h6>
+
+ <ul class="list-unstyled">
+ {% for number in account.telephone_numbers %}
+ <li>
+ {% if number in account.mobile_telephone_numbers %}
+ <span class="fa fa-mobile" title="{{ _("Mobile Phone") }}"></span>
+ {% elif number in account.home_telephone_numbers %}
+ <span class="fa fa-home" title="{{ _("Home Telephone") }}"></span>
+ {% else %}
+ <span class="fa fa-phone"></span>
+ {% end %}
+ <a href="tel:{{ number }}">{{ number }}</a>
+ </li>
+ {% end %}
+ </ul>
+ </div>
+ {% end %}
+ </div>
+
+ {% if (current_user == account or current_user.is_admin()) and account.uses_sip_forwarding() %}
+ <p class="text-muted mb-0">
+ {{ _("All calls are forwarded to") }}
+ <a href="sip:{{ account.sip_routing_url }}">{{ account.sip_routing_url }}</a>
+ </p>
+ {% end %}
+ </div>
+ </div>
+ </div>
+ </div>
+{% end block %}
+
+{% block right %}{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Users") }}{% end block %}
+
+{% block main %}
+ <h3 class="mb-4">{{ _("Users") }}</h3>
+
+ {% module TalkAccountsList() %}
+{% end block %}
#/usr/bin/python
import logging
+import itertools
import os.path
import tornado.locale
import tornado.options
# UI Modules
"ui_methods" : {
"format_month_name" : self.format_month_name,
+ "grouper" : grouper,
},
"ui_modules" : {
"Menu" : ui_modules.MenuModule,
"Map" : ui_modules.MapModule,
# Talk
+ "TalkAccountsList" : talk.AccountsListModule,
"TalkChannels" : talk.ChannelsModule,
"TalkRegistrations" : talk.RegistrationsModule,
# talk.ipfire.org
self.add_handlers(r"talk(\.dev)?\.ipfire\.org", [
(r"/", talk.IndexHandler),
+ (r"/users", talk.UsersHandler),
+ (r"/users/(\w+)", talk.UserHandler),
(r"/users/(\w+)/registrations", talk.RegistrationsHandler),
(r"/conferences", TalkConferencesHandler),
(r"/diagnosis", TalkDiagnosisHandler),
return _("December")
return month
+
+
+def grouper(handler, iterator, n):
+ """
+ Returns groups of n from the iterator
+ """
+ i = iter(iterator)
+
+ while True:
+ ret = list(itertools.islice(i, 0, n))
+ if not ret:
+ break
+
+ yield ret
self.render("talk/registrations.html", account=account)
+class UsersHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self):
+ self.render("talk/users.html")
+
+
+class UserHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, uid):
+ account = self.backend.accounts.get_by_uid(uid)
+ if not account:
+ raise tornado.web.HTTPError(404, "Could not find account %s" % uid)
+
+ self.render("talk/user.html", account=account)
+
+
+class AccountsListModule(ui_modules.UIModule):
+ def render(self, accounts=None):
+ if accounts is None:
+ accounts = self.backend.talk.accounts
+
+ return self.render_string("talk/modules/accounts-list.html", accounts=accounts)
+
+
class ChannelsModule(ui_modules.UIModule):
def render(self, account):
channels = self.backend.talk.freeswitch.get_sip_channels(account)