Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
c10c1a49
authored
9 years ago
by
Bach Dániel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard: add broadcast message support
parent
ff91b0ff
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
291 additions
and
3 deletions
+291
-3
circle/circle/settings/base.py
+1
-0
circle/dashboard/admin.py
+3
-1
circle/dashboard/context_processors.py
+11
-0
circle/dashboard/forms.py
+13
-1
circle/dashboard/migrations/0003_message.py
+33
-0
circle/dashboard/models.py
+25
-0
circle/dashboard/static/dashboard/dashboard.js
+19
-0
circle/dashboard/static/dashboard/dashboard.less
+6
-0
circle/dashboard/tables.py
+16
-1
circle/dashboard/templates/base.html
+17
-0
circle/dashboard/templates/dashboard/base.html
+6
-0
circle/dashboard/templates/dashboard/message-create.html
+27
-0
circle/dashboard/templates/dashboard/message-edit.html
+34
-0
circle/dashboard/templates/dashboard/message-list.html
+28
-0
circle/dashboard/urls.py
+10
-0
circle/dashboard/views/__init__.py
+1
-0
circle/dashboard/views/message.py
+41
-0
No files found.
circle/circle/settings/base.py
View file @
c10c1a49
...
@@ -282,6 +282,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
...
@@ -282,6 +282,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request'
,
'django.core.context_processors.request'
,
'dashboard.context_processors.notifications'
,
'dashboard.context_processors.notifications'
,
'dashboard.context_processors.extract_settings'
,
'dashboard.context_processors.extract_settings'
,
'dashboard.context_processors.broadcast_messages'
,
)
)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/admin.py
View file @
c10c1a49
...
@@ -21,7 +21,7 @@ from django import contrib
...
@@ -21,7 +21,7 @@ from django import contrib
from
django.contrib.auth.admin
import
UserAdmin
,
GroupAdmin
from
django.contrib.auth.admin
import
UserAdmin
,
GroupAdmin
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
dashboard.models
import
Profile
,
GroupProfile
,
ConnectCommand
from
dashboard.models
import
Profile
,
GroupProfile
,
ConnectCommand
,
Message
class
ProfileInline
(
contrib
.
admin
.
TabularInline
):
class
ProfileInline
(
contrib
.
admin
.
TabularInline
):
...
@@ -43,3 +43,5 @@ contrib.admin.site.unregister(User)
...
@@ -43,3 +43,5 @@ contrib.admin.site.unregister(User)
contrib
.
admin
.
site
.
register
(
User
,
UserAdmin
)
contrib
.
admin
.
site
.
register
(
User
,
UserAdmin
)
contrib
.
admin
.
site
.
unregister
(
Group
)
contrib
.
admin
.
site
.
unregister
(
Group
)
contrib
.
admin
.
site
.
register
(
Group
,
GroupAdmin
)
contrib
.
admin
.
site
.
register
(
Group
,
GroupAdmin
)
contrib
.
admin
.
site
.
register
(
Message
)
This diff is collapsed.
Click to expand it.
circle/dashboard/context_processors.py
View file @
c10c1a49
...
@@ -16,6 +16,10 @@
...
@@ -16,6 +16,10 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from
django.conf
import
settings
from
django.conf
import
settings
from
django.db.models
import
Q
from
django.utils
import
timezone
from
.models
import
Message
def
notifications
(
request
):
def
notifications
(
request
):
...
@@ -31,3 +35,10 @@ def extract_settings(request):
...
@@ -31,3 +35,10 @@ def extract_settings(request):
'COMPANY_NAME'
:
getattr
(
settings
,
"COMPANY_NAME"
,
None
),
'COMPANY_NAME'
:
getattr
(
settings
,
"COMPANY_NAME"
,
None
),
'ADMIN_ENABLED'
:
getattr
(
settings
,
"ADMIN_ENABLED"
,
False
),
'ADMIN_ENABLED'
:
getattr
(
settings
,
"ADMIN_ENABLED"
,
False
),
}
}
def
broadcast_messages
(
request
):
now
=
timezone
.
now
()
messages
=
Message
.
objects
.
filter
(
enabled
=
True
)
.
exclude
(
Q
(
starts_at__gt
=
now
)
|
Q
(
ends_at__lt
=
now
))
return
{
'broadcast_messages'
:
messages
}
This diff is collapsed.
Click to expand it.
circle/dashboard/forms.py
View file @
c10c1a49
...
@@ -57,7 +57,7 @@ from vm.models import (
...
@@ -57,7 +57,7 @@ from vm.models import (
from
storage.models
import
DataStore
,
Disk
from
storage.models
import
DataStore
,
Disk
from
django.contrib.admin.widgets
import
FilteredSelectMultiple
from
django.contrib.admin.widgets
import
FilteredSelectMultiple
from
django.contrib.auth.models
import
Permission
from
django.contrib.auth.models
import
Permission
from
.models
import
Profile
,
GroupProfile
from
.models
import
Profile
,
GroupProfile
,
Message
from
circle.settings.base
import
LANGUAGES
,
MAX_NODE_RAM
from
circle.settings.base
import
LANGUAGES
,
MAX_NODE_RAM
from
django.utils.translation
import
string_concat
from
django.utils.translation
import
string_concat
...
@@ -1624,3 +1624,15 @@ class DiskForm(ModelForm):
...
@@ -1624,3 +1624,15 @@ class DiskForm(ModelForm):
model
=
Disk
model
=
Disk
fields
=
(
"name"
,
"filename"
,
"datastore"
,
"type"
,
"bus"
,
"size"
,
fields
=
(
"name"
,
"filename"
,
"datastore"
,
"type"
,
"bus"
,
"size"
,
"base"
,
"dev_num"
,
"destroyed"
,
"is_ready"
,
)
"base"
,
"dev_num"
,
"destroyed"
,
"is_ready"
,
)
class
MessageForm
(
ModelForm
):
class
Meta
:
model
=
Message
fields
=
(
"message"
,
"enabled"
,
"effect"
,
"starts_at"
,
"ends_at"
)
@property
def
helper
(
self
):
helper
=
FormHelper
()
helper
.
add_input
(
Submit
(
"submit"
,
_
(
"Save"
)))
return
helper
This diff is collapsed.
Click to expand it.
circle/dashboard/migrations/0003_message.py
0 → 100644
View file @
c10c1a49
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
models
,
migrations
import
django.utils.timezone
import
model_utils.fields
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'dashboard'
,
'0002_auto_20150318_1317'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Message'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'created'
,
model_utils
.
fields
.
AutoCreatedField
(
default
=
django
.
utils
.
timezone
.
now
,
verbose_name
=
'created'
,
editable
=
False
)),
(
'modified'
,
model_utils
.
fields
.
AutoLastModifiedField
(
default
=
django
.
utils
.
timezone
.
now
,
verbose_name
=
'modified'
,
editable
=
False
)),
(
'message'
,
models
.
CharField
(
max_length
=
500
,
verbose_name
=
'message'
)),
(
'starts_at'
,
models
.
DateTimeField
(
null
=
True
,
verbose_name
=
'starts at'
,
blank
=
True
)),
(
'ends_at'
,
models
.
DateTimeField
(
null
=
True
,
verbose_name
=
'ends at'
,
blank
=
True
)),
(
'effect'
,
models
.
CharField
(
default
=
b
'info'
,
max_length
=
10
,
verbose_name
=
'effect'
,
choices
=
[(
b
'success'
,
'success'
),
(
b
'info'
,
'info'
),
(
b
'warning'
,
'warning'
),
(
b
'danger'
,
'danger'
)])),
(
'enabled'
,
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'enabled'
)),
],
options
=
{
'ordering'
:
[
'-ends_at'
],
},
bases
=
(
models
.
Model
,),
),
]
This diff is collapsed.
Click to expand it.
circle/dashboard/models.py
View file @
c10c1a49
...
@@ -59,6 +59,31 @@ def pwgen():
...
@@ -59,6 +59,31 @@ def pwgen():
return
User
.
objects
.
make_random_password
()
return
User
.
objects
.
make_random_password
()
class
Message
(
TimeStampedModel
):
message
=
CharField
(
max_length
=
500
,
verbose_name
=
_
(
'message'
))
starts_at
=
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'starts at'
))
ends_at
=
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'ends at'
))
effect
=
CharField
(
default
=
'info'
,
max_length
=
10
,
verbose_name
=
_
(
'effect'
),
choices
=
((
'success'
,
_
(
'success'
)),
(
'info'
,
_
(
'info'
)),
(
'warning'
,
_
(
'warning'
)),
(
'danger'
,
_
(
'danger'
))))
enabled
=
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'enabled'
))
class
Meta
:
ordering
=
[
"id"
]
verbose_name
=
_
(
'message'
)
verbose_name_plural
=
_
(
'messages'
)
def
__unicode__
(
self
):
return
self
.
message
@permalink
def
get_absolute_url
(
self
):
return
(
'dashboard.views.message-detail'
,
None
,
{
'pk'
:
self
.
pk
})
class
Favourite
(
Model
):
class
Favourite
(
Model
):
instance
=
ForeignKey
(
"vm.Instance"
)
instance
=
ForeignKey
(
"vm.Instance"
)
user
=
ForeignKey
(
User
)
user
=
ForeignKey
(
User
)
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/dashboard.js
View file @
c10c1a49
...
@@ -527,3 +527,22 @@ function replaceTag(tag) {
...
@@ -527,3 +527,22 @@ function replaceTag(tag) {
function
safe_tags_replace
(
str
)
{
function
safe_tags_replace
(
str
)
{
return
str
.
replace
(
/
[
&<>
]
/g
,
replaceTag
);
return
str
.
replace
(
/
[
&<>
]
/g
,
replaceTag
);
}
}
$
(
function
()
{
var
closed
=
JSON
.
parse
(
getCookie
(
'broadcast-messages'
));
$
(
'.broadcast-message'
).
each
(
function
()
{
var
id
=
$
(
this
).
data
(
'id'
);
if
(
closed
&&
closed
.
indexOf
(
id
)
!=
-
1
)
{
$
(
this
).
remove
()
}
});
$
(
'.broadcast-message'
).
on
(
'closed.bs.alert'
,
function
()
{
var
closed
=
JSON
.
parse
(
getCookie
(
'broadcast-messages'
));
if
(
!
closed
)
{
closed
=
[];
}
closed
.
push
(
$
(
this
).
data
(
'id'
));
setCookie
(
'broadcast-messages'
,
JSON
.
stringify
(
closed
),
7
*
24
*
60
*
60
*
1000
,
"/"
);
});
});
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/dashboard.less
View file @
c10c1a49
...
@@ -1315,3 +1315,9 @@ textarea[name="new_members"] {
...
@@ -1315,3 +1315,9 @@ textarea[name="new_members"] {
.little-margin-bottom {
.little-margin-bottom {
margin-bottom: 5px;
margin-bottom: 5px;
}
}
.broadcast-message {
margin-bottom: 5px;
padding-top: 5px;
padding-bottom: 5px;
}
This diff is collapsed.
Click to expand it.
circle/dashboard/tables.py
View file @
c10c1a49
...
@@ -29,7 +29,7 @@ from django_sshkey.models import UserKey
...
@@ -29,7 +29,7 @@ from django_sshkey.models import UserKey
from
storage.models
import
Disk
from
storage.models
import
Disk
from
vm.models
import
Node
,
InstanceTemplate
,
Lease
from
vm.models
import
Node
,
InstanceTemplate
,
Lease
from
dashboard.models
import
ConnectCommand
from
dashboard.models
import
ConnectCommand
,
Message
class
FileSizeColumn
(
Column
):
class
FileSizeColumn
(
Column
):
...
@@ -354,3 +354,18 @@ class DiskListTable(Table):
...
@@ -354,3 +354,18 @@ class DiskListTable(Table):
order_by
=
(
"-pk"
,
)
order_by
=
(
"-pk"
,
)
per_page
=
15
per_page
=
15
empty_text
=
_
(
"No disk found."
)
empty_text
=
_
(
"No disk found."
)
class
MessageListTable
(
Table
):
message
=
LinkColumn
(
'dashboard.views.message-detail'
,
args
=
[
A
(
'pk'
)],
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
class
Meta
:
model
=
Message
attrs
=
{
'class'
:
"table table-bordered table-striped table-hover"
,
'id'
:
"disk-list-table"
}
order_by
=
(
"-pk"
,
)
fields
=
(
'pk'
,
'message'
,
'enabled'
,
'effect'
)
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/base.html
View file @
c10c1a49
{% load i18n %}
{% load i18n %}
{% load staticfiles %}
{% load staticfiles %}
{% load cache %}
{% load compressed %}
{% load compressed %}
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"{{lang}}"
>
<html
lang=
"{{lang}}"
>
...
@@ -40,6 +41,22 @@
...
@@ -40,6 +41,22 @@
</div>
<!-- navbar navbar-inverse navbar-fixed-top -->
</div>
<!-- navbar navbar-inverse navbar-fixed-top -->
<div
class=
"container"
>
<div
class=
"container"
>
{% block broadcast_messages %}
{% cache 1 broadcast_messages %}
<div
id=
"broadcast-messages"
>
{% for message in broadcast_messages %}
<div
data-id=
{{
message
.
id
}}
class=
"alert alert-{{ message.effect }}
text-center broadcast-message"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"alert"
aria-label=
"Close"
>
<span
aria-hidden=
"true"
>
×
</span>
</button>
{{ message.message|safe }}
</div>
{% endfor %}
</div>
{% endcache %}
{% endblock broadcast_messages %}
{% block messages %}
{% block messages %}
<div
class=
"messagelist"
>
<div
class=
"messagelist"
>
{% if messages %}
{% if messages %}
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/dashboard/base.html
View file @
c10c1a49
...
@@ -27,6 +27,12 @@
...
@@ -27,6 +27,12 @@
<span
class=
"hidden-sm"
>
{% trans "Admin" %}
</span>
<span
class=
"hidden-sm"
>
{% trans "Admin" %}
</span>
</a>
</a>
</li>
</li>
<li>
<a
href=
"{% url "
dashboard
.
views
.
message-list
"
%}"
>
<i
class=
"fa fa-bullhorn"
></i>
<span
class=
"hidden-sm"
>
{% trans "Messages" %}
</span>
</a>
</li>
{% endif %}
{% endif %}
<li>
<li>
<a
href=
"{% url "
dashboard
.
views
.
storage
"
%}"
>
<a
href=
"{% url "
dashboard
.
views
.
storage
"
%}"
>
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/dashboard/message-create.html
0 → 100644
View file @
c10c1a49
{% extends "dashboard/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block title-page %}{% trans "Broadcast Messages" %}{% endblock %}
{% block content %}
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<a
href=
"{% url "
dashboard
.
views
.
message-list
"
%}"
class=
"btn btn-default btn-xs pull-right"
>
{% trans "Back" %}
</a>
<h3
class=
"no-margin"
>
<i
class=
"fa fa-bullhorn"
></i>
{% trans "New message" %}
</h3>
</div>
<div
class=
"panel-body"
>
{% crispy form %}
</div>
<!-- .panel-body -->
</div>
</div>
</div>
{% endblock %}
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/dashboard/message-edit.html
0 → 100644
View file @
c10c1a49
{% extends "dashboard/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block title-page %}{% trans "Broadcast Messages" %}{% endblock %}
{% block content %}
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<div
class=
"pull-right"
>
<a
href=
"{% url "
dashboard
.
views
.
message-list
"
%}"
class=
"btn btn-default btn-xs"
>
{% trans "Back" %}
</a>
<a
href=
"{% url "
dashboard
.
views
.
message-delete
"
pk=
object.pk
%}"
class=
"btn btn-danger btn-xs"
>
{% trans "Delete" %}
</a>
</div>
<h3
class=
"no-margin"
>
<i
class=
"fa fa-bullhorn"
></i>
{% trans "Edit message" %}
</h3>
</div>
<div
class=
"panel-body"
>
{% crispy form %}
</div>
<!-- .panel-body -->
</div>
</div>
</div>
{% endblock %}
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/dashboard/message-list.html
0 → 100644
View file @
c10c1a49
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block title-page %}{% trans "Broadcast Messages" %}{% endblock %}
{% block content %}
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<a
href=
"{% url "
dashboard
.
views
.
message-create
"
%}"
class=
"pull-right btn btn-success btn-xs"
>
<i
class=
"fa fa-plus"
></i>
{% trans "new message" %}
</a>
<h3
class=
"no-margin"
><i
class=
"fa fa-bullhorn"
></i>
{% trans "Broadcast Messages" %}
</h3>
</div>
<div
class=
"panel-body"
>
<div
class=
"table-responsive"
>
{% render_table table %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
This diff is collapsed.
Click to expand it.
circle/dashboard/urls.py
View file @
c10c1a49
...
@@ -54,6 +54,7 @@ from .views import (
...
@@ -54,6 +54,7 @@ from .views import (
NodeActivityView
,
NodeActivityView
,
UserList
,
UserList
,
StorageDetail
,
DiskDetail
,
StorageDetail
,
DiskDetail
,
MessageList
,
MessageDetail
,
MessageCreate
,
MessageDelete
,
)
)
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.node
import
node_ops
from
.views.node
import
node_ops
...
@@ -232,6 +233,15 @@ urlpatterns = patterns(
...
@@ -232,6 +233,15 @@ urlpatterns = patterns(
name
=
"dashboard.views.storage"
),
name
=
"dashboard.views.storage"
),
url
(
r'^disk/(?P<pk>\d+)/$'
,
DiskDetail
.
as_view
(),
url
(
r'^disk/(?P<pk>\d+)/$'
,
DiskDetail
.
as_view
(),
name
=
"dashboard.views.disk-detail"
),
name
=
"dashboard.views.disk-detail"
),
url
(
r'^message/list/$'
,
MessageList
.
as_view
(),
name
=
"dashboard.views.message-list"
),
url
(
r'^message/(?P<pk>\d+)/$'
,
MessageDetail
.
as_view
(),
name
=
"dashboard.views.message-detail"
),
url
(
r'^message/create/$'
,
MessageCreate
.
as_view
(),
name
=
"dashboard.views.message-create"
),
url
(
r'^message/delete/(?P<pk>\d+)/$'
,
MessageDelete
.
as_view
(),
name
=
"dashboard.views.message-delete"
),
)
)
urlpatterns
+=
patterns
(
urlpatterns
+=
patterns
(
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/views/__init__.py
View file @
c10c1a49
...
@@ -14,3 +14,4 @@ from vm import *
...
@@ -14,3 +14,4 @@ from vm import *
from
graph
import
*
from
graph
import
*
from
storage
import
*
from
storage
import
*
from
request
import
*
from
request
import
*
from
message
import
*
This diff is collapsed.
Click to expand it.
circle/dashboard/views/message.py
0 → 100644
View file @
c10c1a49
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.core.urlresolvers
import
reverse
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
CreateView
,
DeleteView
,
UpdateView
from
braces.views
import
SuperuserRequiredMixin
,
LoginRequiredMixin
from
django_tables2
import
SingleTableView
from
..forms
import
MessageForm
from
..models
import
Message
from
..tables
import
MessageListTable
class
MessageList
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
SingleTableView
):
template_name
=
"dashboard/message-list.html"
model
=
Message
table_class
=
MessageListTable
class
MessageDetail
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
Message
template_name
=
"dashboard/message-edit.html"
form_class
=
MessageForm
success_message
=
_
(
"Broadcast message successfully updated."
)
class
MessageCreate
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
Message
template_name
=
"dashboard/message-create.html"
form_class
=
MessageForm
success_message
=
_
(
"New broadcast message successfully created."
)
class
MessageDelete
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
DeleteView
):
model
=
Message
template_name
=
"dashboard/confirm/base-delete.html"
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.message-list"
)
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment