Commit f5682b9d authored by Romain Loth's avatar Romain Loth

finally harmonize all date processing with DB type date and timestamp, python...

finally harmonize all date processing with DB type date and timestamp, python conversion to and from + fix job_looking_date pre-selection + add job_looking boolean to DB
parent 3f2554e9
...@@ -19,7 +19,7 @@ CREATE TABLE scholars ( ...@@ -19,7 +19,7 @@ CREATE TABLE scholars (
luid int(15) not null auto_increment unique primary key, luid int(15) not null auto_increment unique primary key,
-- doors uid common to all lab's services -- doors uid common to all lab's services
doors_uid char(36) unique, doors_uid char(36) unique,
last_modified_date char(24) not null, last_modified timestamp,
email varchar(255) not null unique, email varchar(255) not null unique,
country varchar(60) not null, country varchar(60) not null,
first_name varchar(30) not null, first_name varchar(30) not null,
...@@ -31,7 +31,8 @@ CREATE TABLE scholars ( ...@@ -31,7 +31,8 @@ CREATE TABLE scholars (
hon_title varchar(30), -- eg Doctor hon_title varchar(30), -- eg Doctor
interests_text varchar(3500), interests_text varchar(3500),
gender char(1), gender char(1),
job_looking_date char(24), -- null if not looking for a job job_looking boolean,
job_looking_date date,
home_url varchar(180), -- homepage home_url varchar(180), -- homepage
pic_url varchar(180), -- remote pic... (full url) pic_url varchar(180), -- remote pic... (full url)
pic_fname varchar(120), -- ...or locally saved pic (basename) pic_fname varchar(120), -- ...or locally saved pic (basename)
......
...@@ -21,7 +21,7 @@ USER_COLS = [ ...@@ -21,7 +21,7 @@ USER_COLS = [
# NAME, NOT NULL, N or MAXCHARS (if applicable) # NAME, NOT NULL, N or MAXCHARS (if applicable)
("luid", True, 15), ("luid", True, 15),
("doors_uid", False, 36), ("doors_uid", False, 36),
("last_modified_date", True, 24), # ("last_modified", True, None), # autoset on update
("email", True, 255), ("email", True, 255),
("country", True, 60), ("country", True, 60),
("first_name", True, 30), ("first_name", True, 30),
...@@ -33,6 +33,7 @@ USER_COLS = [ ...@@ -33,6 +33,7 @@ USER_COLS = [
("hon_title", False, 30), ("hon_title", False, 30),
("interests_text", False, 1200), ("interests_text", False, 1200),
("gender", False, 1), ("gender", False, 1),
("job_looking", False, 1),
("job_looking_date", False, 24), ("job_looking_date", False, 24),
("home_url", False, 120), ("home_url", False, 120),
("pic_url", False, 120), ("pic_url", False, 120),
...@@ -430,18 +431,17 @@ def get_full_scholar(uid, cmx_db = None): ...@@ -430,18 +431,17 @@ def get_full_scholar(uid, cmx_db = None):
# 'email': 'jfk@usa.com', 'first_name': 'John', 'gender': 'M', # 'email': 'jfk@usa.com', 'first_name': 'John', 'gender': 'M',
# 'home_url': 'http://localhost/regcomex/', 'hon_title': 'Student', # 'home_url': 'http://localhost/regcomex/', 'hon_title': 'Student',
# 'initials': 'JFK', 'interests_text': 'Blablabla', # 'initials': 'JFK', 'interests_text': 'Blablabla',
# 'job_looking_date': '2019_09_28T22:00:00.000Z', # 'job_looking_date': datetime.date(2019, 9, 28),
# 'hashtags': '#eccs15', 'hashtags_nb': 1, # 'hashtags': '#eccs15', 'hashtags_nb': 1,
# 'keywords': 'complex networks,complex systems,text mining,machine learning', 'keywords_nb': 4, # 'keywords': 'complex networks,complex systems,text mining,machine learning', 'keywords_nb': 4,
# 'last_modified_date': '2016-12-07T15:56:09.721Z', # 'last_modified_date': datetime.datetime(2017, 2, 22, 12, 25, 59),
# 'last_name': 'Kennedy', # 'last_name': 'Kennedy',
# 'linked_ids': 'twitter:@jfk,yoyo:42,foobar:XWING', 'linked_ids_nb': 3, # 'linked_ids': 'twitter:@jfk,yoyo:42,foobar:XWING', 'linked_ids_nb': 3,
# 'middle_name': 'Fitzgerald', # 'middle_name': 'Fitzgerald',
# 'org': 'Centre National de la Recherche Scientifique (CNRS)', # 'org': 'Centre National de la Recherche Scientifique (CNRS)',
# 'org_city': 'Paris', 'org_type': 'public R&D org', # 'org_city': 'Paris', 'org_type': 'public R&D org',
# 'pic_fname': '12345.jpg', 'pic_url': None, 'position': 'Research Fellow', # 'pic_fname': '12345.jpg', 'pic_url': None, 'position': 'Research Fellow',
# 'record_status': None, 'team_lab': 'ISCPIF'} # 'record_status': 'legacy', 'valid_date': datetime.date(2017, 5, 22)}
# post-treatments # post-treatments
# --------------- # ---------------
......
...@@ -25,7 +25,7 @@ __status__ = "Dev" ...@@ -25,7 +25,7 @@ __status__ = "Dev"
# ============== imports ============== # ============== imports ==============
from re import sub from re import sub, match
from os import path from os import path
from json import dumps from json import dumps
from datetime import timedelta from datetime import timedelta
...@@ -82,10 +82,9 @@ login_manager.init_app(app) ...@@ -82,10 +82,9 @@ login_manager.init_app(app)
# all inputs as they are declared in form, as a couple # all inputs as they are declared in form, as a couple
SOURCE_FIELDS = [ SOURCE_FIELDS = [
# NAME, SANITIZE? Specificity # NAME, SANITIZE? sanitizing specificity
("luid", False, None), ("luid", False, None),
("doors_uid", False, None), ("doors_uid", False, None),
("last_modified_date", False, None), # TODO use stamp
("email", True, None), ("email", True, None),
("country", True, None), ("country", True, None),
("first_name", True, None), ("first_name", True, None),
...@@ -98,7 +97,8 @@ SOURCE_FIELDS = [ ...@@ -98,7 +97,8 @@ SOURCE_FIELDS = [
("hon_title", True, None), ("hon_title", True, None),
("interests_text", True, None), ("interests_text", True, None),
("gender", False, None), # M|F ("gender", False, None), # M|F
("job_looking_date", True, "sdate"), # def null: not looking for a job ("job_looking", True, "sbool"),
("job_looking_date", True, "sdate"),
("home_url", True, "surl"), # scholar's homepage ("home_url", True, "surl"), # scholar's homepage
("pic_url", True, "surl"), ("pic_url", True, "surl"),
("pic_file", False, None), # saved separately ("pic_file", False, None), # saved separately
...@@ -863,6 +863,14 @@ def sanitize(value, specific_type=None): ...@@ -863,6 +863,14 @@ def sanitize(value, specific_type=None):
if not specific_type: if not specific_type:
san_val = sub(r'[^\w@\.:,()# -]', '_', clean_val) san_val = sub(r'[^\w@\.:,()# -]', '_', clean_val)
elif specific_type == "sbool":
# DB uses int(0) or int(1)
if match('^[01]$',clean_val):
san_val = int(clean_val)
else:
san_val = 0
# NB san_val_bool = bool(san_val)
elif specific_type == "surl": elif specific_type == "surl":
san_val = sub(r'[^\w@\.: -/]', '_', clean_val) san_val = sub(r'[^\w@\.: -/]', '_', clean_val)
elif specific_type == "sdate": elif specific_type == "sdate":
......
...@@ -9,7 +9,7 @@ __copyright__ = "Copyright 2016 ISCPIF-CNRS" ...@@ -9,7 +9,7 @@ __copyright__ = "Copyright 2016 ISCPIF-CNRS"
__email__ = "romain.loth@iscpif.fr" __email__ = "romain.loth@iscpif.fr"
from json import dumps, loads from json import dumps, loads
from datetime import date from datetime import date, datetime
from flask_login import LoginManager from flask_login import LoginManager
from re import match from re import match
...@@ -52,16 +52,28 @@ def jsonize_uinfo(uinfo_dict): ...@@ -52,16 +52,28 @@ def jsonize_uinfo(uinfo_dict):
Dumps user_info in json format for client-side needs Dumps user_info in json format for client-side needs
""" """
# most fields are already serializable serializable_dict = {}
serializable_dict = {k:v for k,v in uinfo_dict.items() if k not in ['valid_date']} for k,v in uinfo_dict.items():
mlog('DEBUG', 'user: jsonize_uinfo k=v', k, '=' , v)
if 'valid_date' in uinfo_dict and uinfo_dict['valid_date'] is not None: # most values are already serializable
d = uinfo_dict['valid_date'] if ( v is None
if type(d) != date: or k not in [ 'last_modified',
raise TypeError("Incorrect type for valid_date: '%s' instead of 'date'" % type(d)) 'valid_date',
'job_looking_date' ]
):
serializable_dict[k] = v
# when k is a non-empty date field
else: else:
# "YYYY-MM-DD" # if type(v) != date or type(v) != datetime:
serializable_dict['valid_date'] = d.isoformat() if type(v) not in [date, datetime]:
raise TypeError("Incorrect type for %s field: /%s/ instead of date or datetime" % (k, type(v)))
else:
print("toto")
serializable_dict[k] = v.isoformat()
# date "YYYY-MM-DD"
# datetime "YYYY-MM-DDTHH:MM:SS"
return dumps(serializable_dict) return dumps(serializable_dict)
......
...@@ -12,7 +12,7 @@ CREATE TABLE scholars ( ...@@ -12,7 +12,7 @@ CREATE TABLE scholars (
luid int(15) not null auto_increment unique primary key, luid int(15) not null auto_increment unique primary key,
-- doors uid common to all lab's services -- doors uid common to all lab's services
doors_uid char(36) unique, doors_uid char(36) unique,
last_modified_date char(24) not null, last_modified timestamp,
email varchar(255) not null unique, email varchar(255) not null unique,
country varchar(60) not null, country varchar(60) not null,
first_name varchar(30) not null, first_name varchar(30) not null,
...@@ -24,7 +24,8 @@ CREATE TABLE scholars ( ...@@ -24,7 +24,8 @@ CREATE TABLE scholars (
hon_title varchar(30), -- eg Doctor hon_title varchar(30), -- eg Doctor
interests_text varchar(3500), interests_text varchar(3500),
gender char(1), gender char(1),
job_looking_date char(24), -- null if not looking for a job job_looking boolean,
job_looking_date date,
home_url varchar(180), -- homepage home_url varchar(180), -- homepage
pic_url varchar(180), -- remote pic... (full url) pic_url varchar(180), -- remote pic... (full url)
pic_fname varchar(120), -- ...or locally saved pic (basename) pic_fname varchar(120), -- ...or locally saved pic (basename)
......
...@@ -121,11 +121,7 @@ function completionAsYouGo() { ...@@ -121,11 +121,7 @@ function completionAsYouGo() {
cmxClt.uform.simpleValidateAndMessage(theUForm, diagnosticParams) cmxClt.uform.simpleValidateAndMessage(theUForm, diagnosticParams)
// stamp => #last_modified_date // timestamp is done server-side
cmxClt.uform.stampTime(theUForm)
// debug
// console.log("timestamp:", cmxClt.uform.timestamp.value)
} }
// run first check on existing profile data pre-filled by the template // run first check on existing profile data pre-filled by the template
......
/** /**
* @fileoverview * @fileoverview
* Validates the comex (communityexplorer.org) registration form * Validates the comex (communityexplorer.org) registration form
* + adds a timestamp in input#last_modified_date
* + adds autocompletes * + adds autocompletes
* + prepares DB save into cmxClt.COLS * + prepares DB save into cmxClt.COLS
* *
...@@ -67,8 +66,6 @@ function testAsYouGo() { ...@@ -67,8 +66,6 @@ function testAsYouGo() {
else { else {
regfo.elSubmitBtn.disabled = true regfo.elSubmitBtn.disabled = true
} }
// stamp => #last_modified_date
cmxClt.uform.stampTime(regfo)
} }
var teamCityDivStyle = document.getElementById('team_city_div').style var teamCityDivStyle = document.getElementById('team_city_div').style
......
...@@ -43,9 +43,8 @@ var cmxClt = (function() { ...@@ -43,9 +43,8 @@ var cmxClt = (function() {
// ==> *hashtags* table // ==> *hashtags* table
["doors_uid", true, "auto" , "t", null], ["doors_uid", true, "auto" , "t", null],
["last_modified_date", true, "auto" , "d", null],
["hon_title", false, "plsfill", "t", "basic_infos"],
["email", true, "plsfill", "t", "login_infos"], ["email", true, "plsfill", "t", "login_infos"],
["hon_title", false, "plsfill", "t", "basic_infos"],
["first_name", true, "plsfill", "t", "basic_infos"], ["first_name", true, "plsfill", "t", "basic_infos"],
["middle_name", false, "pref", "t", "basic_infos"], ["middle_name", false, "pref", "t", "basic_infos"],
["last_name", true, "plsfill", "t", "basic_infos"], ["last_name", true, "plsfill", "t", "basic_infos"],
...@@ -54,6 +53,7 @@ var cmxClt = (function() { ...@@ -54,6 +53,7 @@ var cmxClt = (function() {
["position", true, "plsfill", "t", "map_infos"], ["position", true, "plsfill", "t", "map_infos"],
["interests_text", false, "pref", "t", "other_infos"], ["interests_text", false, "pref", "t", "other_infos"],
["gender", false, "plsfill", "m", "other_infos"], ["gender", false, "plsfill", "m", "other_infos"],
["job_looking", false, "pref" , "m", "map_infos"],
["job_looking_date", false, "pref" , "d", "map_infos"], ["job_looking_date", false, "pref" , "d", "map_infos"],
["home_url", false, "plsfill", "t", "other_infos"], ["home_url", false, "plsfill", "t", "other_infos"],
["pic_url", false, "pref" , "t", "other_infos"], ["pic_url", false, "pref" , "t", "other_infos"],
...@@ -338,7 +338,7 @@ var cmxClt = (function() { ...@@ -338,7 +338,7 @@ var cmxClt = (function() {
var mainMessageId, timestampId, buttonId var mainMessageId, timestampId, buttonId
mainMessageId = fParams.mainMessageId || 'main_message' mainMessageId = fParams.mainMessageId || 'main_message'
timestampId = fParams.timestampId || 'last_modified_date' timestampId = fParams.timestampId || 'form_timestamp'
submitBtnId = fParams.submitBtnId || 'form_submit' submitBtnId = fParams.submitBtnId || 'form_submit'
myUform.elMainMessage = document.getElementById(mainMessageId) myUform.elMainMessage = document.getElementById(mainMessageId)
...@@ -511,8 +511,7 @@ var cmxClt = (function() { ...@@ -511,8 +511,7 @@ var cmxClt = (function() {
otherMissingFields ] otherMissingFields ]
} }
// simple timestamp on #last_modified_date element // simple timestamp if needed
// ------------------
cC.uform.stampTime = function (aUForm) { cC.uform.stampTime = function (aUForm) {
var now = new Date() var now = new Date()
aUForm.elTimestamp.value = now.toISOString() aUForm.elTimestamp.value = now.toISOString()
......
...@@ -297,7 +297,7 @@ ...@@ -297,7 +297,7 @@
{% endif %} {% endif %}
{% if return_user.info.job_looking_date or return_user.info.hashtags %} {% if return_user.info.job_looking or return_user.info.hashtags %}
<h3 class="formcat"> About your future activities </h3> <h3 class="formcat"> About your future activities </h3>
...@@ -306,11 +306,11 @@ ...@@ -306,11 +306,11 @@
{% if return_user.info.job_looking %} {% if return_user.info.job_looking %}
<div class="question"> <div class="question">
<div class="input-group"> <div class="input-group">
<label for="job_bool" class="smlabel input-group-addon">Job offers</label> <label for="job_looking" class="smlabel input-group-addon">Job offers</label>
<select disabled id="job_bool" name="job_bool" <select disabled id="job_looking" name="job_looking"
class="custom-select form-control"> class="custom-select form-control">
<option selected value="No">No</option> <option selected value="0">No</option>
<option value="Yes">Yes</option> <option value="1">Yes</option>
</select> </select>
</div> </div>
</div> </div>
......
...@@ -311,11 +311,11 @@ ...@@ -311,11 +311,11 @@
<div class="question"> <div class="question">
<div class="input-group"> <div class="input-group">
<label for="job_bool" class="smlabel input-group-addon">Soon on the job market? <br/><small>and do you want our job contacts?</small></label> <label for="job_looking" class="smlabel input-group-addon">Soon on the job market? <br/><small>and do you want our job contacts?</small></label>
<select id="job_bool" name="job_bool" <select id="job_looking" name="job_looking"
class="custom-select form-control"> class="custom-select form-control">
<option selected value="No">No</option> <option selected value="0">No</option>
<option value="Yes">Yes</option> <option value="1">Yes</option>
</select> </select>
</div> </div>
<!-- job_looking_date_div <=> only if previous choice == Yes --> <!-- job_looking_date_div <=> only if previous choice == Yes -->
...@@ -534,11 +534,6 @@ ...@@ -534,11 +534,6 @@
</div> </div>
<!-- hidden input for modification date -->
<input id="last_modified_date" name="last_modified_date" type="text" hidden>
</input>
<!-- hidden input for main user id --> <!-- hidden input for main user id -->
<input id="luid" name="luid" type="text" hidden <input id="luid" name="luid" type="text" hidden
value="{{ current_user.uid | safe }}"> value="{{ current_user.uid | safe }}">
......
...@@ -182,10 +182,6 @@ ...@@ -182,10 +182,6 @@
<input id="doors_connect" name="doors_connect" type="text" hidden value="{{doors_connect|safe}}"> <input id="doors_connect" name="doors_connect" type="text" hidden value="{{doors_connect|safe}}">
</input> </input>
<!-- hidden input for modification date -->
<input id="last_modified_date" name="last_modified_date" type="text" hidden>
</input>
<!-- hidden input for doors user id --> <!-- hidden input for doors user id -->
<input id="doors_uid" name="doors_uid" type="text" hidden> <input id="doors_uid" name="doors_uid" type="text" hidden>
</input> </input>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment