Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.

Commit 4d4203f

Browse files
committed
added consolidated data model idea
1 parent 496917e commit 4d4203f

File tree

5 files changed

+86
-48
lines changed

5 files changed

+86
-48
lines changed

config.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Config:
1111
"""Base config"""
1212

1313
FLASK_APP = "wsgi.py"
14+
JSON_SORT_KEYS = False
1415
SECRET_KEY = os.environ["SECRET_KEY"]
1516
JWT_SECRET_KEY = os.environ["SECRET_KEY"]
1617
STATIC_FOLDER = "static"

src/ingest/routes.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from ..database import db_utils
1717
from ..database import backend_methods as bm
1818

19-
from ..utils.frontend import ASSET_TYPES
19+
from ..utils.frontend import ASSET_TYPES, DATA_SCHEMA
2020
from ..utils.networkgraph import get_network_data, NODESTYLES
2121

2222
from flask import (
@@ -56,6 +56,11 @@ def experimentbuilder():
5656

5757

5858

59+
@ingest_bp.route("/userdata")
60+
def userdata():
61+
"""Endpoint for reading consolidated data for the current user"""
62+
return DATA_SCHEMA
63+
5964

6065
@ingest_bp.route("/ingestor", methods=["GET", "POST"])
6166
def ingestor():

src/ingest/static/js/ingestor.js

+54-47
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
1-
const schema = {
2-
'material': {
3-
'name': {'type': 'string', 'color': 'rgba(0, 0, 255, 0.1)'},
4-
'source': {'type': 'string', 'color': 'rgba(0, 0, 255, 0.1)'},
5-
'lot_number': {'type': 'string', 'color': 'rgba(0, 0, 255, 0.1)'},
6-
'notes': {'type': 'longstring', 'color': 'rgba(0, 255, 0, 0.1)'},
7-
'keywords': {'type': 'list', 'color': 'rgba(0, 0, 255, 0.1)'},
8-
'hazards': {'type': 'list', 'color': 'rgba(0, 0, 255, 0.1)'},
9-
'properties': {'type': 'list', 'color': 'rgba(0, 0, 255, 0.1)'},
10-
},
11-
'property': {
12-
'name': {'type': 'string',},
13-
'value': {'type': 'float',},
14-
'units': {'type': 'string',},
15-
'notes': {'type': 'string',},
16-
},
17-
};
18-
19-
20-
1+
// import current data as single large JSON
2+
// copy it using var d = d0.slice();
3+
// make adjustments to d
4+
// save or cancel at the end
215

226

237

248
const tablediv = document.getElementById('tablediv');
25-
var matcols = Object.keys(schema['material']);
26-
9+
var udata = {};
10+
var matkeys = [];
11+
12+
// retrieve the consolidated data
13+
getUserData();
14+
15+
// retrieve data from the server
16+
function getUserData(){
17+
$.ajax({
18+
url: "/userdata",
19+
type: "get",
20+
success: function(r) {
21+
udata = r;
22+
updateTable();
23+
},
24+
});
25+
};
2726

2827

2928
function updateTable() {
3029

30+
// get material keys
31+
var matkeys = Object.keys(udata['materials'][0]);
32+
3133
// create table
32-
const table = document.createElement('table');
34+
var table = document.createElement('table');
3335
table.id = 'ingesttable';
3436
table.classList.add('table', 'table-hover');
3537

3638
// loop over each row
3739
// this should happen before table headers are created
38-
// so that the so that the tbody is created automatically
39-
for (let r = 0; r < 3; r++) {
40+
// so that the tbody is created automatically
41+
for (let r = 0; r < udata['materials'].length; r++) {
4042
const tr = table.insertRow();
4143
tr.id = r;
4244

@@ -48,33 +50,38 @@ function updateTable() {
4850

4951

5052
// loop over each cell in the row
51-
for (mc of matcols) {
53+
for (mk of matkeys) {
5254
const td = tr.insertCell();
5355

5456
var el = document.createTextNode('');
55-
var datatype = schema['material'][mc]['type'];
57+
var dataval = udata['materials'][0][mk];
5658

57-
if (datatype === 'string') {
58-
el = createInput(id='id'+r+mc, placeholder=formatLabel(mc), value='');
59-
el.addEventListener('input', parseTable);
59+
if (typeof dataval === 'string') {
6060

61-
} else if (datatype === 'longstring') {
62-
el = createButton(trigger='notesmodal', id='id'+r+mc,)
61+
if (mk === 'notes') {
62+
el = createButton(trigger='notesmodal', id='id'+r+mk,)
63+
} else {
64+
el = createInput(id='id'+r+mk, placeholder=formatLabel(mk), value='');
65+
el.addEventListener('input', parseTable);
66+
};
6367

64-
} else if (datatype === 'list') {
68+
} else if (dataval.constructor === Array) {
6569

66-
if (mc === 'keywords') {
67-
el = createButton(trigger='keywordsmodal', id='id'+r+mc,)
70+
if (mk === 'keywords') {
71+
el = createButton(trigger='keywordsmodal', id='id'+r+mk,)
6872
};
6973

70-
if (mc === 'hazards') {
71-
el = createButton(trigger='hazardsmodal', id='id'+r+mc,)
74+
if (mk === 'hazards') {
75+
el = createButton(trigger='hazardsmodal', id='id'+r+mk,)
7276
};
7377

74-
if (mc === 'properties') {
75-
el = createButton(trigger='propertiesmodal', id='id'+r+mc,)
78+
if (mk === 'properties') {
79+
el = createButton(trigger='propertiesmodal', id='id'+r+mk,)
7680
};
7781

82+
if (mk === 'data') {
83+
el = createButton(trigger='datamodal', id='id'+r+mk,)
84+
};
7885

7986
};
8087

@@ -89,7 +96,7 @@ function updateTable() {
8996
// create table headers
9097
const thead = table.createTHead();
9198
var row = thead.insertRow(0);
92-
for (mc of [''].concat(matcols)) {
99+
for (mc of [''].concat(matkeys)) {
93100
var cell = row.insertCell();
94101
cell.innerHTML = formatLabel(mc);
95102
};
@@ -99,15 +106,16 @@ function updateTable() {
99106

100107

101108
// build the table
102-
var table = updateTable();
109+
//var table = updateTable();
103110

104111

105112

106113

107114
// parse the table contents into JSON format
108115
function parseTable() {
116+
var table = document.getElementById('ingesttable');
109117
// create object to hold data from table
110-
var data = {'materials': []};
118+
var dataexport = {'materials': []};
111119
// iterate over table rows
112120
for (var r = 0, row; row = table.rows[r]; r++) {
113121
// skip the headers row
@@ -117,18 +125,17 @@ function parseTable() {
117125
// iterate over table columns
118126
for (var c = 1, cell; cell = row.cells[c]; c++) {
119127
// get name of current column (subtract 1 to ignore the 'delete row' button in 1st column)
120-
var colname = matcols[c-1];
121-
console.log(colname);
128+
var colname = matkeys[c-1];
122129
// if cell contains a text input, add its value to the data object
123-
if (schema['material'][colname]['type'] === 'string') {
130+
if (typeof cell.children[0].value === 'string') {
124131
mat[colname] = cell.children[0].value;
125132
};
126133
};
127134
// add material to the dataset
128-
data['materials'].push(mat);
135+
dataexport['materials'].push(mat);
129136
};
130137
// display the dataset on the UI
131-
document.getElementById('results').innerHTML = '<pre><b>Result:</b><br>' + JSON.stringify(data, null, 4) + '</pre>';
138+
document.getElementById('results').innerHTML = '<pre><b>Result:</b><br>' + JSON.stringify(dataexport, null, 4) + '</pre>';
132139
};
133140

134141

src/ingest/templates/ingestor.html

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ <h1 class="card-header">
1414
Materials table for data ingestion
1515
</h1>
1616

17+
1718
<div class="card-body">
1819

1920
<button id='addmaterialbtn' type='button' class='btn btn-success'><i class='bi bi-plus-lg'></i> Add new material</button>

src/utils/frontend.py

+24
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,30 @@
33
44
"""
55

6+
DATA_SCHEMA = {
7+
'materials': [
8+
{
9+
'name': '',
10+
'source': '',
11+
'lot_number': '',
12+
'notes': '',
13+
'keywords': [''],
14+
'hazards': [''],
15+
'properties': [
16+
{'name': '', 'value': 0, 'units': '',},
17+
],
18+
'data': [
19+
{'filename': '', 'data': '', 'notes': '',},
20+
],
21+
},
22+
],
23+
};
24+
25+
26+
27+
28+
29+
630
ASSET_TYPES = ["group", "publication", "collection", "experiment"]
731

832

0 commit comments

Comments
 (0)