Browse Source

Add translation to templates and views, convert datetime to user local time and move dashboard JS to file

develop
Sam Black 4 years ago
parent
commit
2de5c273f5
Signed by: samwwwblack GPG Key ID: 0FF0223994EA47D8
  1. 2
      babel/babel.cfg
  2. 8
      cupola/api/templates/api/event.html
  3. 6
      cupola/api/templates/api/event.txt
  4. 16
      cupola/api/templates/api/event_limit.html
  5. 12
      cupola/api/templates/api/event_limit.txt
  6. 2
      cupola/static/js/cupola.js
  7. 70
      cupola/static/js/dashboard.js
  8. 64
      cupola/templates/dashboard/index.html
  9. 27
      cupola/templates/events/index.html
  10. 9
      cupola/templates/events/list.html
  11. 7
      cupola/templates/events/view.html
  12. 48
      cupola/templates/events/view_group.html
  13. 2
      cupola/templates/layout/base.html
  14. 32
      cupola/templates/layout/header.html
  15. 4
      cupola/templates/layout/layout.html
  16. 7
      cupola/templates/layout/macros.html
  17. 10
      cupola/templates/projects/edit.html
  18. 22
      cupola/templates/projects/index.html
  19. 32
      cupola/templates/projects/keys.html
  20. 12
      cupola/templates/projects/new.html
  21. 14
      cupola/templates/projects/notification.html
  22. 47
      cupola/templates/projects/view.html
  23. 32
      cupola/templates/security/_sidebar_menu.html
  24. 4
      cupola/templates/security/change_password.html
  25. 8
      cupola/templates/security/email/change_notice.html
  26. 4
      cupola/templates/security/email/change_notice.txt
  27. 8
      cupola/templates/security/email/confirmation_instructions.html
  28. 4
      cupola/templates/security/email/confirmation_instructions.txt
  29. 8
      cupola/templates/security/email/login_instructions.html
  30. 6
      cupola/templates/security/email/login_instructions.txt
  31. 6
      cupola/templates/security/email/reset_instructions.html
  32. 4
      cupola/templates/security/email/reset_instructions.txt
  33. 2
      cupola/templates/security/email/reset_notice.html
  34. 2
      cupola/templates/security/email/reset_notice.txt
  35. 8
      cupola/templates/security/email/welcome.html
  36. 6
      cupola/templates/security/email/welcome.txt
  37. 7
      cupola/templates/security/forgot_password.html
  38. 44
      cupola/templates/security/login_user.html
  39. 4
      cupola/templates/security/register_user.html
  40. 4
      cupola/templates/security/reset_password.html
  41. 4
      cupola/templates/security/send_confirmation.html
  42. 4
      cupola/templates/security/send_login.html
  43. 25
      cupola/templates/users/edit.html
  44. 14
      cupola/templates/users/index.html
  45. 10
      cupola/templates/users/new.html
  46. 28
      cupola/templates/users/profile.html
  47. 4
      cupola/utils.py
  48. 14
      cupola/views/events.py

2
babel.cfg → babel/babel.cfg

