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
6562e1be
authored
Jan 26, 2015
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into issue-378
Conflicts: circle/network/static/network/network.less
parents
015de106
23ae8ecc
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
246 additions
and
170 deletions
+246
-170
circle/dashboard/static/dashboard/node-list.js
+2
-8
circle/dashboard/templates/dashboard/node-list/column-monitor.html
+1
-0
circle/network/static/network/network.less
+7
-0
circle/network/tables.py
+17
-6
circle/network/templates/network/columns/_rule-type.html
+16
-0
circle/network/templates/network/columns/color-desc.html
+0
-19
circle/network/templates/network/columns/rule-short-description.html
+32
-0
circle/network/templates/network/dashboard.html
+135
-135
circle/network/templates/network/rule-list.html
+18
-1
circle/network/views.py
+18
-1
No files found.
circle/dashboard/static/dashboard/node-list.js
View file @
6562e1be
$
(
function
()
{
$
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
colortable
();
});
// find disabled nodes, set danger (red) on the rows
// find disabled nodes, set danger (red) on the rows
function
colortable
()
$
(
'.node-disabled'
).
closest
(
"tr"
).
addClass
(
'danger'
);
{
});
$
(
'.false'
).
closest
(
"tr"
).
addClass
(
'danger'
);
$
(
'.true'
).
closest
(
"tr"
).
removeClass
(
'danger'
);
}
});
});
circle/dashboard/templates/dashboard/node-list/column-monitor.html
View file @
6562e1be
{% load sizefieldtags %}
{% load sizefieldtags %}
{% load i18n %}
{% load i18n %}
<span
class=
"{% if not record.enabled %}node-disabled{% endif %}"
></span>
<i
class=
"fa fa-gears"
></i>
{% trans "CPU" %}
<i
class=
"fa fa-gears"
></i>
{% trans "CPU" %}
<div
class=
"progress pull-right"
>
<div
class=
"progress pull-right"
>
<div
class=
"progress-bar progress-bar-success"
role=
"progressbar"
<div
class=
"progress-bar progress-bar-success"
role=
"progressbar"
...
...
circle/network/static/network/network.less
View file @
6562e1be
...
@@ -28,3 +28,10 @@ footer {
...
@@ -28,3 +28,10 @@ footer {
.messagelist {
.messagelist {
margin-top: 25px;
margin-top: 25px;
}
}
#rule-list-table {
td {
text-align: center;
&:nth-child(2), &:nth-child(3) {text-align: left;}
}
}
circle/network/tables.py
View file @
6562e1be
...
@@ -148,6 +148,7 @@ class RecordTable(Table):
...
@@ -148,6 +148,7 @@ class RecordTable(Table):
address
=
TemplateColumn
(
address
=
TemplateColumn
(
template_name
=
"network/columns/records-address.html"
template_name
=
"network/columns/records-address.html"
)
)
ttl
=
Column
(
verbose_name
=
_
(
"TTL"
))
class
Meta
:
class
Meta
:
model
=
Record
model
=
Record
...
@@ -171,16 +172,26 @@ class SmallRecordTable(Table):
...
@@ -171,16 +172,26 @@ class SmallRecordTable(Table):
class
RuleTable
(
Table
):
class
RuleTable
(
Table
):
r_type
=
LinkColumn
(
'network.rule'
,
args
=
[
A
(
'pk'
)])
r_type
=
LinkColumn
(
'network.rule'
,
args
=
[
A
(
'pk'
)],
verbose_name
=
_
(
"type"
),
orderable
=
False
,
)
color_desc
=
TemplateColumn
(
color_desc
=
TemplateColumn
(
template_name
=
"network/columns/color-desc.html"
template_name
=
"network/columns/rule-short-description.html"
,
verbose_name
=
_
(
"Short description"
),
orderable
=
False
,
)
nat_external_port
=
Column
(
verbose_name
=
_
(
"NAT"
)
)
)
class
Meta
:
class
Meta
:
model
=
Rule
model
=
Rule
attrs
=
{
'class'
:
'table table-striped table-hover table-condensed'
}
attrs
=
{
'class'
:
'table table-striped table-hover table-condensed'
,
fields
=
(
'r_type'
,
'color_desc'
,
'owner'
,
'extra'
,
'direction'
,
'id'
:
"rule-list-table"
}
'action'
,
'proto'
,
'sport'
,
'dport'
,
'nat'
,
fields
=
(
'r_type'
,
'color_desc'
,
'extra'
,
'direction'
,
'action'
,
'proto'
,
'dport'
,
'nat_external_port'
,
)
'nat_external_port'
,
)
order_by
=
'direction'
order_by
=
'direction'
...
@@ -202,7 +213,7 @@ class VlanTable(Table):
...
@@ -202,7 +213,7 @@ class VlanTable(Table):
class
Meta
:
class
Meta
:
model
=
Vlan
model
=
Vlan
attrs
=
{
'class'
:
'table table-striped table-condensed'
}
attrs
=
{
'class'
:
'table table-striped table-condensed'
}
fields
=
(
'vid'
,
'name'
,
'
interface'
,
'
network4'
,
'network6'
,
fields
=
(
'vid'
,
'name'
,
'network4'
,
'network6'
,
'domain'
,
)
'domain'
,
)
order_by
=
'vid'
order_by
=
'vid'
...
...
circle/network/templates/network/columns/_rule-type.html
0 → 100644
View file @
6562e1be
{% if record.r_type == "host" %}
{{ record.host.get_fqdn }}
{% elif record.r_type == "vlan" %}
{{ record.vlan.name }}
{% elif record.r_type == "vlangroup" %}
{{ record.vlangroup }}
[{% for v in record.vlangroup.vlans.all %}
{{ v.name }}{% if not forloop.last %},{% endif %}
{% endfor %}]
{% elif record.r_type == "group" %}
{{ record.hostgroup.name }}
{% elif record.r_type == "firewall" %}
{{ record.firewall }}
{% else %}
-
{% endif %}
circle/network/templates/network/columns/color-desc.html
deleted
100644 → 0
View file @
015de106
{% load i18n %}
{% load l10n %}
{#
<span
style=
"color: #FF0000;"
>
[{{ record.r_type }}]
</span>
#}
{% if record.direction == "1" %}{{ record.foreign_network }}{% else %}{{ record.r_type }}{% endif %}
{#
<span
style=
"color: #0000FF;"
>
▸
</span>
#}
<i
class=
"fa fa-arrow-right"
></i>
{% if record.direction == "0" %}{{ record.foreign_network }}{% else %}{{ record.r_type }}{% endif %}
<span
style=
"color: #00FF00;"
>
{% if record.proto %}
proto={{ record.proto }}
{% endif %}
{% if record.sport %}
sport={{ record.sport }}
{% endif %}
{% if record.dport %}
dport={{ record.dport }}
{% endif %}
{{ record.description }}
circle/network/templates/network/columns/rule-short-description.html
0 → 100644
View file @
6562e1be
{% load i18n %}
{% if record.direction == "in" %}
{{ record.foreign_network }}
[{% for v in record.foreign_network.vlans.all %}
{{ v.name }}{% if not forloop.last %},{% endif %}
{% endfor %}]
{% else %}
{% include "network/columns/_rule-type.html" %}
{% endif %}
<i
class=
"fa fa-arrow-right"
></i>
{% if record.direction == "out" %}
{{ record.foreign_network }}
[{% for v in record.foreign_network.vlans.all %}
{{ v.name }}{% if not forloop.last %},{% endif %}
{% endfor %}]
{% else %}
{% include "network/columns/_rule-type.html" %}
{% endif %}
{% if record.nat %}
<span
class=
"label label-success"
>
NAT
[
{{record.nat_external_port}}
<i
class=
"fa fa-arrow-right"
></i>
{{ record.dport }}
]
{{ record.proto|upper }}
</span>
{% endif %}
circle/network/templates/network/dashboard.html
View file @
6562e1be
{% load i18n %}
{% load i18n %}
{% load l10n %}
{% load staticfiles %}
{% load staticfiles %}
<style>
.thumbnail
{
margin-bottom
:
30px
;
}
.dashboard-text
{
text-align
:
justify
;
}
</style>
<div
class=
"row"
>
<div
class=
"row"
>
<div
class=
"col-sm-3"
>
<div
class=
"col-sm-12"
>
<div
class=
"thumbnail"
>
<h3>
<div
class=
"caption"
>
<div
class=
"pull-right"
>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
host_list
"
%}"
>
Hosts
</a>
are machines on the network.
</p>
<a
href=
"{% url "
network
.
host_list
"
%}"
class=
"btn btn-xs btn-default"
>
<p
class=
"dashboard-text"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
</a>
</p>
<a
href=
"{% url "
network
.
host_create
"
%}"
class=
"btn btn-xs btn-success"
>
<p
class=
"text-right"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<a
href=
"{% url "
network
.
host_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
</a>
<a
href=
"{% url "
network
.
host_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
</div>
</p>
{% trans "Hosts" %}
</div>
<div>
</div>
<small>
{% trans "Hosts are machines on the network" %}
</small>
</div>
</div>
</h3>
<div
class=
"col-sm-3"
>
<h3>
<div
class=
"thumbnail"
>
<div
class=
"pull-right"
>
<div
class=
"caption"
>
<a
href=
"{% url "
network
.
vlan_list
"
%}"
class=
"btn btn-xs btn-default"
>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
vlan_list
"
%}"
>
Vlans
</a>
are machines on the network.
</p>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<p
class=
"dashboard-text"
>
</a>
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
<a
href=
"{% url "
network
.
vlan_create
"
%}"
class=
"btn btn-xs btn-success"
>
</p>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<p
class=
"text-right"
>
</a>
<a
href=
"{% url "
network
.
vlan_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
</div>
<a
href=
"{% url "
network
.
vlan_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
{% trans "Vlans" %}
</p>
<div>
</div>
<small>
{% trans "Hosts are machines on the network" %}
</small>
</div>
</div>
</div>
</h3>
<h3>
<div
class=
"col-sm-3"
>
<div
class=
"pull-right"
>
<div
class=
"thumbnail"
>
<a
href=
"{% url "
network
.
domain_list
"
%}"
class=
"btn btn-xs btn-default"
>
<div
class=
"caption"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
domain_list
"
%}"
>
Domains
</a>
are machines on the network.
</p>
</a>
<p
class=
"dashboard-text"
>
<a
href=
"{% url "
network
.
domain_create
"
%}"
class=
"btn btn-xs btn-success"
>
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
</p>
</a>
<p
class=
"text-right"
>
</div>
<a
href=
"{% url "
network
.
domain_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
{% trans "Domains" %}
<a
href=
"{% url "
network
.
domain_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
<div>
</p>
<small>
{% trans "Hosts are machines on the network" %}
</small>
</div>
</div>
</div>
</h3>
</div>
<h3>
<div
class=
"pull-right"
>
<div
class=
"col-sm-3"
>
<a
href=
"{% url "
network
.
record_list
"
%}"
class=
"btn btn-xs btn-default"
>
<div
class=
"thumbnail"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<div
class=
"caption"
>
</a>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
record_list
"
%}"
>
Records
</a>
are machines on the network.
</p>
<a
href=
"{% url "
network
.
record_create
"
%}"
class=
"btn btn-xs btn-success"
>
<p
class=
"dashboard-text"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
</a>
</p>
</div>
<p
class=
"text-right"
>
{% trans "Records" %}
<a
href=
"{% url "
network
.
record_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
<div>
<a
href=
"{% url "
network
.
record_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
<small>
{% trans "Hosts are machines on the network" %}
</small>
</p>
</div>
</div>
</h3>
</div>
</div>
<h3>
<div
class=
"pull-right"
>
<a
href=
"{% url "
network
.
blacklist_list
"
%}"
class=
"btn btn-xs btn-default"
>
<div
class=
"col-sm-3"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<div
class=
"thumbnail"
>
</a>
<div
class=
"caption"
>
<a
href=
"{% url "
network
.
blacklist_create
"
%}"
class=
"btn btn-xs btn-success"
>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
blacklist_list
"
%}"
>
Blacklists
</a>
are machines on the network.
</p>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<p
class=
"dashboard-text"
>
</a>
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
</div>
</p>
{% trans "Blacklist items" %}
<p
class=
"text-right"
>
<div>
<a
href=
"{% url "
network
.
blacklist_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
<small>
{% trans "Hosts are machines on the network" %}
</small>
<a
href=
"{% url "
network
.
blacklist_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
</div>
</p>
</h3>
</div>
</div>
<h3>
</div>
<div
class=
"pull-right"
>
<a
href=
"{% url "
network
.
rule_list
"
%}"
class=
"btn btn-xs btn-default"
>
<div
class=
"col-sm-3"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<div
class=
"thumbnail"
>
</a>
<div
class=
"caption"
>
<a
href=
"{% url "
network
.
rule_create
"
%}"
class=
"btn btn-xs btn-success"
>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
rule_list
"
%}"
>
Rules
</a>
are machines on the network.
</p>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<p
class=
"dashboard-text"
>
</a>
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
</div>
</p>
{% trans "Rules" %}
<p
class=
"text-right"
>
<div>
<a
href=
"{% url "
network
.
rule_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
<small>
{% trans "Hosts are machines on the network" %}
</small>
<a
href=
"{% url "
network
.
rule_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
</div>
</p>
</h3>
</div>
</div>
<h3>
</div>
<div
class=
"pull-right"
>
<a
href=
"{% url "
network
.
switch_port_list
"
%}"
class=
"btn btn-xs btn-default"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
<div
class=
"col-sm-3"
>
</a>
<div
class=
"thumbnail"
>
<a
href=
"{% url "
network
.
switch_port_create
"
%}"
class=
"btn btn-xs btn-success"
>
<div
class=
"caption"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
group_list
"
%}"
>
Host groups
</a>
are machines on the network.
</p>
</a>
<p
class=
"dashboard-text"
>
</div>
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
{% trans "Switch ports" %}
</p>
<div>
<p
class=
"text-right"
>
<small>
{% trans "Hosts are machines on the network" %}
</small>
<a
href=
"{% url "
network
.
group_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
</div>
<a
href=
"{% url "
network
.
group_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
</h3>
</p>
</div>
<h3>
</div>
<div
class=
"pull-right"
>
</div>
<a
href=
"{% url "
network
.
vlan_group_list
"
%}"
class=
"btn btn-xs btn-default"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
</a>
<div
class=
"col-sm-3"
>
<a
href=
"{% url "
network
.
vlan_group_create
"
%}"
class=
"btn btn-xs btn-success"
>
<div
class=
"thumbnail"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
<div
class=
"caption"
>
</a>
<p
class=
"lead"
>
<a
href=
"{% url "
network
.
vlan_group_list
"
%}"
>
Vlan groups
</a>
are machines on the network.
</p>
</div>
<p
class=
"dashboard-text"
>
{% trans "Vlan groups" %}
Proin mattis enim risus. Ut eu enim quis auctor. Duis lobort sollicitudin lacus, scelerisque dictum arcu aliquam nec.
<div>
</p>
<small>
{% trans "Hosts are machines on the network" %}
</small>
<p
class=
"text-right"
>
</div>
<a
href=
"{% url "
network
.
vlan_group_list
"
%}"
class=
"btn btn-default"
>
{% trans "List" %}
</a>
</h3>
<a
href=
"{% url "
network
.
vlan_group_create
"
%}"
class=
"btn btn-success"
>
{% trans "Create" %}
</a>
</p>
<h3>
</div>
<div
class=
"pull-right"
>
</div>
<a
href=
"{% url "
network
.
group_list
"
%}"
class=
"btn btn-xs btn-default"
>
<i
class=
"fa fa-list"
></i>
{% trans "list" %}
</a>
<a
href=
"{% url "
network
.
group_create
"
%}"
class=
"btn btn-xs btn-success"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
</a>
</div>
{% trans "Host groups" %}
<div>
<small>
{% trans "Hosts are machines on the network" %}
</small>
</div>
</h3>
</div>
</div>
</div>
</div>
circle/network/templates/network/rule-list.html
View file @
6562e1be
...
@@ -8,10 +8,27 @@
...
@@ -8,10 +8,27 @@
{% block content %}
{% block content %}
<div
class=
"page-header"
>
<div
class=
"page-header"
>
<a
href=
"{% url "
network
.
rule_create
"
%}"
class=
"btn btn-success pull-right"
><i
class=
"fa fa-plus-circle"
></i>
{% trans "Create a new rule" %}
</a>
<a
href=
"{% url "
network
.
rule_create
"
%}"
class=
"btn btn-success pull-right"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "Create a new rule" %}
</a>
<h1>
{% trans "Rules" %}
<small>
{% trans "list of all rules" %}
</small></h1>
<h1>
{% trans "Rules" %}
<small>
{% trans "list of all rules" %}
</small></h1>
</div>
</div>
<ul
class=
"nav nav-pills"
style=
"margin: 5px 0 20px 0;"
>
<li
class=
"disabled"
>
<a
href=
"#"
>
{% trans "Filter by types" %}
</a>
</li>
<li
{%
if
not
request
.
GET
.
type
%}
class=
"active"
{%
endif
%}
>
<a
href=
"{{ request.path }}"
>
{% trans "ALL" %}
</a>
</li>
{% for k, v in types.items %}
<li
{%
if
request
.
GET
.
type =
=
k
%}
class=
"active"
{%
endif
%}
>
<a
href=
"?type={{ k }}"
>
{{ v }}
</a>
</li>
{% endfor %}
</ul>
<div
class=
"table-responsive"
>
<div
class=
"table-responsive"
>
{% render_table table %}
{% render_table table %}
</div>
</div>
...
...
circle/network/views.py
View file @
6562e1be
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
# You should have received a copy of the GNU General Public License along
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from
collections
import
OrderedDict
from
netaddr
import
IPNetwork
from
netaddr
import
IPNetwork
from
django.views.generic
import
(
TemplateView
,
UpdateView
,
DeleteView
,
from
django.views.generic
import
(
TemplateView
,
UpdateView
,
DeleteView
,
CreateView
)
CreateView
)
...
@@ -646,11 +648,26 @@ class RuleList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
...
@@ -646,11 +648,26 @@ class RuleList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
template_name
=
"network/rule-list.html"
template_name
=
"network/rule-list.html"
table_pagination
=
False
table_pagination
=
False
def
get_context_data
(
self
,
**
kwargs
):
self
.
types
=
OrderedDict
([
(
'vlan'
,
_
(
"Vlan"
)),
(
'vlangroup'
,
_
(
"Vlan group"
)),
(
'host'
,
_
(
"Host"
)),
(
'hostgroup'
,
_
(
"Host group"
)),
(
'firewall'
,
_
(
"Firewall"
))
])
context
=
super
(
RuleList
,
self
)
.
get_context_data
(
**
kwargs
)
context
[
'types'
]
=
self
.
types
return
context
def
get_table_data
(
self
):
def
get_table_data
(
self
):
r
eturn
Rule
.
objects
.
select_related
(
'host'
,
'hostgroup'
,
'vlan'
,
r
ules
=
Rule
.
objects
.
select_related
(
'host'
,
'hostgroup'
,
'vlan'
,
'vlangroup'
,
'firewall'
,
'vlangroup'
,
'firewall'
,
'foreign_network'
,
'owner'
)
'foreign_network'
,
'owner'
)
rule_type
=
self
.
request
.
GET
.
get
(
"type"
)
if
rule_type
and
rule_type
in
self
.
types
.
keys
():
rules
=
rules
.
filter
(
**
{
'
%
s__isnull'
%
rule_type
:
False
})
return
rules
class
RuleDetail
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
class
RuleDetail
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
SuccessMessageMixin
,
UpdateView
):
...
...
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