Skip to content

Commit

Permalink
#10 Multiple subtemplates select
Browse files Browse the repository at this point in the history
template creators can now associate multiple templates with the same input field. End-users have to choose one of them through a select (dropdown) element.
  • Loading branch information
Sebastiano-G committed Jul 9, 2024
1 parent 7321f5b commit cc3b27d
Show file tree
Hide file tree
Showing 12 changed files with 592 additions and 5,017 deletions.
4 changes: 2 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,13 @@ def GET(self, res_name):
# importable templates
u.check_ask_class()
ask_form = u.change_template_names()
templates = forms.get_form(ask_form,True).inputs[0]
templates = ask_form[0]['values']

return render.template(f=fields,user=session['username'],
res_type=res_type,res_name=res_full_name,
res_status=res_status,is_git_auth=is_git_auth,
project=conf.myProject,skos_vocabs=skos_file,
templates=templates,)
templates=templates)

def POST(self, res_name):
""" Save the form template for data entry and reload config files
Expand Down
71 changes: 45 additions & 26 deletions forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def parse_config_variables(text:str, conf):
text = text.replace(k, v)
return text

def get_form(json_form, from_dict=False, subtemplate=False):
def get_form(json_form, from_dict=False, supertemplate=False):
""" read config in 'template-(.*).json' and return a webpy form """
import io
if from_dict == False:
Expand Down Expand Up @@ -88,6 +88,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
default = field['defaultvalue'] if 'defaultvalue' in field else ''
# dropdown
dropdown_values = [(k,v) for k,v in field['values'].items()] if 'values' in field else None
# subtemplate
data_supertemplate = supertemplate if supertemplate else 'None'

# Text box
if field['type'] == 'Textbox' and field['value'] == 'Literal':
Expand All @@ -104,7 +106,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
lang=conf.mainLang,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class) , )
data_class=res_class,
data_supertemplate=data_supertemplate) , )
else:
params = params + (form.Textbox(myid,
type='text',
Expand All @@ -117,7 +120,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
lang=conf.mainLang,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

# Entities, SKOS thesauri, links
if field['type'] in ['Skos', 'WebsitePreview'] or (field['type'] == 'Textbox' and field['value'] in ['URL', 'URI', 'Place']):
Expand All @@ -130,7 +134,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
value=default,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

# Multimedia Link
if field['type'] == 'Multimedia':
Expand All @@ -143,7 +148,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
value=default,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class) , )
data_class=res_class,
data_supertemplate=data_supertemplate) , )

# Text box
if field['type'] == 'Textarea':
Expand All @@ -157,7 +163,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
lang=conf.mainLang,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

if field['type'] == 'Date':
if field['calendar'] == 'Month':
Expand All @@ -168,7 +175,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
class_= classes,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )
elif field['calendar'] == 'Day':
params = params + (form.Date(myid,
description = description,
Expand All @@ -177,7 +185,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
class_= classes,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )
elif field['calendar'] == 'Year':
params = params + (form.Textbox(myid,
description = description,
Expand All @@ -187,7 +196,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
value=default,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

if field['type'] == 'Dropdown':
params = params + (form.Dropdown(myid,
Expand All @@ -199,7 +209,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
class_= classes,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

if field['type'] == 'Checkbox':
prepend_title = '<section class="checkbox_group_label label col-12">'+prepend+"\n"+'<span class="title">'+description+'</span></section>'
Expand All @@ -213,7 +224,8 @@ def get_form(json_form, from_dict=False, subtemplate=False):
checked=False,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

for value in dropdown_values[1:]:
i += 1
Expand All @@ -226,25 +238,32 @@ def get_form(json_form, from_dict=False, subtemplate=False):
checked=False,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class), )
data_class=res_class,
data_supertemplate=data_supertemplate), )

# Subtemplate
if field['type'] == 'Subtemplate':
resource_class = "; ".join([t["type"] for t in tpl_list if t["template"] == field['import_subtemplate']][0])
params = params + (form.Textbox(myid,
description = description,
id=myid,
placeholder=placeholder,
pre = prepend,
class_= classes,
value=default,
data_mandatory = mandatory,
data_class=res_class,
data_property = rdf_property,
data_subtemplate = resource_class,
data_subtemplateID = field['import_subtemplate']), ) + get_form(field['import_subtemplate'], subtemplate=True)
dropdown_templates = []
for imported_template in field['import_subtemplate']:
template_dict = next(t for t in tpl_list if t["template"] == imported_template)
resource_class = template_dict['type']
resource_name = template_dict['name']
dropdown_templates.append((resource_class,resource_name))
params = params + get_form(imported_template, supertemplate=myid)
params = params + (form.Dropdown(myid,
description = description,
args=dropdown_templates,
placeholder=placeholder,
id=myid,
pre = prepend,
class_= classes,
data_property = rdf_property,
data_mandatory = mandatory,
data_class=res_class,
data_subtemplate=myid,
data_supertemplate=data_supertemplate), )

if subtemplate:
if supertemplate:
return params
else:
myform = form.Form(*params)
Expand Down
45 changes: 18 additions & 27 deletions mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def getRightURIbase(value):

def inputToRDF(recordData, userID, stage, graphToClear=None,tpl_form=None):
""" transform input data into RDF, upload data to the triplestore, dump data locally """
print("RECORD DATA:", recordData)
print("RECORD DATA:", recordData, "TEMPLATE:", tpl_form)

# MAPPING FORM / PROPERTIES
if tpl_form:
Expand Down Expand Up @@ -191,15 +191,13 @@ def inputToRDF(recordData, userID, stage, graphToClear=None,tpl_form=None):
wd.add(( URIRef(base+graph_name), URIRef(field['property']), Literal(value) ))
# multiple-values fields
elif isinstance(value,dict):
print("Checkpoint:", value, field['id'])
if value['type'] == 'URL': #url
for URL in value['results']:
if URL[1] != "":
valueURL = URL[1] if URL[1].startswith("http") else "http://" + URL[1]
wd.add(( URIRef(base+graph_name), URIRef(field['property']), URIRef(valueURL) ))
elif value['type'] == 'URI': #object properties
rdf_property = SKOS.prefLabel if field['type'] == 'Skos' else RDFS.label
print(field['type'], rdf_property)
for entity in value['results']:
entityURI = getRightURIbase(entity[0]) # Wikidata or new entity
wd.add(( URIRef(base+graph_name), URIRef(field['property']), URIRef(entityURI) ))
Expand Down Expand Up @@ -277,7 +275,6 @@ def inputToRDF(recordData, userID, stage, graphToClear=None,tpl_form=None):
server.update('load <file:///'+dir_path+'/records/'+recordID+"-extraction-"+extraction_num+'.ttl> into graph <'+base+extraction_graph_name+'/>')
# SUBTEMPLATE
elif field['type']=="Subtemplate" and field['id'] in recordData:
print(recordData[field['id']])
if type(recordData[field['id']]) != type([]) and field['id']+"-subrecords" in recordData:
# get the list of subrecords associated to a 'Subtemplate' field
subrecords = recordData[field['id']+"-subrecords"].split(",") if recordData[field['id']+"-subrecords"] != "" else []
Expand All @@ -287,13 +284,12 @@ def inputToRDF(recordData, userID, stage, graphToClear=None,tpl_form=None):
else:
# process a new subrecord, send its data to the triplestore, and link it to the main record
subrecord_id = subrecord
subrecord_template = field['import_subtemplate']
allow_data_reuse = fields if 'dataReuse' in field and field['dataReuse']=='allowDataReuse' else False
processed_subrecord = process_new_subrecord(recordData,userID,stage,subrecord_template,subrecord,supertemplate=None,allow_data_reuse=allow_data_reuse)
processed_subrecord = process_new_subrecord(recordData,userID,stage,subrecord,supertemplate=None,allow_data_reuse=allow_data_reuse)
subrecord_id, retrieved_label = processed_subrecord
wd.add(( URIRef(base+graph_name), URIRef(field['property']), URIRef(base+subrecord_id) ))
wd.add(( URIRef(base+subrecord_id), RDFS.label, Literal(retrieved_label, datatype="http://www.w3.org/2001/XMLSchema#string")))
else:
elif type(recordData[field['id']]) == type([]):
for entity in recordData[field['id']]:
entity_URI, entity_label = entity
wd.add(( URIRef(base+graph_name), URIRef(field['property']), URIRef(base+entity_URI) ))
Expand All @@ -317,13 +313,22 @@ def inputToRDF(recordData, userID, stage, graphToClear=None,tpl_form=None):

return 'records/'+recordID+'.ttl'

def process_new_subrecord(data, userID, stage, sub_tpl, subrecord_id, supertemplate=None, allow_data_reuse=False):
def process_new_subrecord(data, userID, stage, subrecord_id, supertemplate=None, allow_data_reuse=False):
# prepare a new dict to store data of subrecord-x
new_record_data = {'recordID': subrecord_id,}
label = 'No Label!'
with open(sub_tpl) as fields:

# retrieve the template path based on selected class
subrecord_class = data[subrecord_id+'-class']
with open(TEMPLATE_LIST) as templates:
templates_list = json.load(templates)
subtemplate_path = next(t["template"] for t in templates_list if t["type"]==sorted(subrecord_class.split(", ")))

# access the template file
with open(subtemplate_path) as fields:
subtemplate = json.load(fields)
subtemplate = sorted(subtemplate, key=lambda x: x['type'] == 'subtemplate')

# process the input data related to subrecord-x
for subtemplate_field in subtemplate:
if subtemplate_field['hidden'] == 'False':
Expand All @@ -336,13 +341,12 @@ def process_new_subrecord(data, userID, stage, sub_tpl, subrecord_id, supertempl
# Process inner-subrecords and retrieve their ids,labels in order to provide a link to them in the upper-level subrecord
if key+"-subrecords" in data:
new_record_data[subfield_id] = [[]]
inner_subtemplate = subtemplate_field['import_subtemplate']
data_reuse = subtemplate if 'dataReuse' in subtemplate_field and subtemplate_field['dataReuse']=='allowDataReuse' else False
for inner_subrecord in data[key+"-subrecords"].split(","):
if ";" in inner_subrecord:
processed_subrecord = inner_subrecord.split(";",1)
else:
processed_subrecord = process_new_subrecord(data,userID,stage,inner_subtemplate,inner_subrecord,subrecord_id,data_reuse)
processed_subrecord = process_new_subrecord(data,userID,stage,inner_subrecord,subrecord_id,data_reuse)
new_record_data[subfield_id][0].append(processed_subrecord) # store the id,label pair inside the subrecord dict

# Date
Expand Down Expand Up @@ -403,28 +407,15 @@ def process_new_subrecord(data, userID, stage, sub_tpl, subrecord_id, supertempl
label_input_field = upper_level_field_id+"_"+main_lang+"_"+ supertemplate if supertemplate else upper_level_field_id+'_'+main_lang
with open(TEMPLATE_LIST,'r') as tpl_file:
tpl_list = json.load(tpl_file)
disambiguation_label = [t['name'] for t in tpl_list if t['template']==sub_tpl][0]
disambiguation_label = [t['name'] for t in tpl_list if t['template']==subtemplate_path][0]
label = data[label_input_field] + " - " + disambiguation_label if label_input_field in data else "No label"
new_label_input_id = subfield_id + '_' + main_lang
new_record_data[new_label_input_id] = label





print("#### DATA:\n",new_record_data)
store_data = storify(new_record_data)
grapht_to_clear = None if stage == 'not modified' else base+subrecord_id+"/"
inputToRDF(store_data,userID,stage,graphToClear=grapht_to_clear,tpl_form=sub_tpl)
inputToRDF(store_data,userID,stage,graphToClear=grapht_to_clear,tpl_form=subtemplate_path)
result = [subrecord_id,label]
return result

""" def find_label(tpl):
# Retrieve the field associated with the Primary Key (i.e., the label) of the Record
with open(tpl) as tpl_file:
tpl_fields = json.load(tpl_file)
fields_id = [field['id'] for field in tpl_fields if field['disambiguate'] == "True"]
label_field_id = fields_id[0] if fields_id != [] else False
# TODO: add a mechanism to handle potential Templates without a Primary Key in case it's needed
return label_field_id """
return result
8 changes: 1 addition & 7 deletions static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,6 @@ table.url-table i, table.extraction-table i {
text-transform: uppercase;
color: grey;
font-size: 0.9em !important;
display: inline-block;
}

.subtemplateField:last-child {
Expand Down Expand Up @@ -1326,11 +1325,6 @@ table.url-table i, table.extraction-table i {
background-color: silver;
}

.inverses .section-subtitle {
font-weight: 400;
color: grey;
}

.info-bio {
margin-top: 2em;
}
Expand Down Expand Up @@ -2901,7 +2895,7 @@ h4.subrecord-title.closed-title {
}

/* extra */
.material-icons, .fa-plus-circle, .fa-eye, .fa-trash{color: rgba(100,23,180,1); cursor: pointer;}
.material-icons, .fa-plus-circle, .fa-eye, .fa-trash, .fa-external-link-alt{color: rgba(100,23,180,1); cursor: pointer;}
.material-icons {font-size: 1.5em;}
.link_btn, .btn {white-space: nowrap; font-weight: 500;}
.add_fields .link_btn {display: inline-block; margin-bottom: 8px}
Expand Down
Loading

0 comments on commit cc3b27d

Please sign in to comment.