@ -2,3 +2,5 @@
[python: run.py]
[jinja2: cupola/**/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
[jinja2: cupola/**/templates/**.txt]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

8
cupola/api/templates/api/event.html

@ -1,9 +1,11 @@
Hi {{ user.username }},
{% trans username=user.username, project_name=group.project.name, group_message=group.message, event_url=event_url %}
Hi {{ username }},
<p>
Project <strong>{{ group.project.name }}</strong> has registered a new event
for event group <em>{{ group.message }}</em>.
Project <strong>{{ project_name }}</strong> has registered a new event
for event group <em>{{ group_message }}</em>.
</p>
<p>
You can view this event <a href="{{ event_url }}">here</a>.
</p>
{% endtrans %}

6
cupola/api/templates/api/event.txt

@ -1,5 +1,7 @@
Hi {{ user.username }},
{% trans username=user.username, project_name=group.project.name, group_message=group.message, event_url=event_url %}
Hi {{ username }},
Project "{{ group.project.name }}" has registered a new event for event group "{{ group.message }}".
Project "{{ project_name }}" has registered a new event for event group "{{ group_message }}".
You can view this event at {{ event_url }}
{% endtrans %}

16
cupola/api/templates/api/event_limit.html

@ -1,14 +1,24 @@
Hi {{ user.username }},
{% trans username=user.username, project_name=group.project.name, group_message=group.message %}
Hi {{ username }},
<p>
Project <strong>{{ group.project.name }}</strong> has registered a new event
for event group <em>{{ group.message }}</em>.
Project <strong>{{ project_name }}</strong> has registered a new event
for event group <em>{{ group_message }}</em>.
</p>
{% endtrans %}
{% trans event_count=event_count %}
<p>
There is an additional event that have been reported.
</p>
{% pluralize event_count %}
<p>
There are additional {{ event_count }} events that have been reported.
</p>
{% endtrans %}
{% trans event_list_url=event_list_url %}
<p>
You can view this list <a href="{{ event_list_url }}">here</a>.
</p>
{% endtrans %}

12
cupola/api/templates/api/event_limit.txt

@ -1,7 +1,15 @@
Hi {{ user.username }},
{% trans username=user.username, project_name=group.project.name, group_message=group.message %}
Hi {{ username }},
Project "{{ group.project.name }}" has registered a new event for event group "{{ group.message }}".
Project "{{ project_name }}" has registered a new event for event group "{{ group_message }}".
{% endtrans %}
{% trans event_count=event_count %}
There is an additional event that have been reported.
{% pluralize event_count %}
There are additional {{ event_count }} events that have been reported.
{% endtrans %}
{% trans event_list_url=event_list_url %}
You can view this list at {{ event_list_url }}
{% endtrans %}

2
cupola/static/js/cupola.js

@ -18,6 +18,8 @@
$(document).ready(function() {
$('.combobox').combobox();
$('[data-toggle="tooltip"]').tooltip();
$(".rotatable").click(function(){
$(this).toggleClass("right");
});

70
cupola/static/js/dashboard.js

@ -0,0 +1,70 @@
/**
dashboard.js: Dashboard view.
Copyright (C) 2017 Sam Black <samwwwblack@lapwing.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(document).ready(function() {
var infoDiv = $("#chartInfo");
$.ajax({
url: '/event/dashboard/',
dataType: 'json',
success: function(data) {
if (data.groups.length === 1 && data.columns.length === 1) {
return;
}
c3.generate({
axis: {
x: {
show: true,
type: 'timeseries',
tick: {
format: '%Y-%m-%d',
culling: false
}
},
y: {
show: false
}
},
bindto: "#allCharts",
color: {
pattern: ['#0088ce', '#00659c', '#3f9c35', '#ec7a08', '#cc0000']
},
data: {
columns: data.columns,
groups: data.groups,
x: 'date',
type: 'bar'
},
bar: {
width: {
ratio: 0.9
}
},
legend: {
show: false
},
size: {
height: 120
}
});
},
fail: function() {
infoDiv.addClass("bg-danger");
infoDiv.html("<h2>Cannot load chart data</h2>");
}
});
});

64
cupola/templates/dashboard/index.html

@ -1,7 +1,7 @@
{% extends "layout/base.html" %}
{% block head_title %}
| Dashboard
| {{ gettext("Dashboard") }}
{% endblock %}
{% block normal_layout %}
@ -10,15 +10,15 @@
<div class="row">
<div class="col-md-12">
<div class="page-header page-header-bleed-right">
<h2>Dashboard</h2>
<h2>{{ gettext("Dashboard") }}</h2>
</div>
{% include "layout/messages.html" %}
<h4>Overview</h4>
<h4>{{ gettext("Overview") }}</h4>
<div class="row">
<div class="col-sm-12">
<div class="frequency" id="allCharts">
<div class="well-lg bg-info" id="chartInfo">
<h2>No data available</h2>
<h2>{{ gettext("No data available") }}</h2>
</div>
</div>
</div>
@ -31,59 +31,5 @@
{% block body_js %}
{% include "layout/_graph.html" %}
<script type="text/javascript">
$(document).ready(function() {
var infoDiv = $("#chartInfo");
$.ajax({
url: '/event/dashboard/',
dataType: 'json'
})
.success(function(data) {
if (data.groups.length === 1 && data.columns.length === 1) {
return;
}
c3.generate({
axis: {
x: {
show: true,
type: 'timeseries',
tick: {
format: '%Y-%m-%d',
culling: false
}
},
y: {
show: false
}
},
bindto: "#allCharts",
color: {
pattern: ['#0088ce', '#00659c', '#3f9c35', '#ec7a08', '#cc0000']
},
data: {
columns: data.columns,
groups: data.groups,
x: 'date',
type: 'bar'
},
bar: {
width: {
ratio: 0.9
}
},
legend: {
show: false
},
size: {
height: 120
}
});
})
.fail(function() {
infoDiv.addClass("bg-danger");
infoDiv.html("<h2>Cannot load chart data</h2>");
});
});
</script>
<script type="text/javascript" src="/static/js/dashboard.js"></script>
{% endblock %}

27
cupola/templates/events/index.html

@ -1,23 +1,24 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% block head_title %}
| Events
| {{ gettext("Events") }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li class="active">
Events
{{ gettext("Events") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Events
{{ gettext("Events") }}
</h1>
{% endblock %}
@ -28,17 +29,21 @@
<div class="row">
<div class="col-sm-1 col-sm-offset-1">
<h2>{{ group.event_count }}</h2>
event{{ "s" if group.event_count > 1 else "" }}
{% trans event_count=group.event_count %}
event
{% pluralize event_count %}
events
{% endtrans %}
</div>
<div class="col-sm-7">
<h3>
<a href="{{ url_for('events.view_group', event_group_id=group.id) }}">{{ group.message }}</a>
for <a href="{{ url_for('projects.view', project_id=group.project.id) }}">{{ group.project.name }}</a>
{{ gettext("for") }} <a href="{{ url_for('projects.view', project_id=group.project.id) }}">{{ group.project.name }}</a>
</h3>
<p>
{{ group.type }}
<span class="pull-right">
Last seen: {{ group.last_seen }}
{{ gettext("Last seen") }}: {{ render_datetime_tooltip(group.last_seen) }}
</span>
</p>
<div class="collapse" id="collapseGroup{{ group.id }}">
@ -46,14 +51,14 @@
{% for list_event in group.events | sort(attribute="timestamp", reverse=True) %}
<li>
<a href="{{ url_for('events.view_event', event_id=list_event.event_id) }}">
Event {{ list_event.event_id }}</a>
at {{ list_event.timestamp }}
{{ gettext("Event") }} {{ list_event.event_id }}</a>
{{ gettext("at") }} {{ render_datetime_tooltip(list_event.timestamp) }}
</li>
{%- if loop.index >= 5 %}{% break %}{% endif %}
{% endfor %}
</ul>
{% if group.event_count > 5 %}
<em>{{ group.event_count - 5 }} more events</em>
<em>{{ group.event_count - 5 }} {{ gettext("more events") }}</em>
{% endif %}
</div>
</div>
@ -65,7 +70,7 @@
</div>
</div>
{% else %}
No events.
{{ gettext("No events") }}.
{% endfor %}
</div>
</div>

9
cupola/templates/events/list.html

@ -1,4 +1,5 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% set event_count = event_list | count %}
{% block head_title %}
@ -24,7 +25,7 @@
<h1>
Events list for project {{ project.name }}
{% if event_list %}
<small>{{ event_list | count }} events registered since {{ event_list[-1].timestamp }}</small>
<small>{{ event_list | count }} events registered since {{ render_datetime_tooltip(event_list[-1].timestamp) }}</small>
{% else %}
<small>No events registered recently.</small>
{% endif %}
@ -43,8 +44,8 @@
<div class="col-sm-7">
<p>
<span class="pull-right">
First event: {{ event_list[-1].timestamp }} &mdash;
Last event: {{ event_list[0].timestamp }}
First event: {{ render_datetime_tooltip(event_list[-1].timestamp) }} &mdash;
Last event: {{ render_datetime_tooltip(event_list[0].timestamp) }}
</span>
</p>
</div>
@ -74,7 +75,7 @@
<td>
<a href="{{ url_for('events.view_group', event_group_id=event.group.id) }}">{{ event.group.message }}</a>
</td>
<td>{{ event.timestamp }}</td>
<td>{{ render_datetime_tooltip(event.timestamp) }}</td>
</tr>
{% endfor %}
</tbody>

7
cupola/templates/events/view.html

@ -1,5 +1,6 @@
{% extends "layout/layout.html" %}
{% from "events/macros.html" import show_stacktrace %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% block head_title %}
| Event {{ event.event_id }}
@ -51,12 +52,14 @@
{{ event.message }}
</h3>
<p>
Timestamp: {{ event.timestamp }}
Timestamp: {{ render_datetime_tooltip(event.timestamp) }}
</p>
</div>
{#
<div class="col-sm-1 col-sm-offset-2">
<div><i class="fa fa-check fa-2x"></i></div>
</div>
#}
</div>
</div>
</div>
@ -93,7 +96,7 @@
{% for tag, value in event.tags.items() %}
<span class="label label-default">{{ tag }}</span> {{ value }}<br/>
{% else %}
No tags.
No tags
{% endfor %}
</div>
</div>

48
cupola/templates/events/view_group.html

@ -1,29 +1,30 @@
{% extends "layout/layout.html" %}
{% from "events/macros.html" import show_stacktrace %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% set event = event_group.events[0] %}
{% block head_title %}
| Event group {{ event_group.id }}
| {{ gettext("Event group") }} {{ event_group.id }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('projects.view', project_id=event_group.project.id) }}">
Project {{ event_group.project.name }}</a>
{{ gettext("Project") }} {{ event_group.project.name }}</a>
</li>
<li class="active">
Event group {{ event_group.id }}
{{ gettext("Event group") }} {{ event_group.id }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Event group {{ event_group.id }}
{{ gettext("Event group") }} {{ event_group.id }}
<small>{{ event_group.message }}</small>
</h1>
{% endblock %}
@ -40,21 +41,27 @@
<div class="row">
<div class="col-sm-1 col-sm-offset-1">
<h2>{{ event_group.event_count }}</h2>
event{{ "s" if event_group.event_count > 1 else "" }}
{% trans event_count=event_group.event_count %}
event
{% pluralize event_count %}
events
{% endtrans %}
</div>
<div class="col-sm-7">
<h3>{{ event_group.message }}</h3>
<p>
{{ event_group.type }}
<span class="pull-right">
First seen: {{ event_group.first_seen }} &mdash;
Last seen: {{ event_group.last_seen }}
{{ gettext("First seen") }}: {{ render_datetime_tooltip(event_group.first_seen) }} &mdash;
{{ gettext("Last seen") }}: {{ render_datetime_tooltip(event_group.last_seen) }}
</span>
</p>
</div>
{#
<div class="col-sm-1 col-sm-offset-2">
<div><i class="fa fa-check fa-2x"></i></div>
</div>
#}
</div>
</div>
</div>
@ -62,7 +69,7 @@
<div class="col-sm-7 col-sm-offset-1">
<div>
{% if event.exceptions %}
<h3>Exception</h3>
<h3>{{ gettext("Exception") }}</h3>
{% for excp in event.exceptions %}
<div>
<p>
@ -73,31 +80,38 @@
</div>
{% endfor %}
{% elif event.stacktrace %}
<h3>Stacktrace</h3>
<h3>{{ gettext("Stacktrace") }}</h3>
{{ show_stacktrace(event.stacktrace) }}
{% elif event.template %}
<h3>Template fault</h3>
<h3>{{ gettext("Template fault") }}</h3>
{{ event.template }}
{% elif event.logevent %}
<h3>Log event</h3>
<h3>{{ gettext("Log event") }}</h3>
{{ event.logevent }}
{% else %}
<h3>No event data</h3>
<h3>{{ gettext("No event data") }}</h3>
{% endif %}
</div>
</div>
<div class="col-sm-4">
<h4>Tags</h4>
<h4>{{ gettext("Tags") }}</h4>
{% for tag, value in event.tags.items() %}
<span class="label label-default">{{ tag }}</span> {{ value }}<br/>
{% else %}
{{ gettext("No tags") }}
{% endfor %}
<h4>All events</h4>
<h4>{{ gettext("All events") }}</h4>
<ul>
{% for list_event in event_group.events %}
<li>
<a href="{{ url_for('events.view_event', event_id=list_event.event_id) }}">
Event {{ list_event.event_id }}</a>
at {{ list_event.timestamp }}
{{ gettext("Event") }} {{ list_event.event_id }}</a>
{{ gettext("at") }}
{{ render_datetime_tooltip(list_event.timestamp) }}
</li>
{% else %}
<li>
{{ gettext("No events") }}
</li>
{% endfor %}
</ul>

2
cupola/templates/layout/base.html

@ -5,7 +5,7 @@
<meta charset="UTF-8">
<title>
Cupola
{% block head_title %} | Welcome{% endblock %}
{% block head_title %} | {{ gettext("Welcome") }}{% endblock %}
</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>

32
cupola/templates/layout/header.html

@ -1,17 +1,19 @@
<nav class="navbar navbar-default navbar-pf" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-user">
<span class="sr-only">Toggle navigation</span>
<span class="sr-only">{{ gettext("Toggle navigation") }}</span>
<i class="fa fa-bars"></i>
</button>
<a class="navbar-brand" href="{{ url_for('dashboard.index') }}" style="line-height: 10px;">
<span style="font-weight: bold;">Cupola</span> Application Monitoring
<span style="font-weight: bold;">Cupola</span> {{ gettext("Application Monitoring") }}
</a>
</div>
<div class="collapse navbar-collapse navbar-collapse-user">
<ul class="nav navbar-nav navbar-utility">
{# <li>
<a href="#">Status</a>
<a href="#">
{{ gettext("Status") }}
</a>
</li>#}
<li class="dropdown">
{% if current_user.is_authenticated %}
@ -21,27 +23,39 @@
</a>
<ul class="dropdown-menu">
<li>
<a href="{{ url_for('users.profile', user_id=current_user.get_id()) }}">Profile</a>
<a href="{{ url_for('users.profile', user_id=current_user.get_id()) }}">
{{ gettext("Profile") }}
</a>
</li>
{# <li>
<a href="#">Messages</a>
<a href="#">
{{ gettext("Messages") }}
</a>
</li>#}
<li>
<a href="{{ url_for_security('logout') }}">Log out</a>
<a href="{{ url_for_security('logout') }}">
{{ gettext("Log out") }}
</a>
</li>
</ul>
{% else %}
<a href="{{ url_for_security('login') }}">Log in</a>
<a href="{{ url_for_security('login') }}">
{{ gettext("Log in") }}
</a>
{% endif %}
</li>
</ul>
<ul class="nav navbar-nav navbar-primary">
<li id="navbarProjects">
<a href="{{ url_for('projects.index') }}">Projects</a>
<a href="{{ url_for('projects.index') }}">
{{ gettext("Projects") }}
</a>
</li>
<li id="navbarEvents">
<a href="{{ url_for('events.index') }}">Events</a>
<a href="{{ url_for('events.index') }}">
{{ gettext("Events") }}
</a>
</li>
</ul>
</div>

4
cupola/templates/layout/layout.html

@ -9,8 +9,8 @@
{%- block breadcrumbs -%}{%- endblock -%}
{% block content_header %}
<h1>
Welcome to Cupola
<small>Viewport on your web application</small>
{{ gettext("Welcome to ") }} Cupola
<small>{{ gettext("Viewport on your web application") }}</small>
</h1>
{% endblock %}
</div>

7
cupola/templates/layout/macros.html

@ -245,3 +245,10 @@
</div>
<div class="clearfix"></div>
{% endmacro %}
{% macro render_datetime_tooltip(datetime) %}
<span data-toggle="tooltip" data-placement="top"
title="{{ datetime }}">
{{ datetime | datetimeformat(format="YYYY-MM-dd HH:mm:ssZ") }}
</span>
{% endmacro %}

10
cupola/templates/projects/edit.html

@ -4,20 +4,22 @@
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('projects.view', project_id=project.id) }}">Project {{ project.name }}</a>
<a href="{{ url_for('projects.view', project_id=project.id) }}">
{{ gettext("Project %(project_name)s", project_name=project.name) }}
</a>
</li>
<li class="active">
Edit project
{{ gettext("Edit project") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Project {{ project.name }} settings
{{ gettext("Project %(project_name)s settings", project_name=project.name) }}
</h1>
{% endblock %}

22
cupola/templates/projects/index.html

@ -1,7 +1,7 @@
{% extends "layout/layout.html" %}
{% block head_title %}
| Projects
| {{ gettext("Projects") }}
{% endblock %}
{% block breadcrumbs %}
@ -10,14 +10,14 @@
<a href="{{ url_for('dashboard.index') }}">Home</a>
</li>
<li class="active">
Projects
{{ gettext("Projects") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Projects
{{ gettext("Projects") }}
</h1>
{% endblock %}
@ -28,7 +28,8 @@
{% for project in projects %}
<div class="row">
<div class="col-sm-1 col-sm-offset-1">
{{ project.platform | default("Web application", True) }}
{# gettext returns a string of "None", and breaks '| default' #}
{{ gettext(project.platform if project.platform else "Web application") }}
</div>
<div class="col-sm-7">
<h2><a href="{{ url_for('projects.view', project_id=project.id) }}">{{ project.name }}</a></h2>
@ -38,7 +39,9 @@
{% endfor %}
</div>
<div class="col-sm-1 btn-group">
<a href="{{ url_for('projects.new') }}" class="btn btn-primary">Add new</a>
<a href="{{ url_for('projects.new') }}" class="btn btn-primary">
{{ gettext("Add new") }}
</a>
</div>
</div>
{% else %}
@ -46,12 +49,11 @@
<div class="blank-slate-pf-icon">
<i class="fa fa-rocket"></i>
</div>
<h1>Create a project</h1>
<p>Create a project for your application to start collecting errors.</p>
<h1>{{ gettext("Create a project") }}</h1>
<p>{{ gettext("Create a project for your application to start collecting errors") }}</p>
<div class="blank-slate-pf-main-action">
<a class="btn btn-primary btn-lg"
href="{{ url_for('projects.new') }}">
Create project
<a class="btn btn-primary btn-lg" href="{{ url_for('projects.new') }}">
{{ gettext("Create a project") }}
</a>
</div>
</div>

32
cupola/templates/projects/keys.html

@ -1,22 +1,29 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% block head_title %}
| {{ gettext("Project %(project_name)s client keys", project_name=project.name) }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('projects.view', project_id=project.id) }}">Project {{ project.name }}</a>
<a href="{{ url_for('projects.view', project_id=project.id) }}">
{{ gettext("Project %(project_name)s", project_name=project.name) }}
</a>
</li>
<li class="active">
Keys
{{ gettext("Keys") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Project {{ project.name }} client keys
{{ gettext("Project %(project_name)s client keys", project_name=project.name) }}
</h1>
{% endblock %}
@ -29,18 +36,25 @@
href="#key{{ key.id }}" aria-expanded="true" aria-controls="key{{ key.id }}">
{{ key.name }}
</a>
<p>Created on {{ key.created }}</p>
<p>
{{ gettext("Created on") }} {{ render_datetime_tooltip(key.created) }}
</p>
</div>
<div id="key{{ key.id }}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headerkey{{ key.id }}">
<div class="panel-body">
<div>Public: <code>{{ key.public.hex }}</code></div>
<div>Private: <code>{{ key.private.hex }}</code></div>
<div>Sentry DSN: <code>https://{{ key.public.hex }}:{{ key.private.hex }}@{{ request.host }}/api/sentry/{{ project.id }}</code></div>
<div>{{ gettext("Public") }}: <code>{{ key.public.hex }}</code></div>
<div>{{ gettext("Private") }}: <code>{{ key.private.hex }}</code></div>
<div>
{{ gettext("Sentry DSN") }}:
<code>
https://{{ key.public.hex }}:{{ key.private.hex }}@{{ request.host }}/api/sentry/{{ project.id }}
</code>
</div>
</div>
</div>
</div>
{% else %}
<div>No keys have been created.</div>
<div>{{ gettext("No keys have been created") }}</div>
{% endfor %}
</div>
{% endblock %}

12
cupola/templates/projects/new.html

@ -1,23 +1,27 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block head_title %}
| {{ gettext("New project") }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('projects.index') }}">Projects</a>
<a href="{{ url_for('projects.index') }}">{{ gettext("Projects") }}</a>
</li>
<li class="active">
Add new project
{{ gettext("Add new project") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
New project
{{ gettext("New project") }}
</h1>
{% endblock %}

14
cupola/templates/projects/notification.html

@ -2,23 +2,29 @@
{% from "layout/macros.html" import render_field %}
{% set project = member.project %}
{% block head_title %}
| {{ gettext("Project %(project_name)s notification settings", project_name=project.name) }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('projects.view', project_id=project.id) }}">Project {{ project.name }}</a>
<a href="{{ url_for('projects.view', project_id=project.id) }}">
{{ gettext("Project %(project_name)s", project_name=project.name) }}
</a>
</li>
<li class="active">
Notification settings
{{ gettext("Notification settings") }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Project {{ project.name }} notification settings
{{ gettext("Project %(project_name)s notification settings", project_name=project.name) }}
</h1>
{% endblock %}

47
cupola/templates/projects/view.html

@ -1,23 +1,24 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_datetime_tooltip %}
{% block head_title %}
| Project {{ project.name }}
| {{ gettext("Project %(project_name)s", project_name=project.name) }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li class="active">
Project {{ project.name }}
{{ gettext("Project %(project_name)s", project_name=project.name) }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>
Project {{ project.name }}
{{ gettext("Project %(project_name)s", project_name=project.name) }}
{% if project.description %}<small>{{ project.description }}</small>{% endif %}
</h1>
{% endblock %}
@ -25,11 +26,11 @@
{% block content %}
<div class="row">
<div class="col-sm-10">
<h2>Events</h2>
<h2>{{ gettext("Events") }}</h2>
<div class="row">
<div class="col-sm-12">
<div class="frequency" id="allEventsTimeline" data-project-id="{{ project.id }}">
<h2 class='bg-info'>No data available</h2>
<h2 class='bg-info'>{{ gettext("No data available") }}</h2>
</div>
</div>
</div>
@ -38,36 +39,54 @@
<div class="row">
<div class="col-sm-1 col-sm-offset-1">
<h2>{{ group.event_count }}</h2>
event{{ "s" if group.event_count > 1 else "" }}
{% trans event_count=group.event_count %}
event
{% pluralize event_count %}
events
{% endtrans %}
</div>
<div class="col-sm-6">
<h3><a href="{{ url_for('events.view_group', event_group_id=group.id) }}">{{ group.message }}</a></h3>
<p>
{{ group.type }}
<span class="pull-right">
First seen: {{ group.first_seen }} &mdash;
Last seen: {{ group.last_seen }}
{{ gettext("First seen") }}: {{ render_datetime_tooltip(group.first_seen) }}&mdash;
{{ gettext("Last seen") }}: {{ render_datetime_tooltip(group.last_seen) }}
</span>
</p>
</div>
<div class="col-sm-3">
</div>
{#
<div class="col-sm-1">
<div><i class="fa fa-check fa-2x"></i></div>
</div>
#}
</div>
{% else %}
<div>
<h3 class='bg-info'>No events have been seen.</h3>
<h3 class='bg-info'>{{ gettext("No events have been seen") }}</h3>
</div>
{% endfor %}
</div>
<div class="col-sm-2">
<h4>Information</h4>
<h4>{{ gettext("Information") }}</h4>
<ul>
<li><a href="{{ url_for('projects.edit', project_id=project.id) }}">Settings</a></li>
<li><a href="{{ url_for('projects.client_keys', project_id=project.id) }}">Client keys</a></li>
<li><a href="{{ url_for('projects.notifications', project_id=project.id) }}">User notifications</a></li>
<li>
<a href="{{ url_for('projects.edit', project_id=project.id) }}">
{{ gettext("Settings") }}
</a>
</li>
<li>
<a href="{{ url_for('projects.client_keys', project_id=project.id) }}">
{{ gettext("Client keys") }}
</a>
</li>
<li>
<a href="{{ url_for('projects.notifications', project_id=project.id) }}">
{{ gettext("User notifications") }}
</a>
</li>
</ul>
</div>
</div>

32
cupola/templates/security/_sidebar_menu.html

@ -2,17 +2,37 @@
<aside class="main-sidebar">
<section class="sidebar">
<ul class="sidebar-menu">
<li><a href="{{ url_for('index') }}">About</a></li>
<li class="header">ACCOUNT</li>
<li><a href="{{ url_for_security('login') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Login</a></li>
<li>
<a href="{{ url_for('index') }}">
{{ gettext("About") }}
</a>
</li>
<li class="header">{{ gettext("Account") }}</li>
<li>
<a href="{{ url_for_security('login') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">
{{ gettext("Login") }}
</a>
</li>
{% if security.registerable %}
<li><a href="{{ url_for_security('register') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Register</a></li>
<li>
<a href="{{ url_for_security('register') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">
{{ gettext("Register") }}
</a>
</li>
{% endif %}
{% if security.recoverable %}
<li><a href="{{ url_for_security('forgot_password') }}">Forgot password</a></li>
<li>
<a href="{{ url_for_security('forgot_password') }}">
{{ gettext("Forgot password") }}
</a>
</li>
{% endif %}
{% if security.confirmable %}
<li><a href="{{ url_for_security('send_confirmation') }}">Confirm account</a></li>
<li>
<a href="{{ url_for_security('send_confirmation') }}">
{{ gettext("Confirm account") }}
</a>
</li>
{% endif %}
</ul>
</section>

4
cupola/templates/security/change_password.html

@ -1,9 +1,9 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Change password</h2>
<h2>{{ gettext("Change password") }}</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('change_password') }}" method="POST" name="change_password_form">
{{ change_password_form.hidden_tag() }}
{{ render_field(change_password_form.password) }}

8
cupola/templates/security/email/change_notice.html

@ -1,4 +1,8 @@
<p>Your password has been changed.</p>
<p>{{ gettext("Your password has been changed") }}.</p>
{% if security.recoverable %}
<p>If you did not change your password, <a href="{{ url_for_security('forgot_password', _external=True) }}">click here to reset it</a>.</p>
<p>{{ gettext("If you did not change your password") }},
<a href="{{ url_for_security('forgot_password', _external=True) }}">
{{ gettext("click here to reset it") }}
</a>.
</p>
{% endif %}

4
cupola/templates/security/email/change_notice.txt

@ -1,5 +1,5 @@
Your password has been changed
{{ gettext("Your password has been changed") }}.
{% if security.recoverable %}
If you did not change your password, click the link below to reset it.
{{ gettext("If you did not change your password") }}, {{ gettext("click the link below to reset it") }}.
{{ url_for_security('forgot_password', _external=True) }}
{% endif %}

8
cupola/templates/security/email/confirmation_instructions.html

@ -1,3 +1,7 @@
<p>Please confirm your email through the link below:</p>
<p>{{ gettext("Please confirm your email through the link below") }}:</p>
<p><a href="{{ confirmation_link }}">Confirm my account</a></p>
<p>
<a href="{{ confirmation_link }}">
{{ gettext("Confirm my account") }}
</a>.
</p>

4
cupola/templates/security/email/confirmation_instructions.txt

@ -1,3 +1,3 @@
Please confirm your email through the link below:
{{ gettext("Please confirm your email through the link below") }}:
{{ confirmation_link }}
{{ confirmation_link }}

8
cupola/templates/security/email/login_instructions.html

@ -1,5 +1,7 @@
<p>Welcome {{ user.email }}!</p>
<p>{{ gettext("Welcome") }} {{ user.fullname or user.email }}!</p>
<p>You can log into your through the link below:</p>
<p>
{{ gettext("You can log into your account through the link below") }}:
</p>
<p><a href="{{ login_link }}">Login now</a></p>
<p><a href="{{ login_link }}">{{ gettext("Log in now") }}</a></p>

6
cupola/templates/security/email/login_instructions.txt

@ -1,5 +1,5 @@
Welcome {{ user.email }}!
{{ gettext("Welcome") }} {{ user.fullname or user.email }}!
You can log into your through the link below:
{{ gettext("You can log into your account through the link below") }}:
{{ login_link }}
{{ login_link }}

6
cupola/templates/security/email/reset_instructions.html

@ -1 +1,5 @@
<p><a href="{{ reset_link }}">Click here to reset your password</a></p>
<p>
<a href="{{ reset_link }}">
{{ gettext("Click here to reset your password") }}
</a>.
</p>

4
cupola/templates/security/email/reset_instructions.txt

@ -1,3 +1,3 @@
Click the link below to reset your password:
{{ gettext("Click the link below to reset your password") }}:
{{ reset_link }}
{{ reset_link }}

2
cupola/templates/security/email/reset_notice.html

@ -1 +1 @@
<p>Your password has been reset</p>
<p>{{ gettext("Your password has been reset") }}.</p>

2
cupola/templates/security/email/reset_notice.txt

@ -1 +1 @@
Your password has been reset
{{ gettext("Your password has been reset") }}.

8
cupola/templates/security/email/welcome.html

@ -1,7 +1,7 @@
<p>Welcome {{ user.email }}!</p>
<p>{{ gettext("Welcome") }} {{ user.fullname or user.email }}!</p>
{% if security.confirmable %}
<p>You can confirm your email through the link below:</p>
<p>{{ gettext("You can confirm your email through the link below") }}:</p>
<p><a href="{{ confirmation_link }}">Confirm my account</a></p>
{% endif %}
<p><a href="{{ confirmation_link }}">{{ gettext("Confirm my account") }}</a>.</p>
{% endif %}

6
cupola/templates/security/email/welcome.txt

@ -1,7 +1,7 @@
Welcome {{ user.email }}!
{{ gettext("Welcome") }} {{ user.fullname or user.email }}!
{% if security.confirmable %}
You can confirm your email through the link below:
{{ gettext("You can confirm your email through the link below") }}:
{{ confirmation_link }}
{% endif %}
{% endif %}

7
cupola/templates/security/forgot_password.html

@ -1,10 +1,11 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Send password reset instructions</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('forgot_password') }}" method="POST" name="forgot_password_form">
<h2>{{ gettext("Send password reset instructions") }}</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('forgot_password') }}"
method="POST" name="forgot_password_form">
{{ forgot_password_form.hidden_tag() }}
{{ render_field(forgot_password_form.email) }}
{{ render_field(forgot_password_form.submit, False, "primary") }}

44
cupola/templates/security/login_user.html

@ -13,7 +13,7 @@
<div class="row">
<div class="col-sm-12">
<div id="brand">
<h1>Cupola <small>Application Monitoring</small></h1>
<h1>Cupola <small>{{ gettext("Application Monitoring") }}</small></h1>
</div>
</div>
{% if login_user_form.errors %}
@ -21,13 +21,15 @@
{% if "Email requires confirmation." in login_user_form.errors.get("email", "") %}
<div class="alert alert-warning">
<span class="pficon pficon-warning-triangle-o"></span>
{% trans confirm_email=url_for_security("send_confirmation") %}
Your email address requires confirmation.
Please <a href="{{ url_for_security('send_confirmation') }}">confirm your email</a>.
Please <a href="{{ confirm_email }}">confirm your email</a>.
{% endtrans %}
</div>
{% elif "email" in login_user_form.errors or "password" in login_user_form.errors %}
<div class="alert alert-danger">
<span class="pficon pficon-error-circle-o"></span>
Your email or password is incorrect.
{{ gettext("Your email or password is incorrect") }}.
</div>
{% endif %}
</div>
@ -38,32 +40,38 @@
name="login_user_form">
{{ login_user_form.hidden_tag() }}
<div class="form-group">
<label for="inputUsername" class="col-sm-2 col-md-2 control-label">Email</label>
<label for="inputUsername" class="col-sm-2 col-md-2 control-label">
{{ gettext("Email") }}
</label>
<div class="col-sm-10 col-md-10">
{{ login_user_form.email(class="form-control", tabindex="2") | safe }}
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-sm-2 col-md-2 control-label">Password</label>
<label for="inputPassword" class="col-sm-2 col-md-2 control-label">
{{ gettext("Password") }}
</label>
<div class="col-sm-10 col-md-10">
{{ login_user_form.password(class="form-control", tabindex="2") | safe }}
</div>
</div>
<div class="form-group">
<div
class="col-xs-8 col-sm-offset-2 col-sm-6 col-md-offset-2 col-md-6">
<span class="help-block">
<a href="{{ url_for_security('send_confirmation') }}"
tabindex="5">Confirm email</a> &mdash;
<a href="{{ url_for_security('forgot_password') }}"
tabindex="6">Forgot password</a>
</span>
<div class="col-xs-8 col-sm-offset-2 col-sm-6 col-md-offset-2 col-md-6">
<span class="help-block">
{% trans send_confirm=url_for_security('send_confirmation'),
forgot_pass=url_for_security('forgot_password') %}
<a href="{{ send_confirm }}" tabindex="5">
Confirm email
</a> &mdash;
<a href="{{ forgot_pass }}" tabindex="6">
Forgot password
</a>
{% endtrans %}
</span>
</div>
<div class="col-xs-4 col-sm-4 col-md-4 submit">
<button type="submit" class="btn btn-primary btn-lg"
tabindex="4">Log In
<button type="submit" class="btn btn-primary btn-lg" tabindex="4">
{{ gettext("Log in") }}
</button>
</div>
</div>
@ -71,7 +79,7 @@
</div>
<div class="col-sm-5 col-md-6 col-lg-7 details">
<p>
<strong>Cupola</strong> 0.2.0
<strong>Cupola</strong> 0.3.0
</p>
</div>
</div>

4
cupola/templates/security/register_user.html

@ -1,9 +1,9 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Register</h2>
<h2>{{ gettext("Register") }}</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('register') }}" method="POST" name="register_user_form">
{{ register_user_form.hidden_tag() }}
{{ render_field(register_user_form.email) }}

4
cupola/templates/security/reset_password.html

@ -1,9 +1,9 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Reset password</h2>
<h2>{{ gettext("Reset password") }}</h2>
<form class="form-horizontal" role="form"
action="{{ url_for_security('reset_password', token=reset_password_token) }}"
method="POST" name="reset_password_form">

4
cupola/templates/security/send_confirmation.html

@ -1,9 +1,9 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Resend confirmation instructions</h2>
<h2>{{ gettext("Resend confirmation instructions") }}</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('send_confirmation') }}" method="POST" name="send_confirmation_form">
{{ send_confirmation_form.hidden_tag() }}
{{ render_field(send_confirmation_form.email) }}

4
cupola/templates/security/send_login.html

@ -1,9 +1,9 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content %}
<div class="row col-lg-offset-2 col-lg-8">
<h2>Login</h2>
<h2>{{ gettext("Login") }}</h2>
<form class="form-horizontal" role="form" action="{{ url_for_security('login') }}" method="POST" name="send_login_form">
{{ send_login_form.hidden_tag() }}
{{ render_field(send_login_form.email) }}

25
cupola/templates/users/edit.html

@ -1,17 +1,26 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block content_header %}
<h1>Edit user {{ user.fullname or user.email }}</h1>
{% block head_title %}
| {{ gettext("Edit user %(user)s", user=user.fullname or user.email) }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
</li>
<li><a href="{{ url_for('users.profile', user_id=user.id) }}">User {{ user.username }}</a></li>
<li class="active">Edit</li>
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li>
<a href="{{ url_for('users.profile', user_id=user.id) }}">
{{ gettext("User %(user)s", user=user.fullname or user.email) }}
</a>
</li>
<li class="active">Edit</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>{{ gettext("Edit user %(user)s", user=user.fullname or user.email) }}</h1>
{% endblock %}
{% block content %}

14
cupola/templates/users/index.html

@ -1,11 +1,15 @@
{% extends "layout/layout.html" %}
{% block head_title %}
| {{ gettext("User list") }}
{% endblock %}
{% block content_header %}
<h1>User list</h1>
<h1>{{ gettext("User list") }}</h1>
{% endblock %}
{% block content_breadcrumb %}
<li class="active">Users</li>
<li class="active">{{ gettext("Users") }}</li>
{% endblock %}
{% block content %}
@ -13,8 +17,8 @@
<div class="table-responsive">
<table class="table table-hover">
<tr>
<th>Name</th>
<th>Roles</th>
<th>{{ gettext("Name") }}</th>
<th>{{ gettext("Roles") }}</th>
</tr>
{% for user in users %}
<tr>
@ -30,7 +34,7 @@
<button class="btn btn-primary" type="button"
data-toggle="collapse" data-target="#collapseNewUser"
aria-expanded="false" aria-controls="collapseNewUser">
Add new user
{{ gettext("Add new user") }}
</button>
<div class="collapse" id="collapseNewUser">
<h3>Create new user</h3>

10
cupola/templates/users/new.html

@ -1,16 +1,20 @@
{% extends "layout/layout.html" %}
{% block head_title %}
| {{ gettext("Create new user") }}
{% endblock %}
{% block content_header %}
<h1>Create new user</h1>
<h1>{{ gettext("Create new user") }}</h1>
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li class="active">
New user
{{ gettext("New user") }}
</li>
</ol>
{% endblock %}

28
cupola/templates/users/profile.html

@ -1,19 +1,23 @@
{% extends "layout/layout.html" %}
{% from "layout/macros.html" import render_field %}
{% block head_title %}
| {{ gettext("Profile for %(user)s", user=user.fullname or user.email) }}
{% endblock %}
{% block breadcrumbs %}
<ol class="breadcrumb">
<li>
<a href="{{ url_for('dashboard.index') }}">Home</a>
<a href="{{ url_for('dashboard.index') }}">{{ gettext("Home") }}</a>
</li>
<li class="active">
{{ user.username }} Profile
{{ gettext("%(user)s profile", user=user.fullname or user.email) }}
</li>
</ol>
{% endblock %}
{% block content_header %}
<h1>Profile for {{ user.username }}</h1>
<h1>{{ gettext("Profile for %(user)s", user=user.fullname or user.email) }}</h1>
{% endblock %}
{% block content %}
@ -24,32 +28,38 @@
{% if current_user.id == user.id %}
{{ form.hidden_tag() }}
<div class="col-lg-12">