Skip to content

Commit fd7c459

Browse files
Merge branch 'master' into 189-Cleanup-CSS-Foundation
2 parents d951b82 + 855fbb6 commit fd7c459

22 files changed

+2773
-2247
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ env/
1919
.hermes/process/hermes.json
2020
hermes.log
2121
hermes.toml
22+
23+
*.sln
24+
*.pyproj
25+
*.user

docs/field_types_in_curation.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ SMECS supports typical field types in the curation interface. The following type
1919
* Cardinality: 1
2020
* Type: string
2121

22+
### Big Field
23+
* tag: big_field
24+
* full page field for longer text with multiple rows
25+
* Typical used for:
26+
* Cardinality: 1
27+
* Type: string
28+
2229
### Dropdown
2330
* tag: dropdown
2431
* full page dropdown field

meta_creator/hermes_process.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def run_hermes_commands(url, token=None):
3434
print(error_msg)
3535
errors.append(error_msg)
3636
return {
37+
'metadata': {"codeRepository": url },
3738
'success': False,
3839
'errors': errors,
3940
'warnings': warnings
@@ -71,15 +72,32 @@ def run_hermes_commands(url, token=None):
7172
# Step 3: Run hermes process
7273
print("Running hermes process...")
7374
process_command = subprocess.run(['hermes', 'process'], capture_output=True, text=True, cwd=base_directory)
75+
76+
## Check result and create correct path
7477
if process_command.returncode != 0:
7578
error_msg = f"Error in hermes process: {process_command.stderr}"
7679
print(error_msg)
7780
errors.append(error_msg)
78-
return {
79-
'success': False,
80-
'errors': errors,
81-
'warnings': warnings
82-
}
81+
file_names = ["codemeta.json", "cff.json", "githublab.json"]
82+
for file_name in file_names:
83+
file_path = os.path.join(base_directory, ".hermes", "harvest", file_name)
84+
os.remove(file_path)
85+
print(f"Removed {file_path}")
86+
process_command = subprocess.run(['hermes', 'process'], capture_output=True, text=True, cwd=base_directory)
87+
88+
if process_command.returncode == 0:
89+
break
90+
91+
if process_command.returncode != 0:
92+
errors.append(error_msg)
93+
return {
94+
'metadata': {"codeRepository": url },
95+
'success': False,
96+
'errors': errors,
97+
'warnings': warnings
98+
}
99+
else:
100+
errors = []
83101

84102
# Construct the path to hermes.json
85103
hermes_json_path = os.path.join(base_directory, ".hermes", "process", "hermes.json")

meta_creator/init_curated_metadata.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ def load_description_dict_from_schema(schema: dict) -> dict[str, str]:
5656
if desc and key not in description_dict:
5757
description_dict[key] = desc
5858

59+
## Define descriptions for tabs
60+
description_dict['GeneralInformation'] = "This section gives general information about the software."
61+
description_dict['Provenance'] = "This section describes the creation history of the software."
62+
description_dict['RelatedPersons'] = "This section lists all relevant persons who are connected to the software."
63+
description_dict['TechnicalAspects'] = "This section describes the technical aspects of the software."
64+
5965
return description_dict
6066

6167
# Define required field_type per element
@@ -94,15 +100,16 @@ def define_field_type(schema: dict, types: dict, array = False) -> dict[str, str
94100
else:
95101
type_dict[key] = "single_input_object"
96102
elif value.get("type") == "string":
97-
type_dict[key] = "long_field" if key == "description" else "single_inputs"
103+
if key == "description":
104+
type_dict[key] = "big_field"
105+
elif key == "abstract":
106+
type_dict[key] = "long_field"
107+
else:
108+
type_dict[key] = "single_inputs"
98109
elif value.get("type") == "array":
99110
items = value.get("items", {}) # Safely get "items" or default to an empty dict
100-
if "enum" in items:
101-
enum_values = items.get("enum")
102-
if enum_values is not None and len(enum_values) > 10:
103-
type_dict[key] = "tagging_autocomplete"
104-
else:
105-
type_dict[key] = "tagging_dropdown"
111+
if "enum" in items:
112+
type_dict[key] = "tagging_autocomplete"
106113
elif items.get("type") == "string":
107114
type_dict[key] = "tagging"
108115
elif "$ref" in items:
@@ -205,7 +212,7 @@ def create_empty_metadata(schema: dict) -> dict[str, dict[str, str]]:
205212
properties_list = load_properties_list_from_schema(schema)
206213
metadata = {"GeneralInformation": create_empty_metadata_dict_from_properties_list(properties_list, schema, "name", "copyrightHolder"),
207214
"Provenance": create_empty_metadata_dict_from_properties_list(properties_list, schema, "softwareVersion", "funding"),
208-
"Contributors": create_empty_metadata_dict_from_properties_list(properties_list, schema, "contributor", "maintainer"),
215+
"RelatedPersons": create_empty_metadata_dict_from_properties_list(properties_list, schema, "contributor", "maintainer"),
209216
"TechnicalAspects": create_empty_metadata_dict_from_properties_list(properties_list, schema, "downloadUrl", "targetProduct")
210217
}
211218
return metadata

meta_creator/templates/meta_creator/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ <h6 class="custom-tooltip">
6464
type="text"
6565
id="token_input"
6666
name="personal_token_key"
67-
placeholder="Enter your personal token key from GitHub"
67+
placeholder="(Optional) Enter your personal token key from GitHub or GitLab"
6868
value="" />
6969
{% if error_message_token %}
7070
<span id="token_error" class="error_message"
@@ -80,7 +80,9 @@ <h6 class="custom-tooltip">
8080
</button>
8181
</form>
8282
</div>
83+
8384
</div>
85+
8486
</div>
8587

8688
<!-- Pop-up modal overlay for loading spinner -->

meta_creator/templates/meta_creator/showdata.html

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
{% csrf_token %}
1414
<h4>Metdata in JSON format</h4>
1515

16+
1617
<div class="metadata-container">
1718
<div class="left">
1819
<span id="actionFeedback" class="feedback"></span>
@@ -47,11 +48,11 @@ <h4>Metdata in JSON format</h4>
4748
<div class="row">
4849
<div class="col-3 color-code">
4950
<span class="red"></span>
50-
<span class="fs-6">Missing required or recommended metadata</span>
51+
<span class="fs-6">Missing required metadata</span>
5152
</div>
5253
<div class="col-3 color-code">
5354
<span class="yellow"></span>
54-
<span class="fs-6">Better to curate the metadata</span>
55+
<span class="fs-6">Missing recommended metadata</span>
5556
</div>
5657
<div class="col-3 color-code">
5758
<span class="symbol"></span>
@@ -102,10 +103,19 @@ <h1>Extra Hints!</h1>
102103
{% with unique_tab=type_metadata|all_types_same:metadata_dict %}
103104
<!-- {{tab_name}}_info -->
104105
{% if forloop.first %}
105-
<div id="{{ tab_name }}" class="tab active">
106+
<div id="{{ tab_name }}" class="tab active{% if unique_tab %} unique-tab{% endif %}">
106107
{% else %}
107-
<div id="{{ tab_name }}" class="tab">
108+
<div id="{{ tab_name }}" class="tab{% if unique_tab %} unique-tab{% endif %}">
108109
{% endif %}
110+
{% if unique_tab %}
111+
<div class="unique-tab-inner">
112+
{% endif %}
113+
114+
{% if description_metadata|get:tab_name %}
115+
<div class="tab-description">
116+
{{ description_metadata|get:tab_name }}
117+
</div>
118+
{% endif %}
109119
{% for key, value in metadata_dict.items %}
110120
<div class="form-group">
111121
{% if type_metadata|get:key == "hidden" %}
@@ -255,6 +265,18 @@ <h1>Extra Hints!</h1>
255265
</div>
256266
<input title="{{ value }}" id="{{ key }}" name="{{ key }}" type="text" value="{{ value }}"><br>
257267
</div>
268+
{% elif type_metadata|get:key == "big_field" %}
269+
<!-- Single input and long field element -->
270+
<div class={{type_metadata|get:key}}>
271+
<label for="{{ key }}">{{ key|camel_to_spaces_lower }}</label>
272+
<div class="custom-tooltip-metadata">
273+
<span class="tooltip-text-metadata">
274+
{% if key in description_metadata %}{{ description_metadata|get:key }}{% endif %}
275+
</span>
276+
<i class="fa fa-info-circle" aria-hidden="true"></i>
277+
</div>
278+
<textarea title="{{ value }}" id="{{ key }}" name="{{ key }}" rows="3">{{ value }}</textarea><br>
279+
</div>
258280
{% elif forloop.first or not unique_tab %}
259281
<!-- small_table -->
260282
<div class="long_field">
@@ -416,14 +438,18 @@ <h1>Extra Hints!</h1>
416438
</div>
417439
</div>
418440
<!-- tab_contributors -->
441+
{% if unique_tab %}
442+
</div>
443+
{% endif %}
419444
{% endwith %}
420445
{% endfor %}
421446
<!-- </form> -->
447+
422448
</div>
423-
</div>
449+
450+
424451
</form>
425452
</div>
426-
427453
</div><!-- main div -->
428454
</div><!-- whole-extraction-page -->
429455
{% endblock content %}

meta_creator/validate_jsonLD.py

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,36 @@ def validate_codemeta(json):
1111
print("Not a JSON-LD file")
1212
return False
1313

14-
if context == "https://doi.org/10.5063/schema/codemeta-2.0":
14+
# if context == "https://doi.org/10.5063/schema/codemeta-2.0":
15+
if context == "https://w3id.org/codemeta/3.0":
1516
# Temp replacement for https resolution issues for schema.org
16-
context = "https://raw.githubusercontent.com/caltechlibrary/convert_codemeta/main/codemeta.jsonld"
17+
# context = "https://raw.githubusercontent.com/caltechlibrary/convert_codemeta/main/codemeta.jsonld"
18+
context = "https://raw.githubusercontent.com/codemeta/codemeta/3.0/codemeta.jsonld"
1719
json["@context"] = context
18-
cp = copy.deepcopy(json)
19-
# Expand and contract to check mapping
20-
cp = jsonld.expand(cp)
21-
cp = jsonld.compact(cp, context)
22-
keys = cp.keys()
23-
# Using len because @type elements get returned as type
24-
same = len(set(keys)) == len(set(json.keys()))
25-
if not same:
26-
print("Unsupported terms in Codemeta file")
27-
diff = set(json.keys()) - set(keys)
28-
if "@type" in diff:
29-
diff.remove("@type")
30-
print(sorted(diff))
31-
fail = ":" in keys
32-
if fail:
33-
print("Not in schema")
34-
for k in keys:
35-
if ":" in k:
36-
print(k)
3720

38-
# Restore the original context
39-
json["@context"] = original_context
40-
return same and not fail
21+
if context == "https://w3id.org/codemeta/3.0":
22+
cp = copy.deepcopy(json)
23+
# Expand and contract to check mapping
24+
cp = jsonld.expand(cp)
25+
cp = jsonld.compact(cp, context)
26+
keys = cp.keys()
27+
# Using len because @type elements get returned as type
28+
same = len(set(keys)) == len(set(json.keys()))
29+
if not same:
30+
print("Unsupported terms in Codemeta file")
31+
diff = set(json.keys()) - set(keys)
32+
if "@type" in diff:
33+
diff.remove("@type")
34+
print(sorted(diff))
35+
fail = ":" in keys
36+
if fail:
37+
print("Not in schema")
38+
for k in keys:
39+
if ":" in k:
40+
print(k)
41+
42+
# Restore the original context
43+
json["@context"] = original_context
44+
return same and not fail
45+
46+
return True # If the context is not recognized, we assume it's valid for now

meta_creator/views.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ def index(request):
4646
result = data_extraction(request)
4747

4848
if not result.get('success'):
49-
error_messages = ['Error in extraction:', result.get('errors')]
49+
errors = result.get('errors')
50+
51+
# Check if errors is a list or a string and format accordingly
52+
if isinstance(errors, list):
53+
error_messages = ['Error in extraction:'] + errors
54+
else:
55+
error_messages = ['Error in extraction:', errors]
5056
return render(request, 'meta_creator/error.html', {
5157
'error_message': "; ".join(error_messages)
5258
})

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Core Django and JSON handling
2-
django==4.1.10
2+
Django>=4.2.22
33
django_jsonforms==1.1.2
44
environs==9.3.5
55
marshmallow>=3.10,<3.20
@@ -11,6 +11,6 @@ python-gitlab==3.13.0
1111
GitPython>=3.1.41
1212

1313
# Git-based packages pinned to specific commits/branches
14-
git+https://github.com/softwarepub/hermes-plugin-github-gitlab@2a28c038bd87a3050f365ed103702554786ad66f#egg=hermes_plugin_githublab
14+
git+https://github.com/softwarepub/hermes-plugin-github-gitlab
1515
git+https://github.com/Aidajafarbigloo/hermes@14fc040afd4b7f7268b937477dce56bd7695fbf3#egg=hermes
1616

0 commit comments

Comments
 (0)