Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
AE
Sith
Commits
f66b999f
Commit
f66b999f
authored
Aug 31, 2016
by
Skia
Browse files
Improve login form
parent
fcfbfb3a
Pipeline
#159
failed with stage
in 1 minute and 40 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
111 additions
and
90 deletions
+111
-90
core/views/__init__.py
core/views/__init__.py
+3
-3
core/views/forms.py
core/views/forms.py
+18
-0
core/views/user.py
core/views/user.py
+2
-2
counter/views.py
counter/views.py
+3
-4
locale/fr/LC_MESSAGES/django.mo
locale/fr/LC_MESSAGES/django.mo
+0
-0
locale/fr/LC_MESSAGES/django.po
locale/fr/LC_MESSAGES/django.po
+85
-81
No files found.
core/views/__init__.py
View file @
f66b999f
...
...
@@ -3,16 +3,16 @@ from django.shortcuts import render
from
django.http
import
HttpResponseForbidden
,
HttpResponseNotFound
from
django.core.exceptions
import
PermissionDenied
,
ObjectDoesNotExist
from
django.views.generic.base
import
View
from
django.contrib.auth.forms
import
AuthenticationForm
from
core.models
import
Group
from
core.views.forms
import
LoginForm
def
forbidden
(
request
):
try
:
return
HttpResponseForbidden
(
render
(
request
,
"core/403.jinja"
,
context
=
{
'next'
:
request
.
path
,
'form'
:
Authenticatio
nForm
(),
'popup'
:
request
.
resolver_match
.
kwargs
[
'popup'
]
or
""
}))
Logi
nForm
(),
'popup'
:
request
.
resolver_match
.
kwargs
[
'popup'
]
or
""
}))
except
:
return
HttpResponseForbidden
(
render
(
request
,
"core/403.jinja"
,
context
=
{
'next'
:
request
.
path
,
'form'
:
Authenticatio
nForm
()}))
return
HttpResponseForbidden
(
render
(
request
,
"core/403.jinja"
,
context
=
{
'next'
:
request
.
path
,
'form'
:
Logi
nForm
()}))
def
not_found
(
request
):
return
HttpResponseNotFound
(
render
(
request
,
"core/404.jinja"
))
...
...
core/views/forms.py
View file @
f66b999f
...
...
@@ -8,6 +8,7 @@ from django.utils.translation import ugettext as _
from
phonenumber_field.widgets
import
PhoneNumberInternationalFallbackWidget
import
logging
import
re
from
core.models
import
User
,
Page
,
RealGroup
,
SithFile
...
...
@@ -68,6 +69,23 @@ class SelectUser(TextInput):
# Forms
class
LoginForm
(
AuthenticationForm
):
def
__init__
(
self
,
*
arg
,
**
kwargs
):
if
'data'
in
kwargs
.
keys
():
from
counter.models
import
Customer
data
=
kwargs
[
'data'
].
copy
()
account_code
=
re
.
compile
(
r
"^[0-9]+[A-Za-z]$"
)
if
account_code
.
match
(
data
[
'username'
]):
user
=
Customer
.
objects
.
filter
(
account_id
=
data
[
'username'
]).
first
().
user
elif
'@'
in
data
[
'username'
]:
user
=
User
.
objects
.
filter
(
email
=
data
[
'username'
]).
first
()
else
:
user
=
User
.
objects
.
filter
(
username
=
data
[
'username'
]).
first
()
data
[
'username'
]
=
user
.
username
kwargs
[
'data'
]
=
data
super
(
LoginForm
,
self
).
__init__
(
*
arg
,
**
kwargs
)
self
.
fields
[
'username'
].
label
=
_
(
"Username, email, or account number"
)
class
RegisteringForm
(
UserCreationForm
):
error_css_class
=
'error'
required_css_class
=
'required'
...
...
core/views/user.py
View file @
f66b999f
...
...
@@ -16,7 +16,7 @@ from datetime import timedelta
import
logging
from
core.views
import
CanViewMixin
,
CanEditMixin
,
CanEditPropMixin
from
core.views.forms
import
RegisteringForm
,
UserPropForm
,
UserProfileForm
from
core.views.forms
import
RegisteringForm
,
UserPropForm
,
UserProfileForm
,
LoginForm
from
core.models
import
User
,
SithFile
def
login
(
request
):
...
...
@@ -25,7 +25,7 @@ def login(request):
Needs to be improve with correct handling of form exceptions
"""
return
views
.
login
(
request
,
template_name
=
"core/login.jinja"
)
return
views
.
login
(
request
,
template_name
=
"core/login.jinja"
,
authentication_form
=
LoginForm
)
def
logout
(
request
):
"""
...
...
counter/views.py
View file @
f66b999f
...
...
@@ -4,7 +4,6 @@ from django.views.generic.edit import UpdateView, CreateView, DeleteView, Proces
from
django.forms.models
import
modelform_factory
from
django.forms
import
CheckboxSelectMultiple
from
django.core.urlresolvers
import
reverse_lazy
from
django.contrib.auth.forms
import
AuthenticationForm
from
django.http
import
HttpResponseRedirect
from
django.utils
import
timezone
from
django
import
forms
...
...
@@ -18,7 +17,7 @@ from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultip
from
ajax_select
import
make_ajax_form
,
make_ajax_field
from
core.views
import
CanViewMixin
,
CanEditMixin
,
CanEditPropMixin
,
CanCreateMixin
from
core.views.forms
import
SelectUser
from
core.views.forms
import
SelectUser
,
LoginForm
from
core.models
import
User
from
subscription.models
import
Subscriber
from
subscription.views
import
get_subscriber
...
...
@@ -77,7 +76,7 @@ class CounterMain(DetailView, ProcessFormView, FormMixin):
if
self
.
request
.
method
==
'POST'
:
self
.
object
=
self
.
get_object
()
kwargs
=
super
(
CounterMain
,
self
).
get_context_data
(
**
kwargs
)
kwargs
[
'login_form'
]
=
Authenticatio
nForm
()
kwargs
[
'login_form'
]
=
Logi
nForm
()
kwargs
[
'login_form'
].
fields
[
'username'
].
widget
.
attrs
[
'autofocus'
]
=
True
kwargs
[
'login_form'
].
cleaned_data
=
{}
# add_error fails if there are no cleaned_data
if
"credentials"
in
self
.
request
.
GET
:
...
...
@@ -348,7 +347,7 @@ class CounterLogin(RedirectView):
"""
self
.
counter_id
=
kwargs
[
'counter_id'
]
self
.
counter
=
Counter
.
objects
.
filter
(
id
=
kwargs
[
'counter_id'
]).
first
()
form
=
Authenticatio
nForm
(
request
,
data
=
request
.
POST
)
form
=
Logi
nForm
(
request
,
data
=
request
.
POST
)
self
.
errors
=
[]
if
form
.
is_valid
():
user
=
User
.
objects
.
filter
(
username
=
form
.
cleaned_data
[
'username'
]).
first
()
...
...
locale/fr/LC_MESSAGES/django.mo
View file @
f66b999f
No preview for this file type
locale/fr/LC_MESSAGES/django.po
View file @
f66b999f
...
...
@@ -6,7 +6,7 @@
msgid
""
msgstr
""
"Report-Msgid-Bugs-To:
\n
"
"POT-Creation-Date: 2016-08-
29 03:22
+0200
\n
"
"POT-Creation-Date: 2016-08-
31 02:41
+0200
\n
"
"PO-Revision-Date: 2016-07-18
\n
"
"Last-Translator: Skia <skia@libskia.so>
\n
"
"Language-Team: AE info <ae.info@utbm.fr>
\n
"
...
...
@@ -103,7 +103,7 @@ msgid "club account"
msgstr
"compte club"
#: accounting/models.py:135 accounting/models.py:178 counter/models.py:25
#: counter/models.py:
197
#: counter/models.py:
200
msgid
"amount"
msgstr
"montant"
...
...
@@ -124,7 +124,7 @@ msgid "journal"
msgstr
"classeur"
#: accounting/models.py:179 core/models.py:458 core/models.py:734
#: counter/models.py:20
0
counter/models.py:246 counter/models.py:296
#: counter/models.py:20
3
counter/models.py:246 counter/models.py:296
#: eboutic/models.py:15 eboutic/models.py:48
msgid
"date"
msgstr
"date"
...
...
@@ -133,7 +133,7 @@ msgstr "date"
msgid
"comment"
msgstr
"commentaire"
#: accounting/models.py:181 counter/models.py:20
1
counter/models.py:247
#: accounting/models.py:181 counter/models.py:20
4
counter/models.py:247
#: subscription/models.py:52
msgid
"payment method"
msgstr
"méthode de paiement"
...
...
@@ -179,7 +179,7 @@ msgstr "Compte"
msgid
"Company"
msgstr
"Entreprise"
#: accounting/models.py:190 sith/settings.py:2
91
sith/settings_sample.py:27
3
#: accounting/models.py:190 sith/settings.py:2
87
sith/settings_sample.py:27
2
msgid
"Other"
msgstr
"Autre"
...
...
@@ -468,7 +468,7 @@ msgid "Done"
msgstr
"Effectué"
#: accounting/templates/accounting/journal_details.jinja:34
#: counter/views.py:56
1
#: counter/views.py:56
0
msgid
"Comment"
msgstr
"Commentaire"
...
...
@@ -1487,7 +1487,7 @@ msgstr "Cotisant jusqu'au %(subscription_end)s"
msgid
"Not subscribed"
msgstr
"Non cotisant"
#: core/templates/core/user_detail.jinja:5
1
#: core/templates/core/user_detail.jinja:5
2
#: subscription/templates/subscription/subscription.jinja:4
#: subscription/templates/subscription/subscription.jinja:8
msgid
"New subscription"
...
...
@@ -1576,7 +1576,7 @@ msgstr "Gestion de Sith"
msgid
"Subscriptions"
msgstr
"Cotisations"
#: core/templates/core/user_tools.jinja:22 counter/views.py:47
6
#: core/templates/core/user_tools.jinja:22 counter/views.py:47
5
msgid
"Counters"
msgstr
"Comptoirs"
...
...
@@ -1613,20 +1613,24 @@ msgstr "Ajouter un nouveau dossier"
msgid
"Error creating folder %(folder_name)s: %(msg)s"
msgstr
"Erreur de création du dossier %(folder_name)s : %(msg)s"
#: core/views/files.py:61 core/views/forms.py:1
52
core/views/forms.py:1
56
#: core/views/files.py:61 core/views/forms.py:1
70
core/views/forms.py:1
74
#, python-format
msgid
"Error uploading file %(file_name)s: %(msg)s"
msgstr
"Erreur d'envoie du fichier %(file_name)s : %(msg)s"
#: core/views/forms.py:
49
core/views/forms.py:5
2
#: core/views/forms.py:
50
core/views/forms.py:5
3
msgid
"Choose file"
msgstr
"Choisir un fichier"
#: core/views/forms.py:6
3
core/views/forms.py:6
6
#: core/views/forms.py:6
4
core/views/forms.py:6
7
msgid
"Choose user"
msgstr
"Choisir un utilisateur"
#: core/views/forms.py:111
#: core/views/forms.py:87
msgid
"Username, email, or account number"
msgstr
"Nom d'utilisateur, email, ou numéro de compte AE"
#: core/views/forms.py:129
msgid
""
"Profile: you need to be visible on the picture, in order to be recognized (e."
"g. by the barmen)"
...
...
@@ -1634,15 +1638,15 @@ msgstr ""
"Photo de profil: vous devez être visible sur la photo afin d'être reconnu "
"(par exemple par les barmen)"
#: core/views/forms.py:1
12
#: core/views/forms.py:1
30
msgid
"Avatar: used on the forum"
msgstr
"Avatar : utilisé sur le forum"
#: core/views/forms.py:1
1
3
#: core/views/forms.py:13
1
msgid
"Scrub: let other know how your scrub looks like!"
msgstr
"Blouse : montrez aux autres à quoi ressemble votre blouse !"
#: core/views/forms.py:1
5
7
#: core/views/forms.py:17
5
msgid
"Bad image format, only jpeg, png, and gif are accepted"
msgstr
"Mauvais format d'image, seuls les jpeg, png, et gif sont acceptés"
...
...
@@ -1726,8 +1730,8 @@ msgstr "Bureau"
#: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
#: eboutic/templates/eboutic/eboutic_payment_result.jinja:4
#: sith/settings.py:2
90
sith/settings.py:29
8
sith/settings_sample.py:27
2
#: sith/settings_sample.py:2
80
#: sith/settings.py:2
86
sith/settings.py:29
4
sith/settings_sample.py:27
1
#: sith/settings_sample.py:2
79
msgid
"Eboutic"
msgstr
"Eboutic"
...
...
@@ -1740,15 +1744,15 @@ msgstr "vendeurs"
msgid
"counter"
msgstr
"comptoir"
#: counter/models.py:20
3
#: counter/models.py:20
6
msgid
"bank"
msgstr
"banque"
#: counter/models.py:20
5
counter/models.py:249
#: counter/models.py:20
8
counter/models.py:249
msgid
"is validated"
msgstr
"est validé"
#: counter/models.py:2
08
#: counter/models.py:2
11
msgid
"refilling"
msgstr
"rechargement"
...
...
@@ -1764,9 +1768,9 @@ msgstr "quantité"
msgid
"Sith account"
msgstr
"Compte utilisateur"
#: counter/models.py:248 sith/settings.py:2
83
sith/settings.py:28
8
#: sith/settings.py:3
1
0 sith/settings_sample.py:26
5
#: sith/settings_sample.py:2
70
sith/settings_sample.py:29
2
#: counter/models.py:248 sith/settings.py:2
79
sith/settings.py:28
4
#: sith/settings.py:30
6
sith/settings_sample.py:26
4
#: sith/settings_sample.py:2
69
sith/settings_sample.py:29
1
msgid
"Credit card"
msgstr
"Carte bancaire"
...
...
@@ -1937,93 +1941,93 @@ msgstr "Nouveau type de produit"
msgid
"There is no product types in this website."
msgstr
"Il n'y a pas de types de produit dans ce site web."
#: counter/views.py:3
6
#: counter/views.py:3
5
msgid
"Select user"
msgstr
"Choisir un utilisateur"
#: counter/views.py:5
2
#: counter/views.py:5
1
msgid
"User not found"
msgstr
"Utilisateur non trouvé"
#: counter/views.py:8
4
#: counter/views.py:8
3
msgid
"Bad credentials"
msgstr
"Mauvais identifiants"
#: counter/views.py:8
6
#: counter/views.py:8
5
msgid
"User is not subscriber"
msgstr
"L'utilisateur n'est pas cotisant."
#: counter/views.py:26
1
#: counter/views.py:26
0
msgid
"END"
msgstr
"FIN"
#: counter/views.py:26
3
#: counter/views.py:26
2
msgid
"CAN"
msgstr
"ANN"
#: counter/views.py:29
3
#: counter/views.py:29
2
msgid
"You have not enough money to buy all the basket"
msgstr
"Vous n'avez pas assez d'argent pour acheter le panier"
#: counter/views.py:47
3
#: counter/views.py:47
2
msgid
"Parent product"
msgstr
"Produit parent"
#: counter/views.py:47
4
#: counter/views.py:47
3
msgid
"Buying groups"
msgstr
"Groupes d'achat"
#: counter/views.py:54
1
#: counter/views.py:54
0
msgid
"10 cents"
msgstr
"10 centimes"
#: counter/views.py:54
2
#: counter/views.py:54
1
msgid
"20 cents"
msgstr
"20 centimes"
#: counter/views.py:54
3
#: counter/views.py:54
2
msgid
"50 cents"
msgstr
"50 centimes"
#: counter/views.py:54
4
#: counter/views.py:54
3
msgid
"1 euro"
msgstr
"1 €"
#: counter/views.py:54
5
#: counter/views.py:54
4
msgid
"2 euros"
msgstr
"2 €"
#: counter/views.py:54
6
#: counter/views.py:54
5
msgid
"5 euros"
msgstr
"5 €"
#: counter/views.py:54
7
#: counter/views.py:54
6
msgid
"10 euros"
msgstr
"10 €"
#: counter/views.py:54
8
#: counter/views.py:54
7
msgid
"20 euros"
msgstr
"20 €"
#: counter/views.py:54
9
#: counter/views.py:54
8
msgid
"50 euros"
msgstr
"50 €"
#: counter/views.py:5
50
#: counter/views.py:5
49
msgid
"100 euros"
msgstr
"100 €"
#: counter/views.py:55
1
counter/views.py:55
3
counter/views.py:55
5
#: counter/views.py:55
7
counter/views.py:55
9
#: counter/views.py:55
0
counter/views.py:55
2
counter/views.py:55
4
#: counter/views.py:55
6
counter/views.py:55
8
msgid
"Check amount"
msgstr
"Montant du chèque"
#: counter/views.py:55
2
counter/views.py:55
4
counter/views.py:55
6
#: counter/views.py:55
8
counter/views.py:5
60
#: counter/views.py:55
1
counter/views.py:55
3
counter/views.py:55
5
#: counter/views.py:55
7
counter/views.py:5
59
msgid
"Check quantity"
msgstr
"Nombre de chèque"
#: counter/views.py:56
2
#: counter/views.py:56
1
msgid
"Emptied"
msgstr
"Coffre vidé"
...
...
@@ -2175,12 +2179,12 @@ msgid "Washing and drying"
msgstr
"Lavage et séchage"
#: launderette/templates/launderette/launderette_book.jinja:26
#: sith/settings.py:42
4
sith/settings_sample.py:40
6
#: sith/settings.py:42
0
sith/settings_sample.py:40
5
msgid
"Washing"
msgstr
"Lavage"
#: launderette/templates/launderette/launderette_book.jinja:30
#: sith/settings.py:42
4
sith/settings_sample.py:40
6
#: sith/settings.py:42
0
sith/settings_sample.py:40
5
msgid
"Drying"
msgstr
"Séchage"
...
...
@@ -2235,116 +2239,116 @@ msgstr "L'utilisateur n'a pas réservé de créneau"
msgid
"Token not found"
msgstr
"Jeton non trouvé"
#: sith/settings.py:174 sith/settings_sample.py:16
1
#: sith/settings.py:174 sith/settings_sample.py:16
0
msgid
"English"
msgstr
"Anglais"
#: sith/settings.py:175 sith/settings_sample.py:16
2
#: sith/settings.py:175 sith/settings_sample.py:16
1
msgid
"French"
msgstr
"Français"
#: sith/settings.py:2
80
sith/settings.py:28
7
sith/settings.py:30
8
#: sith/settings_sample.py:26
2
sith/settings_sample.py:26
9
#: sith/settings_sample.py:29
0
#: sith/settings.py:2
76
sith/settings.py:28
3
sith/settings.py:30
4
#: sith/settings_sample.py:26
1
sith/settings_sample.py:26
8
#: sith/settings_sample.py:2
8
9
msgid
"Check"
msgstr
"Chèque"
#: sith/settings.py:2
81
sith/settings.py:28
9
sith/settings.py:30
9
#: sith/settings_sample.py:26
3
sith/settings_sample.py:27
1
#: sith/settings_sample.py:29
1
#: sith/settings.py:2
77
sith/settings.py:28
5
sith/settings.py:30
5
#: sith/settings_sample.py:26
2
sith/settings_sample.py:27
0
#: sith/settings_sample.py:29
0
msgid
"Cash"
msgstr
"Espèces"
#: sith/settings.py:28
2
sith/settings_sample.py:26
4
#: sith/settings.py:2
7
8 sith/settings_sample.py:26
3
msgid
"Transfert"
msgstr
"Virement"
#: sith/settings.py:29
5
sith/settings_sample.py:27
7
#: sith/settings.py:29
1
sith/settings_sample.py:27
6
msgid
"Belfort"
msgstr
"Belfort"
#: sith/settings.py:29
6
sith/settings_sample.py:27
8
#: sith/settings.py:29
2
sith/settings_sample.py:27
7
msgid
"Sevenans"
msgstr
"Sevenans"
#: sith/settings.py:29
7
sith/settings_sample.py:27
9
#: sith/settings.py:29
3
sith/settings_sample.py:27
8
msgid
"Montbéliard"
msgstr
"Montbéliard"
#: sith/settings.py:33
7
sith/settings_sample.py:31
9
#: sith/settings.py:33
3
sith/settings_sample.py:31
8
msgid
"One semester"
msgstr
"Un semestre, 15 €"
#: sith/settings.py:3
42
sith/settings_sample.py:32
4
#: sith/settings.py:3
38
sith/settings_sample.py:32
3
msgid
"Two semesters"
msgstr
"Deux semestres, 28 €"
#: sith/settings.py:34
7
sith/settings_sample.py:32
9
#: sith/settings.py:34
3
sith/settings_sample.py:32
8
msgid
"Common core cursus"
msgstr
"Cursus tronc commun, 45 €"
#: sith/settings.py:3
52
sith/settings.py:35
7
sith/settings_sample.py:33
4
#: sith/settings_sample.py:33
9
#: sith/settings.py:3
48
sith/settings.py:35
3
sith/settings_sample.py:33
3
#: sith/settings_sample.py:33
8
msgid
"Branch cursus"
msgstr
"Cursus branche, 45 €"
#: sith/settings.py:3
62
sith/settings_sample.py:34
4
#: sith/settings.py:3
58
sith/settings_sample.py:34
3
msgid
"Honorary member"
msgstr
"Membre honoraire, 0 €"
#: sith/settings.py:36
7
sith/settings_sample.py:34
9
#: sith/settings.py:36
3
sith/settings_sample.py:34
8
msgid
"Assidu member"
msgstr
"Membre d'Assidu, 0 €"
#: sith/settings.py:3
72
sith/settings_sample.py:35
4
#: sith/settings.py:3
68
sith/settings_sample.py:35
3
msgid
"Amicale/DOCEO member"
msgstr
"Membre de l'Amicale/DOCEO, 0 €"
#: sith/settings.py:37
7
sith/settings_sample.py:35
9
#: sith/settings.py:37
3
sith/settings_sample.py:35
8
msgid
"UT network member"
msgstr
"Cotisant du réseau UT, 0 €"
#: sith/settings.py:38
2
sith/settings_sample.py:36
4
#: sith/settings.py:3
7
8 sith/settings_sample.py:36
3
msgid
"CROUS member"
msgstr
"Membres du CROUS, 0 €"
#: sith/settings.py:38
7
sith/settings_sample.py:36
9
#: sith/settings.py:38
3
sith/settings_sample.py:36
8
msgid
"Sbarro/ESTA member"
msgstr
"Membre de Sbarro ou de l'ESTA, 15 €"
#: sith/settings.py:39
5
sith/settings_sample.py:37
7
#: sith/settings.py:39
1
sith/settings_sample.py:37
6
msgid
"President"
msgstr
"Président"
#: sith/settings.py:39
6
sith/settings_sample.py:37
8
#: sith/settings.py:39
2
sith/settings_sample.py:37
7
msgid
"Vice-President"
msgstr
"Vice-Président"
#: sith/settings.py:39
7
sith/settings_sample.py:37
9
#: sith/settings.py:39
3
sith/settings_sample.py:37
8
msgid
"Treasurer"
msgstr
"Trésorier"
#: sith/settings.py:39
8
sith/settings_sample.py:3
80
#: sith/settings.py:39
4
sith/settings_sample.py:3
79
msgid
"Communication supervisor"
msgstr
"Responsable com"
#: sith/settings.py:39
9
sith/settings_sample.py:38
1
#: sith/settings.py:39
5
sith/settings_sample.py:38
0
msgid
"Secretary"
msgstr
"Secrétaire"
#: sith/settings.py:
400
sith/settings_sample.py:38
2
#: sith/settings.py:
396
sith/settings_sample.py:38
1
msgid
"IT supervisor"
msgstr
"Responsable info"
#: sith/settings.py:
401
sith/settings_sample.py:38
3
#: sith/settings.py:
397
sith/settings_sample.py:38
2
msgid
"Board member"
msgstr
"Membre du bureau"
#: sith/settings.py:
402
sith/settings_sample.py:38
4
#: sith/settings.py:
398
sith/settings_sample.py:38
3
msgid
"Active member"
msgstr
"Membre actif"
#: sith/settings.py:
403
sith/settings_sample.py:38
5
#: sith/settings.py:
399
sith/settings_sample.py:38
4
msgid
"Curious"
msgstr
"Curieux"
...
...
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