Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
clinicaltrials
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
david Chavalarias
clinicaltrials
Commits
d6e932a7
Commit
d6e932a7
authored
Jan 04, 2017
by
Romain Loth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
used js module pattern (cmxClt) and almost finished all client-side controllers factorization
parent
40322a00
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
587 additions
and
569 deletions
+587
-569
main.py
services/main.py
+3
-3
comex_page_login_controllers.js
static/js/comex_page_login_controllers.js
+85
-0
comex_page_profile_controllers.js
static/js/comex_page_profile_controllers.js
+15
-0
comex_page_reg_controllers.js
static/js/comex_page_reg_controllers.js
+53
-97
comex_user_login_controllers.js
static/js/comex_user_login_controllers.js
+0
-158
comex_user_profile_controllers.js
static/js/comex_user_profile_controllers.js
+0
-0
comex_user_shared.js
static/js/comex_user_shared.js
+68
-49
comex_user_shared_auth.js
static/js/comex_user_shared_auth.js
+327
-226
base_layout.html
templates/base_layout.html
+2
-2
login.html
templates/login.html
+5
-11
profile.html
templates/profile.html
+17
-8
registration_full_form.html
templates/registration_full_form.html
+12
-15
No files found.
services/main.py
View file @
d6e932a7
...
@@ -151,7 +151,8 @@ def user():
...
@@ -151,7 +151,8 @@ def user():
def
login
():
def
login
():
if
request
.
method
==
'GET'
:
if
request
.
method
==
'GET'
:
return
render_template
(
return
render_template
(
"login.html"
"login.html"
,
doors_connect
=
config
[
'DOORS_HOST'
]
+
':'
+
config
[
'DOORS_PORT'
]
)
)
elif
request
.
method
==
'POST'
:
elif
request
.
method
==
'POST'
:
# TODO sanitize
# TODO sanitize
...
@@ -341,9 +342,8 @@ def sanitize(value):
...
@@ -341,9 +342,8 @@ def sanitize(value):
return
san_typed_val
return
san_typed_val
########### MAIN ###########
########### MAIN ###########
# this only uses the dev server (in prod we're run by unicorn and not as main)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
# our app should be bound to an ip (cf stackoverflow.com/a/30329547/2489184)
# our app should be bound to an ip (cf stackoverflow.com/a/30329547/2489184)
app
.
run
(
host
=
config
[
'COMEX_HOST'
],
port
=
int
(
config
[
'COMEX_PORT'
]))
app
.
run
(
host
=
config
[
'COMEX_HOST'
],
port
=
int
(
config
[
'COMEX_PORT'
]))
static/js/comex_page_login_controllers.js
0 → 100755
View file @
d6e932a7
/**
* @fileoverview
* Login via Doors
* @todo
* - package.json
*
* @version 1
* @copyright ISCPIF-CNRS 2016
* @author romain.loth@iscpif.fr
*
* @requires comex_user_shared
* @requires comex_user_shared_auth
*/
// initialize form controllers
cmxClt
.
uform
.
initialize
(
"comex_login_form"
,
loginValidate
)
// initialize auth with doors
cmxClt
.
uauth
.
emailIdSupposedToExist
=
true
// done when anything in the form changes
function
loginValidate
()
{
// console.log("loginValidate Go")
cmxClt
.
uauth
.
earlyValidate
()
// TODO checkPassStatusSingle()
if
(
cmxClt
.
uauth
.
passStatus
&&
cmxClt
.
uauth
.
emailStatus
&&
cmxClt
.
uauth
.
captchaStatus
)
{
cmxClt
.
uform
.
submitButton
.
disabled
=
false
}
else
{
cmxClt
.
uform
.
submitButton
.
disabled
=
true
}
}
function
loginDoorsThenTestUidAndSubmit
(){
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
"Logging in ISCPIF Doors..."
// all values from the form have now been validated
var
emailValue
=
cmxClt
.
uauth
.
email
.
value
var
passValue
=
cmxClt
.
uauth
.
pass1
.
value
// KNOCKING ON THE DOORS -------------------------------------
// /!\ async
callDoors
(
"user"
,
[
emailValue
,
passValue
],
// callback: get uid to send to server -------------------
function
(
doorsResp
)
{
console
.
log
(
"login resp:"
,
doorsResp
)
testUidAndSubmit
(
doorsResp
)
}
)
}
function
testUidAndSubmit
(
doorsResp
)
{
var
doorsUid
=
doorsResp
[
0
]
var
doorsMsg
=
doorsResp
[
1
]
if
(
doorsUid
==
null
)
{
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
"Problem with doors login..."
cmxClt
.
uform
.
mainMessage
.
style
.
color
=
cmxClt
.
colorRed
cmxClt
.
uform
.
submitButton
.
disabled
=
false
}
else
{
// fill in the answer we got
// £TODO fix scope uauth and uform ?
uidInput
.
value
=
doorsUid
console
.
info
(
"form was validated and registered@doors: submitting now"
)
//==== SEND! ====
theForm
.
submit
()
//===============
}
}
console
.
log
(
"login controllers load OK"
)
static/js/comex_page_profile_controllers.js
0 → 100755
View file @
d6e932a7
/**
* @fileoverview
* Profile 1/overview and 2/completing via Doors
* @todo
* - package.json
*
* @version 1
* @copyright ISCPIF-CNRS 2016
* @author romain.loth@iscpif.fr
*
* @requires comex_user_shared
* @requires comex_user_shared_auth
*/
// TODO
static/js/comex_
user
_reg_controllers.js
→
static/js/comex_
page
_reg_controllers.js
View file @
d6e932a7
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* + prepares DB save into COLS
* + prepares DB save into COLS
*
*
* @todo
* @todo
* - harmonize var names (eg 'email' vs 'initialsInput' are both input elts)
* - harmonize var names (eg '
cmxClt.uauth.
email' vs 'initialsInput' are both input elts)
* - package.json
* - package.json
*
*
* @version 1
* @version 1
...
@@ -17,49 +17,32 @@
...
@@ -17,49 +17,32 @@
* @requires comex_user_shared_auth
* @requires comex_user_shared_auth
*/
*/
// common vars to user forms
// initialize form controllers
// NB other vars defined in main scope but just before their respective funs
cmxClt
.
uform
.
initialize
(
"comex_reg_form"
,
testAsYouGo
)
// our form is now in cmxClt.uform.theForm
var
theFormId
=
"comex_login_form"
var
theForm
=
document
.
getElementById
(
theFormId
)
var
wholeFormData
// cf corresponding css classes
// initialize auth with doors
var
colorWhite
=
'#fff'
cmxClt
.
uauth
.
emailIdSupposedToExist
=
false
var
colorRed
=
'#910'
var
colorGreen
=
'#161'
var
colorGrey
=
'#554'
// vars that will be used during the interaction
var
submitButton
=
document
.
getElementById
(
'formsubmit'
)
var
mainMessage
=
document
.
getElementById
(
'main_validation_message'
)
var
jobLookingDateStatus
=
false
var
jobLookingDateStatus
=
false
submitButton
.
disabled
=
true
theForm
.
onkeyup
=
testAsYouGo
theForm
.
onchange
=
testAsYouGo
theForm
.
onblur
=
testAsYouGo
var
lastEmailValueCheckedDisplayed
=
null
// done when anything in the form changes
// done when anything in the form changes
function
testAsYouGo
()
{
function
testAsYouGo
()
{
// console.log("testAsYouGo Go")
// console.log("testAsYouGo Go")
if
(
email
.
value
!=
lastEmailValueCheckedDisplayed
)
{
cmxClt
.
uauth
.
earlyValidate
()
// will update the emailStatus boolean
basicEmailValidate
(
email
.
value
)
}
captchaStatus
=
(
captcha
.
value
.
length
==
realCaptchaLength
)
checkPassStatus
()
checkJobDateStatus
()
checkJobDateStatus
()
if
(
passStatus
&&
emailStatus
&&
captchaStatus
&&
jobLookingDateStatus
)
{
if
(
cmxClt
.
uauth
.
passStatus
submitButton
.
disabled
=
false
&&
cmxClt
.
uauth
.
emailStatus
&&
cmxClt
.
uauth
.
captchaStatus
&&
jobLookingDateStatus
)
{
cmxClt
.
uform
.
submitButton
.
disabled
=
false
}
}
else
{
else
{
submitButton
.
disabled
=
true
cmxClt
.
uform
.
submitButton
.
disabled
=
true
}
}
var
now
=
new
Date
()
var
now
=
new
Date
()
regTimestamp
.
value
=
now
.
toISOString
()
regTimestamp
.
value
=
now
.
toISOString
()
...
@@ -111,7 +94,7 @@ var jobLookingDivStyle = document.getElementById('job_looking_div').style
...
@@ -111,7 +94,7 @@ var jobLookingDivStyle = document.getElementById('job_looking_div').style
// case false => Ok("""{"status":"login available"}""")
// case false => Ok("""{"status":"login available"}""")
function
testDoorsUserExists
(
emailValue
)
{
function
testDoorsUserExists
(
emailValue
)
{
// /!\ async
// /!\ async
callDoors
(
c
mxClt
.
uauth
.
c
allDoors
(
"userExists"
,
"userExists"
,
[
emailValue
],
[
emailValue
],
function
(
doorsResp
)
{
function
(
doorsResp
)
{
...
@@ -119,6 +102,7 @@ function testDoorsUserExists(emailValue) {
...
@@ -119,6 +102,7 @@ function testDoorsUserExists(emailValue) {
var
doorsMsg
=
doorsResp
[
1
]
var
doorsMsg
=
doorsResp
[
1
]
// the global status can be true iff login is available and format ok
// the global status can be true iff login is available and format ok
// £TODO fix scope (use uauth)
emailStatus
=
(
doorsMsg
==
"login available"
)
emailStatus
=
(
doorsMsg
==
"login available"
)
displayDoorsStatusInRegisterBox
(
emailStatus
,
emailValue
)
displayDoorsStatusInRegisterBox
(
emailStatus
,
emailValue
)
...
@@ -131,8 +115,8 @@ function registerDoorsAndSubmit(){
...
@@ -131,8 +115,8 @@ function registerDoorsAndSubmit(){
mainMessage
.
innerHTML
=
"Registering with ISCPIF Doors..."
mainMessage
.
innerHTML
=
"Registering with ISCPIF Doors..."
// all values from the form have now been validated
// all values from the form have now been validated
var
emailValue
=
email
.
value
var
emailValue
=
cmxClt
.
uauth
.
email
.
value
var
passValue
=
pass1
.
value
var
passValue
=
cmxClt
.
uauth
.
pass1
.
value
var
wholenameValue
=
""
var
wholenameValue
=
""
if
(
mName
.
value
!=
""
)
{
if
(
mName
.
value
!=
""
)
{
...
@@ -143,7 +127,7 @@ function registerDoorsAndSubmit(){
...
@@ -143,7 +127,7 @@ function registerDoorsAndSubmit(){
}
}
//
KNOCK
ING ON THE DOORS -------------------------------------
//
REGISTER
ING ON THE DOORS -------------------------------------
// /!\ async
// /!\ async
callDoors
(
callDoors
(
"register"
,
"register"
,
...
@@ -151,6 +135,7 @@ function registerDoorsAndSubmit(){
...
@@ -151,6 +135,7 @@ function registerDoorsAndSubmit(){
// callback: send to DB -------------------
// callback: send to DB -------------------
function
(
doorsResp
)
{
function
(
doorsResp
)
{
console
.
log
(
"register resp:"
,
doorsResp
)
addUidThenSubmit
(
doorsResp
)
addUidThenSubmit
(
doorsResp
)
}
}
)
)
...
@@ -161,55 +146,21 @@ function addUidThenSubmit(doorsResp) {
...
@@ -161,55 +146,21 @@ function addUidThenSubmit(doorsResp) {
var
doorsMsg
=
doorsResp
[
1
]
var
doorsMsg
=
doorsResp
[
1
]
if
(
doorsUid
==
null
)
{
if
(
doorsUid
==
null
)
{
mainMessage
.
innerHTML
=
"Problem with doors registration... TODO debug"
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
"Problem with doors registration... TODO debug"
mainMessage
.
style
.
color
=
colorRed
cmxClt
.
uform
.
mainMessage
.
style
.
color
=
cmxClt
.
colorRed
submitButton
.
disabled
=
false
cmxClt
.
uform
.
submitButton
.
disabled
=
false
}
}
else
{
else
{
// fill in the answer we got
// fill in the answer we got
// £TODO fix scope uauth and uform ?
uidInput
.
value
=
doorsUid
uidInput
.
value
=
doorsUid
console
.
info
(
"form was validated and registered@doors: submitting now"
)
console
.
info
(
"form was validated and registered@doors: submitting now"
)
//==== SEND! ====
//==== SEND! ==================
theForm
.
submit
()
cmxClt
.
uform
.
theForm
.
submit
()
//===============
//=============================
}
}
var
doorsIcon
=
document
.
getElementById
(
'doors_ret_icon'
)
function
displayDoorsStatusInRegisterBox
(
available
,
emailValue
)
{
if
(
available
)
{
// icon
doorsIconMessage
.
title
=
"Ok ID available on Doors"
doorsIcon
.
style
.
color
=
colorGreen
doorsIcon
.
classList
.
remove
(
'glyphicon-remove'
)
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
doorsIcon
.
classList
.
add
(
'glyphicon-ok'
)
// message in legend
doorsMessage
.
innerHTML
=
"Ok, this email ID is available on Doors!"
doorsMessage
.
style
.
color
=
colorGreen
}
}
else
{
// icon
doorsIconMessage
.
title
=
"Sorry ID already taken on Doors!"
doorsIcon
.
style
.
color
=
colorRed
doorsIcon
.
classList
.
remove
(
'glyphicon-ok'
)
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
doorsIcon
.
classList
.
add
(
'glyphicon-remove'
)
// message in legend
doorsMessage
.
innerHTML
=
"Sorry this email ID is already taken on Doors!"
doorsMessage
.
style
.
color
=
colorRed
}
// to debounce further actions in testAsYouGo
// return to neutral is also in testAsYouGo
lastEmailValueCheckedDisplayed
=
emailValue
}
}
// validateAndMsg() : bool (validates fields before doors registration and send)
// validateAndMsg() : bool (validates fields before doors registration and send)
...
@@ -224,20 +175,19 @@ function validateAndMsg() {
...
@@ -224,20 +175,19 @@ function validateAndMsg() {
// not necessary b/c button type is set and is != "submit"
// not necessary b/c button type is set and is != "submit"
// submitEvent.preventDefault()
// submitEvent.preventDefault()
submitButton
.
disabled
=
true
cmxClt
.
uform
.
submitButton
.
disabled
=
true
mainMessage
.
style
.
display
=
'block'
cmxClt
.
uform
.
mainMessage
.
style
.
display
=
'block'
var
valid
=
true
var
valid
=
true
// TODO pass mainMessage ref as arg
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
"Validating the form..."
mainMessage
.
innerHTML
=
"Validating the form..."
// also reformat the jobDate from "YYYY/MM/DD" to ISO
// also reformat the jobDate from "YYYY/MM/DD" to ISO
if
(
jobDate
.
value
.
length
)
jobDate
.
value
=
(
new
Date
(
jobDate
.
value
)).
toISOString
()
if
(
jobDate
.
value
.
length
)
jobDate
.
value
=
(
new
Date
(
jobDate
.
value
)).
toISOString
()
// objectify the form
// objectify the form
wholeFormData
=
new
FormData
(
theForm
);
cmxClt
.
uform
.
wholeFormData
=
new
FormData
(
theForm
);
var
missingFields
=
[]
var
missingFields
=
[]
var
toolongFields
=
[]
var
toolongFields
=
[]
...
@@ -255,7 +205,7 @@ function validateAndMsg() {
...
@@ -255,7 +205,7 @@ function validateAndMsg() {
// skip doors_uid done afterwards if form ok
// skip doors_uid done afterwards if form ok
if
(
fieldName
==
'doors_uid'
)
continue
;
if
(
fieldName
==
'doors_uid'
)
continue
;
var
actualValue
=
wholeFormData
.
get
(
fieldName
)
var
actualValue
=
cmxClt
.
uform
.
wholeFormData
.
get
(
fieldName
)
// console.log("actualValue", actualValue)
// console.log("actualValue", actualValue)
...
@@ -296,11 +246,11 @@ function validateAndMsg() {
...
@@ -296,11 +246,11 @@ function validateAndMsg() {
// RESULTS
// RESULTS
if
(
valid
)
{
if
(
valid
)
{
// add the captchaCheck inside the form (
jquery interference
)
// add the captchaCheck inside the form (
TODO should be automatic via realperson or uauth submodules
)
captchaCheck
.
value
=
$
(
captcha
).
realperson
(
'getHash'
)
c
mxClt
.
uauth
.
c
aptchaCheck
.
value
=
$
(
captcha
).
realperson
(
'getHash'
)
mainMessage
.
innerHTML
=
"Form is valid... Will register and submit..."
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
"Form is valid... Will register and submit..."
mainMessage
.
style
.
display
=
'block'
cmxClt
.
uform
.
mainMessage
.
style
.
display
=
'block'
return
true
return
true
}
}
...
@@ -308,11 +258,11 @@ function validateAndMsg() {
...
@@ -308,11 +258,11 @@ function validateAndMsg() {
console
.
warn
(
"form is not valid"
)
console
.
warn
(
"form is not valid"
)
// TODO highlight invalid fields
// TODO highlight invalid fields
submitButton
.
disabled
=
false
cmxClt
.
uform
.
submitButton
.
disabled
=
false
var
errorMessage
=
''
var
errorMessage
=
''
if
(
missingFields
.
length
)
{
if
(
missingFields
.
length
)
{
errorMessage
+=
"Please fill the missing fields: "
+
ulListFromLabelsArray
(
missingFields
,
[
"red"
])
errorMessage
+=
"Please fill the missing fields: "
+
cmxClt
.
ulListFromLabelsArray
(
missingFields
,
[
"red"
])
}
}
// length is handled by each input's maxlength
// length is handled by each input's maxlength
...
@@ -321,7 +271,7 @@ function validateAndMsg() {
...
@@ -321,7 +271,7 @@ function validateAndMsg() {
if
(
jobDate
.
value
.
length
)
jobDate
.
value
=
jobDate
.
value
.
slice
(
0
,
10
).
replace
(
/-/g
,
"/"
)
if
(
jobDate
.
value
.
length
)
jobDate
.
value
=
jobDate
.
value
.
slice
(
0
,
10
).
replace
(
/-/g
,
"/"
)
// display (TODO setTimeout and fade)
// display (TODO setTimeout and fade)
mainMessage
.
innerHTML
=
errorMessage
cmxClt
.
uform
.
mainMessage
.
innerHTML
=
errorMessage
return
false
return
false
}
}
}
}
...
@@ -359,12 +309,12 @@ function checkShowPic() {
...
@@ -359,12 +309,12 @@ function checkShowPic() {
if
(
theFile
.
size
>
max_size
)
{
if
(
theFile
.
size
>
max_size
)
{
// msg pb
// msg pb
picMsg
.
innerHTML
=
"The picture is too big (200kB max)!"
picMsg
.
innerHTML
=
"The picture is too big (200kB max)!"
picMsg
.
style
.
color
=
colorRed
picMsg
.
style
.
color
=
c
mxClt
.
c
olorRed
}
}
else
{
else
{
// msg ok
// msg ok
picMsg
.
innerHTML
=
"Picture ok"
picMsg
.
innerHTML
=
"Picture ok"
picMsg
.
style
.
color
=
colorGreen
picMsg
.
style
.
color
=
c
mxClt
.
c
olorGreen
// to show the pic when readAsDataURL
// to show the pic when readAsDataURL
imgReader
.
onload
=
function
()
{
imgReader
.
onload
=
function
()
{
...
@@ -389,7 +339,7 @@ function checkShowPic() {
...
@@ -389,7 +339,7 @@ function checkShowPic() {
boxShowPicImg
.
style
.
display
=
'block'
boxShowPicImg
.
style
.
display
=
'block'
// possible re-adjust outerbox ?
// possible re-adjust outerbox ?
// showPicImg.style.border = "2px dashed " + colorGrey
// showPicImg.style.border = "2px dashed " + c
mxClient.c
olorGrey
}
}
...
@@ -456,17 +406,22 @@ jobDate.onchange = checkJobDateStatus
...
@@ -456,17 +406,22 @@ jobDate.onchange = checkJobDateStatus
function
checkJobDateStatus
()
{
function
checkJobDateStatus
()
{
jobLookingDateStatus
=
(
jobBool
.
value
==
"No"
||
validDate
.
test
(
jobDate
.
value
))
jobLookingDateStatus
=
(
jobBool
.
value
==
"No"
||
validDate
.
test
(
jobDate
.
value
))
if
(
!
jobLookingDateStatus
)
{
if
(
!
jobLookingDateStatus
)
{
jobDateMsg
.
style
.
color
=
colorRed
jobDateMsg
.
style
.
color
=
c
mxClt
.
c
olorRed
jobDateMsg
.
innerHTML
=
'Date is not yet in the valid format YYYY/MM/DD'
jobDateMsg
.
innerHTML
=
'Date is not yet in the valid format YYYY/MM/DD'
}
}
else
{
else
{
jobDateMsg
.
style
.
color
=
colorGreen
jobDateMsg
.
style
.
color
=
c
mxClt
.
c
olorGreen
jobDateMsg
.
innerHTML
=
'Ok valid date!'
jobDateMsg
.
innerHTML
=
'Ok valid date!'
}
}
}
}
// £TODO1 move autocomp data to an autocomplete module
// -> local data for countries, jobtitles
// -> ajax fetcher for the scholars, kws and labs
// £TODO2 add a fetcher API on services side
// autocomplete countries
// autocomplete countries
$
(
function
()
{
$
(
function
()
{
var
$countryInput
=
$
(
'#country'
)
var
$countryInput
=
$
(
'#country'
)
...
@@ -1077,11 +1032,12 @@ console.log("reg controllers load OK")
...
@@ -1077,11 +1032,12 @@ console.log("reg controllers load OK")
// lName.value = "Tartampion"
// lName.value = "Tartampion"
// initialsInput.value="JPP"
// initialsInput.value="JPP"
// document.getElementById('country').value = "France"
// document.getElementById('country').value = "France"
// email.value= makeRandomString(7)+"@om.fr"
// pass1.value="123456+789"
// pass2.value="123456+789"
// document.getElementById('position').value = "atitle"
// document.getElementById('position').value = "atitle"
// document.getElementById('keywords').value = "Blabla"
// document.getElementById('keywords').value = "Blabla"
// document.getElementById('org').value = "CNRS"
// document.getElementById('org').value = "CNRS"
// basicEmailValidate(email.value)
// cmxClt.uauth.email.value= cmxClt.makeRandomString(7)+"@om.fr"
// cmxClt.uauth.pass1.value="123456+789"
// cmxClt.uauth.pass2.value="123456+789"
// cmxClt.uauth.testMailFormatAndExistence(email.value, false)
// --------------------------->8------
// --------------------------->8------
static/js/comex_user_login_controllers.js
deleted
100755 → 0
View file @
40322a00
/**
* @fileoverview
* Login via Doors
* @todo
* - package.json
*
* @version 1
* @copyright ISCPIF-CNRS 2016
* @author romain.loth@iscpif.fr
*
* @requires comex_user_shared
* @requires comex_user_shared_auth
*/
// common vars to user forms
// NB other vars defined in main scope but just before their respective funs
var
theFormId
=
"comex_login_form"
var
theForm
=
document
.
getElementById
(
theFormId
)
var
wholeFormData
// cf corresponding css classes
var
colorWhite
=
'#fff'
var
colorRed
=
'#910'
var
colorGreen
=
'#161'
var
colorGrey
=
'#554'
// vars that will be used during the interaction
var
submitButton
=
document
.
getElementById
(
'formsubmit'
)
var
mainMessage
=
document
.
getElementById
(
'main_validation_message'
)
submitButton
.
disabled
=
true
theForm
.
onkeyup
=
testAsYouGo
theForm
.
onchange
=
testAsYouGo
theForm
.
onblur
=
testAsYouGo
var
lastEmailValueCheckedDisplayed
=
null
// done when anything in the form changes
function
testAsYouGo
()
{
// console.log("testAsYouGo Go")
if
(
email
.
value
!=
lastEmailValueCheckedDisplayed
)
{
// will update the emailStatus boolean
basicEmailValidate
(
email
.
value
)
}
captchaStatus
=
(
captcha
.
value
.
length
==
realCaptchaLength
)
checkPassStatusSingle
()
if
(
passStatus
&&
emailStatus
&&
captchaStatus
)
{
submitButton
.
disabled
=
false
}
else
{
submitButton
.
disabled
=
true
}
}
// NB using new route in doors api/userExists
// case true => Ok("""{"status":"login exists"}""")
// case false => Ok("""{"status":"login available"}""")
function
testDoorsUserExists
(
emailValue
)
{
// /!\ async
callDoors
(
"userExists"
,
[
emailValue
],
function
(
doorsResp
)
{
var
doorsUid
=
doorsResp
[
0
]
var
doorsMsg
=
doorsResp
[
1
]
// for login the global status can be true iff login exists
emailStatus
=
(
doorsMsg
==
"login available"
)
displayDoorsStatusInLoginBox
(
emailStatus
,
emailValue
)
}
)
}
function
doorsThenTestUidAndSubmit
(){
mainMessage
.
innerHTML
=
"Logging in ISCPIF Doors..."
// all values from the form have now been validated
var
emailValue
=
email
.
value
var
passValue
=
pass
.
value
// KNOCKING ON THE DOORS -------------------------------------
// /!\ async
callDoors
(
"user"
,
[
emailValue
,
passValue
],
// callback: get uid to send to server -------------------
function
(
doorsResp
)
{
testUidAndSubmit
(
doorsResp
)
}
)
}
function
testUidAndSubmit
(
doorsResp
)
{
var
doorsUid
=
doorsResp
[
0
]
var
doorsMsg
=
doorsResp
[
1
]
if
(
doorsUid
==
null
)
{
mainMessage
.
innerHTML
=
"Problem with doors login..."
mainMessage
.
style
.
color
=
colorRed
submitButton
.
disabled
=
false
}
else
{
// fill in the answer we got
uidInput
.
value
=
doorsUid
console
.
info
(
"form was validated and registered@doors: submitting now"
)
//==== SEND! ====
theForm
.
submit
()
//===============
}
}
var
doorsIcon
=
document
.
getElementById
(
'doors_ret_icon'
)
function
displayDoorsStatusInLoginBox
(
available
,
emailValue
)
{
if
(
available
)
{
// icon
doorsIconMessage
.
title
=
"Sorry this ID isn't recognized on Doors!"
doorsIcon
.
style
.
color
=
colorRed
doorsIcon
.
classList
.
remove
(
'glyphicon-ok'
)
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
doorsIcon
.
classList
.
add
(
'glyphicon-remove'
)
// message in legend
doorsMessage
.
innerHTML
=
"Sorry this email ID isn't recognized on Doors!"
doorsMessage
.
style
.
color
=
colorRed
}
else
{
// icon
doorsIconMessage
.
title
=
"Ok ID exists in Doors"
doorsIcon
.
style
.
color
=
colorGreen
doorsIcon
.
classList
.
remove
(
'glyphicon-remove'
)
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
doorsIcon
.
classList
.
add
(
'glyphicon-ok'
)
// message in legend
doorsMessage
.
innerHTML
=
"Ok, this email ID is recognized in Doors!"
doorsMessage
.
style
.
color
=
colorGreen
}
// to debounce further actions in testAsYouGo
// return to neutral is also in testAsYouGo
lastEmailValueCheckedDisplayed
=
emailValue
}
console
.
log
(
"login controllers load OK"
)
static/js/comex_user_profile_controllers.js
deleted
100755 → 0
View file @
40322a00
static/js/comex_user_shared.js
View file @
d6e932a7
/**
/**
* @fileoverview
* @fileoverview
* Shared vars and functions for all user forms
* Comex Client Module: initialize and expose as *cmxClt* var
* -> shared vars for css
* -> shared vars and functions for all user forms in *cmxClt.uform* submodule
*
*
* @todo
* @todo
* - package.json
* - package.json
...
@@ -11,56 +13,73 @@
...
@@ -11,56 +13,73 @@
*
*
*/
*/
// common vars to user forms
// NB other vars defined in main scope but just before their respective funs
// initialize and export cmxClt module
var
theFormId
=
"comex_login_form"
var
cmxClt
=
(
function
()
{
var
theForm
=
document
.
getElementById
(
theFormId
)
var
wholeFormData
ccModule
=
{}
// cf corresponding css classes
// cf corresponding css classes
var
colorWhite
=
'#fff'
ccModule
.
colorWhite
=
'#fff'
var
colorRed
=
'#910'
ccModule
.
colorRed
=
'#910'
var
colorGreen
=
'#161'
ccModule
.
colorGreen
=
'#161'
var
colorGrey
=
'#554'
ccModule
.
colorGrey
=
'#554'
// vars that will be used during the interaction
var
submitButton
=
document
.
getElementById
(
'formsubmit'
)
ccModule
.
makeRandomString
=
function
(
nChars
)
{
var
mainMessage
=
document
.
getElementById
(
'main_validation_message'
)
var
rando
=
""
theForm
.
onkeyup
=
testAsYouGo
var
possible
=
"abcdefghijklmnopqrstuvwxyz0123456789"
;
theForm
.
onchange
=
testAsYouGo
var
len
=
possible
.
length
theForm
.
onblur
=
testAsYouGo
for
(
var
i
=
0
;
i
<
nChars
;
i
++
)
rando
+=
possible
.
charAt
(
Math
.
floor
(
Math
.
random
()
*
len
));
var
lastEmailValueCheckedDisplayed
=
null
return
rando
}
function
makeRandomString
(
nChars
)
{
var
rando
=
""
ccModule
.
ulListFromLabelsArray
=
function
(
strArray
,
ulClassList
)
{
var
possible
=
"abcdefghijklmnopqrstuvwxyz0123456789"
;
ulClasses
=
[
"minilabels"
].
concat
(
ulClassList
).
join
(
" "
)
var
len
=
possible
.
length
var
resultHtml
=
'<ul class="'
+
ulClasses
+
'">'
for
(
var
i
=
0
;
i
<
nChars
;
i
++
)
for
(
var
i
in
strArray
)
{
rando
+=
possible
.
charAt
(
Math
.
floor
(
Math
.
random
()
*
len
));
var
label
=
strArray
[
i
].
replace
(
/_/
,
" "
)
return
rando
resultHtml
+=
'<li class="minilabel">'
+
label
+
'</li>'
}
}
resultHtml
+=
'</ul>'
return
resultHtml
function
ulListFromLabelsArray
(
strArray
,
ulClassList
)
{
}
ulClasses
=
[
"minilabels"
].
concat
(
ulClassList
).
join
(
" "
)
var
resultHtml
=
'<ul class="'
+
ulClasses
+
'">'
// basic inputs get normal on focus
for
(
var
i
in
strArray
)
{
ccModule
.
makeNormal
=
function
(
elt
)
{
var
label
=
strArray
[
i
].
replace
(
/_/
,
" "
)
elt
.
style
.
fontWeight
=
"normal"
resultHtml
+=
'<li class="minilabel">'
+
label
+
'</li>'
}
// basic inputs get bold on blur
ccModule
.
makeBold
=
function
(
elt
){
if
(
elt
.
value
!=
""
)
elt
.
style
.
fontWeight
=
"bold"
}
// common vars to user forms
ccModule
.
uform
=
{}
ccModule
.
uform
.
theFormId
=
null
ccModule
.
uform
.
theForm
=
null
ccModule
.
uform
.
wholeFormData
=
null
// vars that will be used during the interaction
ccModule
.
uform
.
submitButton
=
document
.
getElementById
(
'formsubmit'
)
ccModule
.
uform
.
mainMessage
=
document
.
getElementById
(
'main_validation_message'
)
ccModule
.
uform
.
initialize
=
function
(
aFormId
,
aValidationFun
)
{
ccModule
.
uform
.
theFormId
=
aFormId
ccModule
.
uform
.
theForm
=
document
.
getElementById
(
aFormId
)
ccModule
.
uform
.
theForm
.
onkeyup
=
aValidationFun
ccModule
.
uform
.
theForm
.
onchange
=
aValidationFun
ccModule
.
uform
.
theForm
.
onblur
=
aValidationFun
}
}
resultHtml
+=
'</ul>'
return
resultHtml
}
return
ccModule
}())
;
// basic inputs get normal on focus
function
makeNormal
(
elt
)
{
elt
.
style
.
fontWeight
=
"normal"
}
// basic inputs get bold on blur
function
makeBold
(
elt
){
if
(
elt
.
value
!=
""
)
elt
.
style
.
fontWeight
=
"bold"
}
console
.
log
(
"shared load OK"
)
static/js/comex_user_shared_auth.js
View file @
d6e932a7
/**
/**
* @fileoverview
* @fileoverview
* Validates email ID and passwords
* Validates an email ID and password(s)
* Prepares "captcha" data
* Transmits login credentials to Doors for login or register (fun callDoors)
* Transmits login credentials to Doors for login or register (fun callDoors)
*
*
* @todo
* @todo
...
@@ -14,246 +15,346 @@
...
@@ -14,246 +15,346 @@
* @requires realperson (keith-wood.name/realPerson.html)
* @requires realperson (keith-wood.name/realPerson.html)
*/
*/
// common vars to authenticating user forms
// cmxClt module augmentation
var
uidInput
=
document
.
getElementById
(
'doors_uid'
)
cmxClt
=
(
function
(
ccModule
)
{
var
email
=
document
.
getElementById
(
'email'
)
// common vars to authenticating/registering in user area
ccModule
.
uauth
=
{}
// str of the form: doors_hostname:doors_port
var
bidule
=
"trux"
var
doorsConnectParam
=
document
.
getElementById
(
'doors_connect'
).
value
ccModule
.
uauth
.
emailIdSupposedToExist
=
null
// captchaHash should be appended by itself if normal submit,
// but we may need to do it ourselves (TODO test)
ccModule
.
uauth
.
uidInput
=
document
.
getElementById
(
'doors_uid'
)
var
captcha
=
document
.
getElementById
(
'my-captcha'
)
ccModule
.
uauth
.
email
=
document
.
getElementById
(
'email'
)
var
captchaCheck
=
document
.
getElementById
(
'my-captchaHash'
)
ccModule
.
uauth
.
emailLbl
=
document
.
querySelector
(
'label[for=email]'
)
// param for generation & validation
// str of the form: doors_hostname:doors_port
var
realCaptchaLength
=
5
ccModule
.
uauth
.
doorsConnectParam
=
document
.
getElementById
(
'doors_connect'
).
value
// captchaHash should be appended by itself if normal submit,
// but we may need to do it ourselves (TODO test)
var
doorsMessage
=
document
.
getElementById
(
'doors_ret_message'
)
ccModule
.
uauth
.
captcha
=
document
.
getElementById
(
'my-captcha'
)
var
doorsIconMessage
=
document
.
getElementById
(
'doors_ret_icon_msg'
)
ccModule
.
uauth
.
captchaCheck
=
document
.
getElementById
(
'my-captchaHash'
)
var
doorsIcon
=
document
.
getElementById
(
'doors_ret_icon'
)
// param for generation & validation
// validate as we go to even get the submitButton
ccModule
.
uauth
.
realCaptchaLength
=
5
var
passStatus
=
false
var
emailStatus
=
false
// initialize pseudo captcha
var
captchaStatus
=
false
$
(
'#my-captcha'
).
realperson
({
length
:
ccModule
.
uauth
.
realCaptchaLength
});
/* --------------- doors ajax cors function ----------------
// doors-related html elements
* @args:
ccModule
.
uauth
.
doorsMessage
=
document
.
getElementById
(
'doors_ret_message'
)
* apiAction: 'register' or 'user' or 'userExists' => route to doors api
ccModule
.
uauth
.
doorsIconMessage
=
document
.
getElementById
(
'doors_ret_icon_msg'
)
* if unknown type, default action is login via doors/api/user
ccModule
.
uauth
.
doorsIcon
=
document
.
getElementById
(
'doors_ret_icon'
)
*
* data: 3-uple with mail, pass, name
// cmxClt.u.auth validators (needed to even get the submitButton)
*
ccModule
.
uauth
.
passStatus
=
false
* callback: function that will be called after success AND after error
ccModule
.
uauth
.
emailStatus
=
false
* with the return couple
ccModule
.
uauth
.
captchaStatus
=
false
*
ccModule
.
uauth
.
lastEmailValueCheckedDisplayed
=
null
* returns couple (id, message)
* ----------------------------
ccModule
.
uauth
.
earlyValidate
=
function
()
{
* ajax success <=> doorsId should be != null except if unknown error
// will update the ccModule.uauth.emailStatus boolean
* ajax user infos == doorsMsg
ccModule
.
uauth
.
testMailFormatAndExistence
(
ccModule
.
uauth
.
email
.
value
,
ccModule
.
uauth
.
emailIdSupposedToExist
)
*
* EXPECTED DOORS ANSWER FORMAT
ccModule
.
uauth
.
captchaStatus
=
(
ccModule
.
uauth
.
captcha
.
value
.
length
==
ccModule
.
uauth
.
realCaptchaLength
)
* -----------------------------
* {
}
* "status": "login ok",
* "userInfo": {
// email validation and side-effects
* "id": {
// =================================
* "id": "78407900-6f48-44b8-ab37-503901f85458"
// NB for login, use --------> expectExists = true
* },
// for registration, use -> expectExists = false
* "password": "68d23eab21abab38542184e8fca2199d",
* "name": "JPP",
// no return value, but side effect on icon + msg + emailStatus
* "hashAlgorithm": "PBKDF2",
// wrong format ===========================> grey
* "hashParameters": {"iterations": 1000, "keyLength": 128}
// format ok, doorsStatus != expectExists => red
* }
// format ok, doorsStatus == expectExists => green
* }
*/
ccModule
.
uauth
.
testMailFormatAndExistence
=
function
(
emailValue
,
expectExists
)
{
function
callDoors
(
apiAction
,
data
,
callback
)
{
if
(
ccModule
.
uauth
.
email
.
value
!=
ccModule
.
uauth
.
lastEmailValueCheckedDisplayed
)
{
// console.warn("=====> CORS <=====")
// console.log("data",data)
// tests if email is well-formed
// console.log("apiAction",apiAction)
// TODO: better extension and allowed chars set
var
emailFormatOk
=
/^
[
-A-z0-9_=.+
]
+@
[
-A-z0-9_=.+
]
+
\.[
-A-z0-9_=.+
]{1,4}
$/
.
test
(
emailValue
)
var
doorsUid
=
null
var
doorsMsg
=
null
if
(
!
emailFormatOk
)
{
// restore original lack of message
// all mandatory params for doors
ccModule
.
uauth
.
doorsMessage
.
title
=
'The email will be checked in our DB after you finish typing'
var
mailStr
=
data
[
0
]
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-remove'
)
var
passStr
=
data
[
1
]
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-ok'
)
var
nameStr
=
data
[
2
]
ccModule
.
uauth
.
doorsIcon
.
classList
.
add
(
'glyphicon-question-sign'
)
ccModule
.
uauth
.
doorsIcon
.
style
.
color
=
ccModule
.
colorGrey
// test params and set defaults
ccModule
.
uauth
.
doorsMessage
.
innerHTML
=
""
if
(
typeof
apiAction
==
'undefined'
||
(
apiAction
!=
'register'
&&
apiAction
!=
'userExists'
))
{
ccModule
.
uauth
.
emailLbl
.
style
.
color
=
""
// currently forces login action unless we got 'register' or userExists
apiAction
=
'user'
// module-wide flag
console
.
warn
(
'DBG: forcing user route'
)
ccModule
.
uauth
.
emailStatus
=
false
}
else
{
// additional ajax to check login availability
// => updates the emailStatus global boolean
// => displays an icon
// NB using route in doors api/userExists
// case true => Ok("""{"status":"login exists"}""")
// case false => Ok("""{"status":"login available"}""")
// /!\ async
ccModule
.
uauth
.
callDoors
(
"userExists"
,
[
emailValue
],
function
(
doorsResp
)
{
var
doorsUid
=
doorsResp
[
0
]
var
doorsMsg
=
doorsResp
[
1
]
// the global status can be true iff login is as expected and format ok
if
(
expectExists
)
{
ccModule
.
uauth
.
emailStatus
=
(
doorsMsg
==
"login exists"
)
}
else
{
ccModule
.
uauth
.
emailStatus
=
(
doorsMsg
==
"login available"
)
}
if
(
ccModule
.
uauth
.
emailStatus
)
{
// icon
ccModule
.
uauth
.
doorsIconMessage
.
title
=
"OK: "
+
doorsMsg
+
" on Doors"
ccModule
.
uauth
.
doorsIcon
.
style
.
color
=
ccModule
.
colorGreen
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-remove'
)
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
ccModule
.
uauth
.
doorsIcon
.
classList
.
add
(
'glyphicon-ok'
)
// message in legend
ccModule
.
uauth
.
doorsMessage
.
innerHTML
=
"OK: "
+
doorsMsg
+
" on Doors"
ccModule
.
uauth
.
doorsMessage
.
style
.
color
=
ccModule
.
colorGreen
// label
ccModule
.
uauth
.
emailLbl
.
style
.
color
=
ccModule
.
colorGreen
}
else
{
var
errMsg
=
expectExists
?
"your ID isn't recognized"
:
"this ID is already taken"
// icon
ccModule
.
uauth
.
doorsIconMessage
.
title
=
"Sorry "
+
errMsg
+
" on Doors!"
ccModule
.
uauth
.
doorsIcon
.
style
.
color
=
ccModule
.
colorRed
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-ok'
)
ccModule
.
uauth
.
doorsIcon
.
classList
.
remove
(
'glyphicon-question-sign'
)
ccModule
.
uauth
.
doorsIcon
.
classList
.
add
(
'glyphicon-remove'
)
// message in legend
ccModule
.
uauth
.
doorsMessage
.
innerHTML
=
"Sorry "
+
errMsg
+
" on Doors!"
ccModule
.
uauth
.
doorsMessage
.
style
.
color
=
ccModule
.
colorRed
// label
ccModule
.
uauth
.
emailLbl
.
style
.
backgroundColor
=
ccModule
.
colorRed
}
// to debounce further actions in testAsYouGo
// return to neutral is also in testAsYouGo
ccModule
.
uauth
.
lastEmailValueCheckedDisplayed
=
emailValue
}
)
}
}
}
}
if
(
typeof
callback
!=
'function'
)
{
// -----------------------------------------------------------------------
callback
=
function
(
retval
)
{
return
retval
}
// pass 1 and pass 2 ~~~> do they match?
// TODO use a most common passwords lists
ccModule
.
uauth
.
pass1
=
document
.
getElementById
(
'password'
)
ccModule
.
uauth
.
pass2
=
document
.
getElementById
(
'password2'
)
ccModule
.
uauth
.
passMsg
=
document
.
getElementById
(
'password_message'
)
ccModule
.
uauth
.
pass1
.
onkeyup
=
ccModule
.
uauth
.
checkPassStatus
ccModule
.
uauth
.
pass1
.
onchange
=
ccModule
.
uauth
.
checkPassStatus
if
(
ccModule
.
uauth
.
pass2
)
{
// could also be attached to form onchange but then called often for nothing
ccModule
.
uauth
.
pass2
.
onkeyup
=
ccModule
.
uauth
.
checkPassStatus
ccModule
.
uauth
.
pass2
.
onchange
=
ccModule
.
uauth
.
checkPassStatus
}
}
var
ok
=
((
apiAction
==
'userExists'
&&
typeof
mailStr
!=
'undefined'
&&
mailStr
)
||
(
typeof
mailStr
!=
'undefined'
&&
typeof
mailStr
!=
'undefined'
&&
typeof
nameStr
!=
'undefined'
&&
mailStr
&&
passStr
))
// assumes mail and pass will nvr be == 0
if
(
!
ok
)
{
ccModule
.
uauth
.
checkPassStatus
=
function
()
{
doorsMsg
=
"Invalid parameters in input data (arg #1)"
// £TODO 2 functions:
console
.
warn
(
'DEBUG callDoors() internal validation failed before ajax'
)
// - check pass #X is valid (with arg pass1 or pass2) [for Login + Register]
// - check 2 passes are identical (only for Register)
if
(
pass1
.
value
||
pass2
.
value
)
{
var
pass1v
=
pass1
.
value
var
pass2v
=
pass2
.
value
if
((
pass1v
&&
pass1v
.
length
>
7
)
||
(
pass2v
&&
pass2v
.
length
>
7
))
{
// test values
if
(
pass1v
==
pass2v
)
{
if
(
pass1v
.
match
(
'[^A-z0-9]'
))
{
passMsg
.
innerHTML
=
'Ok valid passwords!'
passStatus
=
true
}
else
{
passMsg
.
innerHTML
=
'Passwords match but contain only letters and/or digits, please complexify!'
passStatus
=
false
}
}
else
{
passMsg
.
innerHTML
=
"The passwords don't match yet."
passStatus
=
false
}
}
else
{
passMsg
.
innerHTML
=
"The password is too short (8 chars min)."
passStatus
=
false
}
}
if
(
!
passStatus
)
passMsg
.
style
.
color
=
ccModule
.
colorRed
else
passMsg
.
style
.
color
=
ccModule
.
colorGreen
}
}
else
{
$
.
ajax
({
contentType
:
"application/json"
,
/* --------------- doors ajax cors function ----------------
dataType
:
'json'
,
* @args:
url
:
"http://"
+
doorsConnectParam
+
"/api/"
+
apiAction
,
* apiAction: 'register' or 'user' or 'userExists' => route to doors api
data
:
JSON
.
stringify
({
* if unknown type, default action is login via doors/api/user
"login"
:
mailStr
,
*
"password"
:
passStr
,
* data: 3-uple with mail, pass, name
"name"
:
nameStr
*
}),
* callback: function that will be called after success AND after error
type
:
'POST'
,
* with the return couple
success
:
function
(
data
)
{
*
if
(
typeof
data
!=
'undefined'
* returns couple (id, message)
&&
apiAction
==
'userExists'
)
{
* ----------------------------
// userExists success case: it's all in the message :)
* ajax success <=> doorsId should be != null except if unknown error
doorsUid
=
null
* ajax user infos == doorsMsg
doorsMsg
=
data
.
status
*
}
* EXPECTED DOORS ANSWER FORMAT
else
if
(
typeof
data
!=
'undefined'
* -----------------------------
&&
typeof
data
.
userInfo
!=
undefined
* {
&&
typeof
data
.
userInfo
.
id
!=
undefined
* "status": "login ok",
&&
typeof
data
.
userInfo
.
id
.
id
!=
undefined
* "userInfo": {
&&
typeof
data
.
status
==
'string'
)
{
* "id": {
// main success case: get the id
* "id": "78407900-6f48-44b8-ab37-503901f85458"
doorsUid
=
data
.
userInfo
.
id
.
id
* },
doorsMsg
=
data
.
status
* "password": "68d23eab21abab38542184e8fca2199d",
}
* "name": "JPP",
else
{
* "hashAlgorithm": "PBKDF2",
doorsMsg
=
"Unknown response for doors apiAction ("
+
apiAction
+
"):"
* "hashParameters": {"iterations": 1000, "keyLength": 128}
doorsMsg
+=
'"'
+
JSON
.
stringify
(
data
).
substring
(
0
,
10
)
+
'..."'
* }
}
* }
*/
// start the callback
ccModule
.
uauth
.
callDoors
=
function
(
apiAction
,
data
,
callback
)
{
callback
([
doorsUid
,
doorsMsg
])
},
// console.warn("=====> CORS <=====")
// console.log("data",data)
error
:
function
(
result
)
{
// console.log("apiAction",apiAction)
console
.
log
(
result
)
if
(
apiAction
==
'user'
){
var
doorsUid
=
null
if
(
result
.
responseText
.
match
(
/"User .+@.+ not found"/
))
{
var
doorsMsg
=
null
doorsMsg
=
result
.
responseText
.
replace
(
/^"/g
,
''
).
replace
(
/"$/g
,
''
)
// all mandatory params for doors
var
mailStr
=
data
[
0
]
var
passStr
=
data
[
1
]
var
nameStr
=
data
[
2
]
// test params and set defaults
if
(
typeof
apiAction
==
'undefined'
||
(
apiAction
!=
'register'
&&
apiAction
!=
'userExists'
))
{
// currently forces login action unless we got 'register' or userExists
apiAction
=
'user'
console
.
warn
(
'DBG: forcing user route'
)
}
if
(
typeof
callback
!=
'function'
)
{
callback
=
function
(
retval
)
{
return
retval
}
}
var
ok
=
((
apiAction
==
'userExists'
&&
typeof
mailStr
!=
'undefined'
&&
mailStr
)
||
(
typeof
mailStr
!=
'undefined'
&&
typeof
mailStr
!=
'undefined'
&&
typeof
nameStr
!=
'undefined'
&&
mailStr
&&
passStr
))
// assumes mail and pass will nvr be == 0
if
(
!
ok
)
{
doorsMsg
=
"Invalid parameters in input data (arg #1)"
console
.
warn
(
'DEBUG callDoors() internal validation failed before ajax'
)
}
else
{
$
.
ajax
({
contentType
:
"application/json"
,
dataType
:
'json'
,
url
:
"http://"
+
ccModule
.
uauth
.
doorsConnectParam
+
"/api/"
+
apiAction
,
data
:
JSON
.
stringify
({
"login"
:
mailStr
,
"password"
:
passStr
,
"name"
:
nameStr
}),
type
:
'POST'
,
success
:
function
(
data
)
{
if
(
typeof
data
!=
'undefined'
&&
apiAction
==
'userExists'
)
{
// userExists success case: it's all in the message :)
doorsUid
=
null
doorsMsg
=
data
.
status
}
else
if
(
typeof
data
!=
'undefined'
&&
typeof
data
.
userInfo
!=
undefined
&&
typeof
data
.
userInfo
.
id
!=
undefined
&&
typeof
data
.
userInfo
.
id
.
id
!=
undefined
&&
typeof
data
.
status
==
'string'
)
{
// main success case: get the id
doorsUid
=
data
.
userInfo
.
id
.
id
doorsMsg
=
data
.
status
}
}
else
{
else
{
// POSS: user message
doorsMsg
=
"Unknown response for doors apiAction ("
+
apiAction
+
"):"
console
.
warn
(
"Unhandled error doors login ("
+
result
.
responseText
+
")"
)
doorsMsg
+=
'"'
+
JSON
.
stringify
(
data
).
substring
(
0
,
10
)
+
'..."'
}
// start the callback
callback
([
doorsUid
,
doorsMsg
])
},
error
:
function
(
result
)
{
console
.
log
(
result
)
if
(
apiAction
==
'user'
){
if
(
result
.
responseText
.
match
(
/"User .+@.+ not found"/
))
{
doorsMsg
=
result
.
responseText
.
replace
(
/^"/g
,
''
).
replace
(
/"$/g
,
''
)
}
else
{
// POSS: user message
console
.
warn
(
"Unhandled error doors login ("
+
result
.
responseText
+
")"
)
}
}
}
}
else
if
(
apiAction
==
'register'
){
else
if
(
apiAction
==
'register'
){
if
(
typeof
result
.
responseJSON
!=
'undefined'
if
(
typeof
result
.
responseJSON
!=
'undefined'
&&
typeof
result
.
responseJSON
.
status
==
'string'
)
{
&&
typeof
result
.
responseJSON
.
status
==
'string'
)
{
doorsMsg
=
result
.
responseJSON
.
status
doorsMsg
=
result
.
responseJSON
.
status
// will be useful in the future (actually doors errs don't have a status message yet)
// will be useful in the future (actually doors errs don't have a status message yet)
// if doorsMsg == ''
// if doorsMsg == ''
}
else
{
// POSS: user message
doorsMsg
=
"Unhandled error doors register ("
+
result
.
responseText
+
")"
console
.
warn
(
doorsMsg
)
}
}
}
else
{
else
{
// POSS: user message
doorsMsg
=
"Unhandled error from unknown doors apiAction ("
+
apiAction
+
")"
doorsMsg
=
"Unhandled error doors register ("
+
result
.
responseText
+
")"
console
.
error
(
doorsMsg
)
console
.
warn
(
doorsMsg
)
}
}
}
else
{
// start the callback
doorsMsg
=
"Unhandled error from unknown doors apiAction ("
+
apiAction
+
")"
callback
([
doorsUid
,
doorsMsg
])
console
.
error
(
doorsMsg
)
}
}
});
}
// start the callback
callback
([
doorsUid
,
doorsMsg
])
}
});
}
}
// very basic email validation TODO: better extension and allowed chars set :)
// (used in tests "as we go")
function
basicEmailValidate
(
emailValue
)
{
// tests if email is well-formed
var
emailFormatOk
=
/^
[
-A-z0-9_=.+
]
+@
[
-A-z0-9_=.+
]
+
\.[
-A-z0-9_=.+
]{1,4}
$/
.
test
(
emailValue
)
if
(
!
emailFormatOk
)
{
// restore original lack of message
doorsMessage
.
title
=
'The email will be checked in our DB after you type and leave the box.'
doorsIcon
.
classList
.
remove
(
'glyphicon-remove'
)
doorsIcon
.
classList
.
remove
(
'glyphicon-ok'
)
doorsIcon
.
classList
.
add
(
'glyphicon-question-sign'
)
doorsIcon
.
style
.
color
=
colorGrey
emailStatus
=
false
}
else
{
// additional ajax to check login availability
// => updates the emailStatus global boolean
// => displays an icon
testDoorsUserExists
(
emailValue
)
}
}
// pass 1 and pass 2 ~~~> do they match?
// TODO use a most common passwords lists
var
pass1
=
document
.
getElementById
(
'password'
)
var
pass2
=
document
.
getElementById
(
'password2'
)
var
passMsg
=
document
.
getElementById
(
'password_message'
)
var
passwords
=
[
pass1
,
pass2
]
passwords
.
forEach
(
function
(
pass
)
{
// could also be attached to form onchange but then called often for nothing
pass
.
onkeyup
=
checkPassStatus
pass
.
onchange
=
checkPassStatus
})
function
checkPassStatus
()
{
if
(
pass1
.
value
||
pass2
.
value
)
{
var
pass1v
=
pass1
.
value
var
pass2v
=
pass2
.
value
if
((
pass1v
&&
pass1v
.
length
>
7
)
||
(
pass2v
&&
pass2v
.
length
>
7
))
{
// test values
if
(
pass1v
==
pass2v
)
{
if
(
pass1v
.
match
(
'[^A-z0-9]'
))
{
passMsg
.
innerHTML
=
'Ok valid passwords!'
passStatus
=
true
}
else
{
passMsg
.
innerHTML
=
'Passwords match but contain only letters and/or digits, please complexify!'
passStatus
=
false
}
}
else
{
passMsg
.
innerHTML
=
"The passwords don't match yet."
passStatus
=
false
}
}
else
{
passMsg
.
innerHTML
=
"The password is too short (8 chars min)."
passStatus
=
false
}
}
}
if
(
!
passStatus
)
passMsg
.
style
.
color
=
colorRed
else
passMsg
.
style
.
color
=
colorGreen
}
// we return our augmented comex client module
return
ccModule
})(
cmxClt
)
;
// pseudo captcha
$
(
'#my-captcha'
).
realperson
({
length
:
realCaptchaLength
});
$
(
'#my-captcha'
).
val
(
''
)
console
.
log
(
"user shared auth load OK"
)
console
.
log
(
"user shared auth load OK"
)
templates/base_layout.html
View file @
d6e932a7
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
<!-- NB our js will be at the end -->
<!-- NB our js will be at the end -->
<!-- ## Piwik ## -->
<!-- ## Piwik ## -->
<script
type=
"text/javascript"
>
<
!-- <
script type="text/javascript">
var _paq = _paq || [];
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['enableLinkTracking']);
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
})();
</script>
</script>
<noscript><p><img
src=
"//piwik.iscpif.fr/piwik.php?idsite=4"
style=
"border:0;"
alt=
""
/></p></noscript>
<noscript><p><img src="//piwik.iscpif.fr/piwik.php?idsite=4" style="border:0;" alt="" /></p></noscript>
-->
<!-- End Piwik Code -->
<!-- End Piwik Code -->
...
...
templates/login.html
View file @
d6e932a7
...
@@ -36,10 +36,7 @@
...
@@ -36,10 +36,7 @@
<div
class=
"question"
>
<div
class=
"question"
>
<p
class=
"legend"
>
(It is the same login for all the ISC services.)
</p>
<p
class=
"legend"
>
(It is the same login for all the ISC services.)
</p>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<!-- email validation onblur/onchange
<!-- email validation onblur/onchange is done by cmxClt.uauth in comex_user_shared_auth.js -->
is done by basicEmailValidate
and testDoorsUserExists
in comex_reg_form_controllers.js -->
<label
for=
"email"
class=
"smlabel input-group-addon"
>
Email
</label>
<label
for=
"email"
class=
"smlabel input-group-addon"
>
Email
</label>
<input
id=
"email"
name=
"email"
maxlength=
"255"
<input
id=
"email"
name=
"email"
maxlength=
"255"
type=
"text"
class=
"form-control"
placeholder=
"email"
>
type=
"text"
class=
"form-control"
placeholder=
"email"
>
...
@@ -89,7 +86,7 @@
...
@@ -89,7 +86,7 @@
<label
for=
"my-captcha"
class=
"smlabel input-group-addon"
>
Code
</label>
<label
for=
"my-captcha"
class=
"smlabel input-group-addon"
>
Code
</label>
<input
id=
"my-captcha"
name=
"my-captcha"
style=
"max-width:60%"
<input
id=
"my-captcha"
name=
"my-captcha"
style=
"max-width:60%"
type=
"text"
class=
"form-control input-lg"
placeholder=
"Enter the 5 letters you see beside =>"
type=
"text"
class=
"form-control input-lg"
placeholder=
"Enter the 5 letters you see beside =>"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<!-- == S U B M I T == -->
<!-- == S U B M I T == -->
...
@@ -106,13 +103,10 @@
...
@@ -106,13 +103,10 @@
<!-- FOR DEBUG: test go-between with Doors -->
<!-- FOR DEBUG: test go-between with Doors -->
<p>
<p>
<button
type=
button
onclick=
'c
allDoors("user", [email.value, pass1.value, initialsInput.value
], console.warn)'
>
<button
type=
button
onclick=
'c
mxClt.uauth.callDoors("user", [cmxClt.uauth.email.value, cmxClt.uauth.pass1.value, null
], console.warn)'
>
test doors login
test doors login
</button>
</button>
<button
type=
button
onclick=
'callDoors("register", [email.value, pass1.value, initialsInput.value], console.warn)'
>
<button
type=
button
onclick=
'cmxClt.uauth.callDoors("userExists", [cmxClt.uauth.email.value, null, null], console.warn)'
>
test doors register
</button>
<button
type=
button
onclick=
'callDoors("userExists", [email.value, null, null], console.warn)'
>
test doors userExists
test doors userExists
</button>
</button>
</p>
</p>
...
@@ -128,5 +122,5 @@
...
@@ -128,5 +122,5 @@
<!-- our js -->
<!-- our js -->
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared_auth.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared_auth.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_
user
_login_controllers.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_
page
_login_controllers.js') }}"
></script>
{% endblock %}
{% endblock %}
templates/profile.html
View file @
d6e932a7
...
@@ -13,9 +13,22 @@
...
@@ -13,9 +13,22 @@
<div
class=
"spacer col-sm-1 col-md-1"
>
</div>
<div
class=
"spacer col-sm-1 col-md-1"
>
</div>
<div
class=
"my_form_box col-sm-8 col-md-8"
>
<div
class=
"my_form_box col-sm-8 col-md-8"
>
<!-- INTRODUCTION TEXT -->
<!-- ##################### ( PROFILE OVERVIEW ) #################### -->
<div
id=
"intro"
>
<div
id=
"intro"
>
<h2
class=
"oldstyle"
>
Profile
</h2>
<h2
class=
"oldstyle"
>
Your Profile Info
</h2>
<p
class=
"mini-hero"
>
</p>
</div>
<!-- FORM COMPLETING INTRO TEXT -->
<div
id=
"intro"
>
<h2
class=
"oldstyle"
>
Complete your profile
</h2>
<p
class=
"mini-hero"
>
<p
class=
"mini-hero"
>
Take the time to complete your
<strong>
Community Explorer
</strong>
profile to generate better maps of your own socio-semantic network .
Take the time to complete your
<strong>
Community Explorer
</strong>
profile to generate better maps of your own socio-semantic network .
<br/>
<br/>
...
@@ -27,7 +40,6 @@
...
@@ -27,7 +40,6 @@
</p>
</p>
</div>
</div>
<!-- ########################### ( FORM ) ########################## -->
<!-- ########################### ( FORM ) ########################## -->
<form
id=
"comex_profil_form"
enctype=
"multipart/form-data"
<form
id=
"comex_profil_form"
enctype=
"multipart/form-data"
method=
"post"
onsubmit=
"console.info('submitted')"
>
method=
"post"
onsubmit=
"console.info('submitted')"
>
...
@@ -94,10 +106,7 @@
...
@@ -94,10 +106,7 @@
<div
class=
"question"
>
<div
class=
"question"
>
<p
class=
"legend"
>
Your email will also be your login for the ISC services.
</p>
<p
class=
"legend"
>
Your email will also be your login for the ISC services.
</p>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<!-- email validation onblur/onchange
<!-- email validation onblur/onchange is done by cmxClt.uauth in comex_user_shared_auth.js -->
is done by basicEmailValidate
and testDoorsUserExists
in comex_reg_form_controllers.js -->
<label
for=
"email"
class=
"smlabel input-group-addon"
>
* Email
</label>
<label
for=
"email"
class=
"smlabel input-group-addon"
>
* Email
</label>
<input
id=
"email"
name=
"email"
maxlength=
"255"
<input
id=
"email"
name=
"email"
maxlength=
"255"
type=
"text"
class=
"form-control"
placeholder=
"email"
>
type=
"text"
class=
"form-control"
placeholder=
"email"
>
...
@@ -375,5 +384,5 @@
...
@@ -375,5 +384,5 @@
{% block last_imports %}
{% block last_imports %}
<!-- our js -->
<!-- our js -->
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_p
rofile_form
_controllers.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_p
age_profile
_controllers.js') }}"
></script>
{% endblock %}
{% endblock %}
templates/registration_full_form.html
View file @
d6e932a7
...
@@ -57,7 +57,7 @@
...
@@ -57,7 +57,7 @@
</label>
</label>
<input
id=
"first_name"
name=
"first_name"
maxlength=
"30"
<input
id=
"first_name"
name=
"first_name"
maxlength=
"30"
type=
"text"
class=
"form-control"
placeholder=
"prénom"
type=
"text"
class=
"form-control"
placeholder=
"prénom"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<!-- optionnel -->
<!-- optionnel -->
...
@@ -67,7 +67,7 @@
...
@@ -67,7 +67,7 @@
</label>
</label>
<input
id=
"middle_name"
name=
"middle_name"
maxlength=
"30"
<input
id=
"middle_name"
name=
"middle_name"
maxlength=
"30"
type=
"text"
class=
"form-control"
placeholder=
"autres prénoms"
type=
"text"
class=
"form-control"
placeholder=
"autres prénoms"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<div
class=
"question input-group"
>
<div
class=
"question input-group"
>
...
@@ -76,7 +76,7 @@
...
@@ -76,7 +76,7 @@
</label>
</label>
<input
id=
"last_name"
name=
"last_name"
maxlength=
"30"
<input
id=
"last_name"
name=
"last_name"
maxlength=
"30"
type=
"text"
class=
"form-control"
placeholder=
"nom de famille"
type=
"text"
class=
"form-control"
placeholder=
"nom de famille"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<button
class=
"btn btn-xs btn-default operation"
<button
class=
"btn btn-xs btn-default operation"
...
@@ -108,10 +108,7 @@
...
@@ -108,10 +108,7 @@
<div
class=
"question"
>
<div
class=
"question"
>
<p
class=
"legend"
>
Your email will also be your login for the ISC services.
</p>
<p
class=
"legend"
>
Your email will also be your login for the ISC services.
</p>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<!-- email validation onblur/onchange
<!-- email validation onblur/onchange is done by cmxClt.uauth in comex_user_shared_auth.js -->
is done by basicEmailValidate
and testDoorsUserExists
in comex_reg_form_controllers.js -->
<label
for=
"email"
class=
"smlabel input-group-addon"
>
* Email
</label>
<label
for=
"email"
class=
"smlabel input-group-addon"
>
* Email
</label>
<input
id=
"email"
name=
"email"
maxlength=
"255"
<input
id=
"email"
name=
"email"
maxlength=
"255"
type=
"text"
class=
"form-control"
placeholder=
"email"
>
type=
"text"
class=
"form-control"
placeholder=
"email"
>
...
@@ -153,14 +150,14 @@
...
@@ -153,14 +150,14 @@
<label
for=
"hon_title"
class=
"smlabel input-group-addon"
>
Title
</label>
<label
for=
"hon_title"
class=
"smlabel input-group-addon"
>
Title
</label>
<input
id=
"hon_title"
name=
"hon_title"
maxlength=
"30"
<input
id=
"hon_title"
name=
"hon_title"
maxlength=
"30"
type=
"text"
class=
"form-control autocomp"
placeholder=
"titre"
type=
"text"
class=
"form-control autocomp"
placeholder=
"titre"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<div
class=
"question input-group"
>
<div
class=
"question input-group"
>
<label
for=
"position"
class=
"smlabel input-group-addon"
>
* Job Position
</label>
<label
for=
"position"
class=
"smlabel input-group-addon"
>
* Job Position
</label>
<input
id=
"position"
name=
"position"
maxlength=
"30"
<input
id=
"position"
name=
"position"
maxlength=
"30"
type=
"text"
class=
"form-control autocomp"
placeholder=
"titre"
type=
"text"
class=
"form-control autocomp"
placeholder=
"titre"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<div
class=
"question"
>
<div
class=
"question"
>
...
@@ -298,7 +295,7 @@
...
@@ -298,7 +295,7 @@
<textarea
id=
"interests_text"
name=
"interests_text"
maxlength=
"1200"
<textarea
id=
"interests_text"
name=
"interests_text"
maxlength=
"1200"
rows=
"7"
style=
"resize:none"
rows=
"7"
style=
"resize:none"
class=
"form-control"
placeholder=
"If you wish, you may describe here your personal interests."
class=
"form-control"
placeholder=
"If you wish, you may describe here your personal interests."
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
></textarea>
></textarea>
</div>
</div>
<p
class=
"legend"
>
Optional, ~15 lines max (1200 chars)
</p>
<p
class=
"legend"
>
Optional, ~15 lines max (1200 chars)
</p>
...
@@ -398,7 +395,7 @@
...
@@ -398,7 +395,7 @@
<label
for=
"my-captcha"
class=
"smlabel input-group-addon"
>
Code
</label>
<label
for=
"my-captcha"
class=
"smlabel input-group-addon"
>
Code
</label>
<input
id=
"my-captcha"
name=
"my-captcha"
style=
"max-width:60%"
<input
id=
"my-captcha"
name=
"my-captcha"
style=
"max-width:60%"
type=
"text"
class=
"form-control input-lg"
placeholder=
"Enter the 5 letters you see beside =>"
type=
"text"
class=
"form-control input-lg"
placeholder=
"Enter the 5 letters you see beside =>"
onblur=
"
makeBold(this)"
onfocus=
"
makeNormal(this)"
>
onblur=
"
cmxClt.makeBold(this)"
onfocus=
"cmxClt.
makeNormal(this)"
>
</div>
</div>
<!-- == S U B M I T == -->
<!-- == S U B M I T == -->
...
@@ -416,13 +413,13 @@
...
@@ -416,13 +413,13 @@
<!-- FOR DEBUG: test go-between with Doors -->
<!-- FOR DEBUG: test go-between with Doors -->
<!-- <p>
<!-- <p>
<button type=button onclick='c
allDoors("user", [email.value,
pass1.value, initialsInput.value], console.warn)'>
<button type=button onclick='c
mxClt.uauth.callDoors("user", [cmxClt.uauth.email.value, cmxClt.uauth.
pass1.value, initialsInput.value], console.warn)'>
test doors login
test doors login
</button>
</button>
<button type=button onclick='c
allDoors("register", [email.value,
pass1.value, initialsInput.value], console.warn)'>
<button type=button onclick='c
mxClt.uauth.callDoors("register", [cmxClt.uauth.email.value, cmxClt.uauth.
pass1.value, initialsInput.value], console.warn)'>
test doors register
test doors register
</button>
</button>
<button type=button onclick='c
allDoors("userExists", [
email.value, null, null], console.warn)'>
<button type=button onclick='c
mxClt.uauth.callDoors("userExists", [cmxClt.uauth.
email.value, null, null], console.warn)'>
test doors userExists
test doors userExists
</button>
</button>
</p> -->
</p> -->
...
@@ -439,5 +436,5 @@
...
@@ -439,5 +436,5 @@
<!-- our js -->
<!-- our js -->
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared_auth.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_user_shared_auth.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_
user
_reg_controllers.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/comex_
page
_reg_controllers.js') }}"
></script>
{% endblock %}
{% endblock %}
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