From f53a361dde2156be71fa49812fc96b40e3eec052 Mon Sep 17 00:00:00 2001 From: Peter Sefton <peter.sefton@uts.edu.au> Date: Thu, 31 Jan 2019 09:20:08 +1100 Subject: [PATCH] Nearly feature complete for describing the DataCrate sample dataset - need to be able to add a directory as a Dataset --- _CONTEXT_entities.json.template | 14 ++--- routes/index.js | 55 ++++++++++++---- views/index.ejs | 107 ++++++++++++++++++++------------ 3 files changed, 118 insertions(+), 58 deletions(-) diff --git a/_CONTEXT_entities.json.template b/_CONTEXT_entities.json.template index af0b8c8..cc51529 100644 --- a/_CONTEXT_entities.json.template +++ b/_CONTEXT_entities.json.template @@ -1,20 +1,20 @@ { - "1" : { + "1" : {"properties" : { "type": [{"value": "Dataset"}], "name": [{"value": "Dataset"}], "description": [{"value": "---- Your Description Goes here --- (Try to add more info than is in the name"}], "creator": [{"id": "2", "value": ""}], "publisher": [{"id": "3", "value": ""}], "datePublished": [{"value": "2019"}] - }, - "2" : { + }}, + "2" : {"properties" : { "type": [{"value": "Person"}], "name": [{"value": "Person 1"}], - "affiliation": [{"id": "2", "value": ""}] - }, - "3" : { + "affiliation": [{"id": "3", "value": ""}] + }}, + "3" : {"properties" : { "type": [{"value": "Organization"}], "name": [{"value": "Org"}], "description": [{"value": ""}] - } + }} } \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 328e0ae..1684b84 100644 --- a/routes/index.js +++ b/routes/index.js @@ -27,10 +27,12 @@ var schema = { "instrument" : {"input": "link", "type": ["IndividualProduct", "SoftwareApplication"]}, "object" : {"input": "link", "type": ["File", "Place", "Person", "Organization", "IndividualProduct"]}, "agent" : {"input": "link", "type": ["Person"]}, + "publisher" : {"input": "link", "type": ["Person", "Organization"]}, "result" : {"input": "link", "type": ["File"]}, "contactPoint" : {"input": "link", "type": ["ContactPoint"]}, "contentLocation" : {"input": "link", "type": ["Place"]}, "geo" : {"input": "link", "type": ["GeoCoordinates"]}, + "thumbnail" : {"input": "link", "type": ["File"]}, "license" : {"input": "link", "type": ["CreativeWork", "File"]}, "latitude" : {"input": "text"}, "longitude" : {"input": "text"}, @@ -41,7 +43,8 @@ var schema = { "types" : { "Person" : { - "template" : + "create" : true, + "template" : {"properties": { "type" : [{"value" : "Person"}], "name" : [{"value" : " "}], @@ -49,35 +52,49 @@ var schema = { "email" : [{"value" : " "}], "URL" : [{"value" : " "}] } + } }, "Organization" : { + "create" : true, + "template" : { + "properties": + { "type" : [{"value" : "Organization"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], "URL" : [{"value" : " "}] - }}, + }}}, "ContactPoint" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "ContactPoint"}], "name" : [{"value" : " "}], "email" : [{"value" : " "}], "URL" : [{"value" : " "}] - }}, + }}}, "GeoCoordinates" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "GeoCoordinates"}], "latitude" : [{"value" : " "}], "longitude" : [{"value" : " "}], "URL" : [{"value" : " "}], - }}, + }}}, "Dataset" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "Dataset"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], @@ -85,10 +102,13 @@ var schema = { "creator" : [{"id" : ""}], "contributor" : [{"id" : ""}], "URL" : [{"value" : " "}] - }}, + }}}, "File" : { + "create" : false, + "template" : { + "properties": { "type" : [{"value" : "File"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], @@ -96,38 +116,49 @@ var schema = { "contributor" : [{"id" : ""}], "license" : [{"id" : ""}], "URL" : [{"value" : " "}] - }}, + }}}, "Place" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "Place"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], "URL" : [{"value" : " "}], "geo": [{"value" : " "}], "Address" : [{"value" : " "}] - } - }, + }}}, "IndividualProduct" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "IndividualProduct"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], "serialNumber" : [{"value" : ""}] - } + }} }, "SoftwareApplication" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "SoftwareApplication"}], "name" : [{"value" : " "}], "description" : [{"value" : " "}], "version" : [{"value" : ""}] - } + }} }, "CreateAction" : { + "create" : true, + "template" : { + "properties": { "type" : [{"value" : "CreateAction"}], "name" : [{"value" : " "}], "agent" : [{"id" : ""}], @@ -135,7 +166,7 @@ var schema = { "result" : [{"id" : ""}], "object" : [{"id" : ""}], - } + }} } } } @@ -172,7 +203,7 @@ router.get('/files', function(req, res, next) { files[absolute_path]= ({"filename": f, "name": f, "id": absolute_path}) // Crude thumbnail-hack for now until we deal with this properly if (isImage(absolute_path)) { - files[absolute_path]["img"] = `/preview?path=${absolute_path}`; + files[absolute_path]["_img"] = `/preview?path=${absolute_path}`; } } } diff --git a/views/index.ejs b/views/index.ejs index 30fa368..94ca3a6 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -12,10 +12,11 @@ <!-- Vue app element --> <div id="app" > - <h1><a v-bind:href="'?path=' + files.up">.. </a></h1> + {{ changed }} + <h1><a v-bind:href="'?path=' + files.up + '&dataset_path=' + dataset_path">.. </a></h1> <template v-if="context"> - {{this.changed}} + <template v-for="(item, id) in context"> <h2 v-bind:id="id"> <form v-on:submit.prevent="removeItem(id)"> @@ -23,39 +24,42 @@ <button type="submit">-</button> {{ id }} </form> </h2> - <img width="60%" v-bind:src='item.img'> + <img width="60%" v-bind:src='item._img'> <table width="100%" > - <tr v-for="(values, name) in item"> + <tr v-for="(values, name) in item.properties"> <td> - <form v-on:submit.prevent="removeProp(item, name)" style='display:inline;'> + <form v-on:submit.prevent="removeProp(item.properties, name)" style='display:inline;'> <button type="submit">-</button> </form> {{ name }} </td> <td> - <form v-on:submit.prevent="addProp(item, name)" style='display:inline;'> + <form v-on:submit.prevent="addProp(item.properties, name)" style='display:inline;'> <button type="submit">+</button> </form> </td> <td> <div v-for="(val, i_index) in values"> - - - + + <!-- TODO - make sure it's deletable --> + <form v-on:submit.prevent="unlinkProp(val)" style='display:inline;'> + <button type="submit" title="Delete this property">-</button> + </form> + <template v-if="schema.properties[name] && schema.properties[name].input === 'text'"> <input v-model="val.value" type="text" size="45" v-on:keyup="trigger_change_on_enter"/> </template> - <template v-else-if="val && val.id && context[val.id] && context[val.id].name"> + <template v-else-if="val && val.id && context[val.id] && context[val.id].properties.name"> + + <a v-bind:href="'#' + val.id">{{ context[val.id].properties.name[0].value }}</b></a> <form v-on:submit.prevent="unlinkProp(val)" style='display:inline;'> - <button type="submit">-</button> + <button type="submit">unlink</button> </form> - <a v-bind:href="'#' + val.id">{{ context[val.id].name[0].value }}</b></a> - </template> <b v-else> @@ -65,13 +69,14 @@ <template v-if="schema.properties[name] && schema.properties[name].input === 'link' " > - <form v-on:submit.prevent="linkProp(val)" style='display:inline;'> + + <form v-on:submit.prevent="linkProp(val)" style='display:inline;' v-if="!val.id"> <button type="submit"> -> </button> - <select v-model="link_to_id" > + <select v-model="val.selection" > <template v-for="(link_item, link_id) in context"> - <template v-for="other_name in link_item.name"> - <option v-if="(!val.id || link_id != val.id) && schema.properties[name] && link_item.type && schema.properties[name].type.includes(link_item.type[0].value)" v-bind:value="link_id">{{ other_name.value }}</select> + <template v-for="other_name in link_item.properties.name"> + <option v-if="(!val.id || link_id != val.id) && schema.properties[name] && link_item.properties.type && schema.properties[name].type.includes(link_item.properties.type[0].value)" v-bind:value="link_id">{{ other_name.value }}</select> </template> </template> @@ -80,6 +85,22 @@ </form> + <form v-on:submit.prevent="linkToNew(val)" style='display:inline;' v-if="!val.id && schema.properties[name].type.filter(type => {return (schema.types[type] && schema.types[type].create)}).length > 0"> + ... or ... + <button type="submit" text="Link to a new contextual item"> -> New -> </button> + <select v-model="val.new_type" > + <template v-for="type in schema.properties[name].type.filter(type => {return (schema.types[type] && schema.types[type].create)})"> + + <option> {{ type }} </option> + + </template> + + + </select> + </select> + + </form> + </template> @@ -95,7 +116,7 @@ <form v-on:submit.prevent="addContextProp(item)"> <select v-model="prop_name" > <template v-for="(prop, prop_name) in schema.properties"> - <option v-if="!item[prop_name]">{{prop_name}}</option> + <option v-if="!item.properties[prop_name]">{{prop_name}}</option> </template> </select> @@ -104,18 +125,18 @@ <br><br> </template> - + <form v-on:submit.prevent="addContext(context)"> <select v-model="type" > - <option v-for="(type, type_name) in schema.types" v-bind:value="type_name"> {{ type_name }} </option> + <option v-for="type_name in Object.getOwnPropertyNames(schema.types).filter(type => {return schema.types[type].create})" v-bind:value="type_name"> {{ type_name }} </option> </select> <button type="submit">Add contextual item</button> </form> - + </template> <h1> - <a v-bind:href="'/?path=' + path + '&dataset_path=' + path"> + <a v-bind:href="'/?path=' + path + '&dataset_path=' + dataset_path"> <template v-if="files.existing_describo"> Edit existing data package </template> @@ -128,7 +149,7 @@ <div v-for="(file, path) in files.files"> <template v-if="!(context[file.id])"> <h1>{{ file.filename }}</h1> - <img width="50%" v-bind:src='file.img'> + <img width="50%" v-bind:src='file._img'> <form v-if="context" v-on:submit.prevent="addFile(file)"> <button type="submit">Add file to package</button> </form> @@ -138,7 +159,7 @@ <div id="filelist" border="1"> <ul v-for="dir in files.dirs"> - <li><a v-bind:href="'?path=' + dir.absolute">{{ dir.name }}</a></li> + <li><a v-bind:href="'?path=' + dir.absolute + '&dataset_path=' + dataset_path">{{ dir.name }}</a></li> </ul> </div> @@ -184,7 +205,7 @@ prop: {"name":"nom", "value": "val"}, type: "Person", prop_name: "", - link_to_id: "", + link_to_id: {}, link_id: "", changed: 0, latest_id: 0, @@ -205,19 +226,19 @@ "addContextProp": function addContextProp(item){ // Warning! Repetition! var prop_name = this.prop_name; - if (item[prop_name]) { - item[prop_name].push({"value": "", "id": ""}); + if (item.properties[prop_name]) { + item.properties[prop_name].push({"value": "", "id": ""}); } else { - item[prop_name] = [{"value": "", "id": ""}]; + item.properties[prop_name] = [{"value": "", "id": ""}]; } this.changed += 1; this.save_context(); }, "addProp": function addProp(item, prop_name){ - if (item[prop_name]) { - item[prop_name].push({"value": "", "id": ""}); + if (item.properties[prop_name]) { + item.properties[prop_name].push({"value": "", "id": ""}); } else { - item[prop_name] = [{"value": "", "id": ""}]; + item.properties[prop_name] = [{"value": "", "id": ""}]; } this.changed += 1; this.save_context(); @@ -236,23 +257,23 @@ } }, - "linkProp": function linkProp(val) { - val.value = context[this.link_to_id].name[0].value - val.id = this.link_to_id + "linkProp": function linkProp(val) { + val.value = context[val.selection].properties.name[0].value; + val.id = val.selection; this.changed += 1; this.save_context(); }, "unlinkProp": function unlinkProp(val) { - val.value = "" - val.id = "" + val.value = ""; + val.id = ""; this.changed += 1; this.save_context(); }, "addFile": function addFile(file) { if (!context[file.id]) { var new_item = JSON.parse(JSON.stringify(schema.types.File.template)); - new_item.name[0].value = file.id; - new_item.img = file.img; + new_item.properties.name[0].value = file.id; + new_item._img = file._img; context[file.id] = new_item; this.changed += 1; @@ -271,15 +292,23 @@ this.save_context(); }, + "linkToNew" : function linkToNew(val) { + alert(val.new_type); + this.type = val.new_type; + val.id = this.addContext(context); + this.save_context(); + + }, "addContext": function addContext(context){ while (context[this.latest_id.toString()]) { this.latest_id += 1; } var id = this.latest_id.toString(); context[id] = JSON.parse(JSON.stringify(schema.types[this.type].template)); - context[id].name=[{"value": this.id}] + context[id].properties.name=[{"value": this.type + "(" + id + ")"}] this.changed += 1; this.save_context(); + return(id); } } -- GitLab