diff --git a/routes/index.js b/routes/index.js index 22b3267bb5effe982715b049aa758b5dc5efd325..328e0ae410ec5189f0f87ed98630898eab4c5fa0 100644 --- a/routes/index.js +++ b/routes/index.js @@ -6,6 +6,14 @@ var fs = require("fs"); var isImage = require('is-image'); var path = require("path"); +// Todo - require this as a module and clean up repetition +const defaults = { + describo_file: "describo.json", + ignore_dirs: ["CATALOG_html"], + ignore_files: ["describo.json", "CATALOG.json"] +} + + var schema = { "properties": { "name" : {"input": "text"}, @@ -13,6 +21,7 @@ var schema = { "type" : {}, "affiliation" : {"input": "link", "type": ["Organization"]}, "address" : {"input" : "text"}, + "URL" : {"input" : "text"}, "creator" : {"input": "link", "type": ["Person", "Organization"]}, "contributor" : {"input": "link", "type": ["Person", "Organization"]}, "instrument" : {"input": "link", "type": ["IndividualProduct", "SoftwareApplication"]}, @@ -148,19 +157,18 @@ router.get('/files', function(req, res, next) { var dir_path = req.query.path; var files_json_path = path.join(dir_path, "_FILES.json"); var up_path = path.resolve(dir_path + "/.."); - if (shell.test("-f", files_json_path )) { - known_files = JSON.parse(fs.readFileSync(files_json_path)) - } - + var describo_exists = false; for (let f of shell.ls(dir_path)) { + if (f === defaults.describo_file) { + describo_exists = true; + } var absolute_path = path.resolve(path.join(dir_path, f)); + console.log(absolute_path, shell.test('-d', absolute_path)); if (shell.test('-d', absolute_path)) { - dirs.push({"absolute": absolute_path, "name": f}) - } else if (known_files[absolute_path]) { - files[absolute_path] = known_files[absolute_path]; - //TODO: Worry about sizes etc - } else { - console.log("Setting file", absolute_path) + if (!defaults.ignore_dirs.includes(f)){ + dirs.push({"absolute": absolute_path, "name": f}) + } + } else if (!defaults.ignore_files.includes(f)) { 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)) { @@ -168,18 +176,17 @@ router.get('/files', function(req, res, next) { } } } - res.json({"files": files, "dirs" : dirs, "up": up_path}) + res.json({"files": files, "dirs" : dirs, "up": up_path, "existing_describo": describo_exists}) }); -router.post('/files', function(req, res, next) { - fs.writeFileSync(path.join(req.query.path, "_FILES.json"), JSON.stringify(req.body,null, 2)); - return {} -}); + router.post('/context_entities', function(req, res, next) { - fs.writeFileSync(path.join(req.query.path, "_CONTEXT_entities.json"), JSON.stringify(req.body,null, 2)); + fs.writeFileSync(path.join(req.query.dataset_path, "describo.json"), JSON.stringify(req.body,null, 2)); return {} }); + + router.get('/preview', function(req, res, next) { const the_path = req.query.path; res.sendFile(the_path); @@ -187,14 +194,21 @@ router.get('/preview', function(req, res, next) { - router.get('/context_entities', function(req, res, next) { - if (!shell.test("-f", "_CONTEXT_entities.json")) { - shell.cp("_CONTEXT_entities.json.template", "_CONTEXT_entities.json") - } - var context = JSON.parse(fs.readFileSync( "_CONTEXT_entities.json")); - console.log(context); - res.json(context); + console.log(req.query.dataset_path); + if (req.query.dataset_path) { + var context_path = path.join(req.query.dataset_path, "describo.json"); + + if (!shell.test("-f", context_path)) { + shell.cp("_CONTEXT_entities.json.template", context_path) + } + var context = JSON.parse(fs.readFileSync(context_path)); + console.log(context); + res.json(context); +} else { + console.log("No context found"); + res.json(undefined); +} }); diff --git a/views/index.ejs b/views/index.ejs index 58233d174229e2af6285868e3fa8d5a5a7488b65..babf77b0e981780349f39f38433e3144e93412a7 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -12,70 +12,94 @@ <!-- Vue app element --> <div id="app" > - {{this.changed}} <h1><a v-bind:href="'?path=' + files.up">.. </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)"> - {{ id }} - <button type="submit">Delete</button> + + <button type="submit">-</button> {{ id }} </form> </h2> - <img width="60%" v-bind:src='item.img'> - <table width="100%" > - - <tr v-for="(values, name) in item"> - <td>{{ name }} </td> - <td> - - <div v-for="(val, i_index) in values"> - - - - <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.id && context[val.id]"> - <a v-bind:href="'#' + val.id">{{ context[val.id].name[0].value }}</b> - </template> - <b v-else> - {{ val.value }} - </b> - - - - <template v-if="schema.properties[name] && schema.properties[name].input === 'link' " > - <form v-on:submit.prevent="linkProp(val)" style='display:inline;'> - <select v-model="link_to_id" > - <template v-for="(link_item, link_id) in context"> - <template v-for="other_name in link_item.name"> - <option v-if="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> + <img width="60%" v-bind:src='item.img'> + <table width="100%" > + + <tr v-for="(values, name) in item"> + <td> + <form v-on:submit.prevent="removeProp(item, name)" style='display:inline;'> + <button type="submit">-</button> + </form> + {{ name }} + + </td> + <td> + <form v-on:submit.prevent="addProp(item, name)" style='display:inline;'> + <button type="submit">+</button> + </form> + </td> + <td> + + <div v-for="(val, i_index) in values"> + + + + <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"> + <form v-on:submit.prevent="unlinkProp(val)" style='display:inline;'> + <button type="submit">-</button> + </form> + <a v-bind:href="'#' + val.id">{{ context[val.id].name[0].value }}</b></a> + + </template> + + <b v-else> + {{ val.value }} + </b> + + + + <template v-if="schema.properties[name] && schema.properties[name].input === 'link' " > + <form v-on:submit.prevent="linkProp(val)" style='display:inline;'> + <button type="submit"> -> </button> + <select v-model="link_to_id" > + + <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> - - </select> + </template> + </select> - <button type="submit">Link</button> - </form> - </template> - - + </select> + + </form> + + </template> + + - - </div> - + + </div> - </td> - </tr> - </table> - + + </td> + </tr> + </table> <form v-on:submit.prevent="addContextProp(item)"> <select v-model="prop_name" > - <option v-for="(prop, prop_name) in schema.properties">{{prop_name}}</option> + <template v-for="(prop, prop_name) in schema.properties"> + <option v-if="!item[prop_name]">{{prop_name}}</option> + </template> </select> - <button type="submit">Add prop</button> + <button type="submit">+</button> </form> <br><br> </template> @@ -88,22 +112,30 @@ <button type="submit">Add contextual item</button> </form> - + </template> - + <h1> + <a v-bind:href="'/?path=' + path + '&dataset_path=' + path"> + <template v-if="files.existing_describo"> + Edit exsiting data package + </template> + <template v-else> + Package a dataset here + </template> + </a> </h1> <div id="filelist" border="1"> <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'> - <form v-on:submit.prevent="addFile(file)"> + <form v-if="context" v-on:submit.prevent="addFile(file)"> <button type="submit">Add file to package</button> </form> </template> </div> </div> - + <div id="filelist" border="1"> <ul v-for="dir in files.dirs"> <li><a v-bind:href="'?path=' + dir.absolute">{{ dir.name }}</a></li> @@ -124,9 +156,6 @@ <script> - var save = function save() { - console.log(data); - } var vue; @@ -134,12 +163,14 @@ var context = {}; var schema = {}; document.addEventListener("DOMContentLoaded", function(event) { - const urlParams = new URLSearchParams(window.location.search); + const urlParams = new URLSearchParams(window.location.search); const path = urlParams.get('path'); + const dataset_path = urlParams.get('dataset_path'); axios.get('/files?path=' + path) .then(function (response) { files = response.data; - axios.get("/context_entities").then(function(response){ + var params = dataset_path ? '?dataset_path=' + dataset_path : "" + axios.get("/context_entities" + params).then(function(response){ context = response.data; axios.get("/schema").then(function(response){ schema = response.data; @@ -156,32 +187,48 @@ link_to_id: "", link_id: "", changed: 0, - latest_id: 0 + latest_id: 0, + path: path, + dataset_path: dataset_path }, methods: { - "save": function save() { - axios.post('/files?path=' + path, this.$data.files.files).then( - ) - }, + "save_context": function save_context() { - - axios.post('/context_entities?path=.', this.context).then( + var params = '?dataset_path=' + this.dataset_path; + axios.post('/context_entities' + params, this.context).then( function () { } ) }, "addContextProp": function addContextProp(item){ + // Warning! Repetition! var prop_name = this.prop_name; - if (item[prop_name]) { + if (item[prop_name]) { + item[prop_name].push({"value": "", "id": ""}); + } else { + item[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": ""}); } else { item[prop_name] = [{"value": "", "id": ""}]; } - this.changed += 1; + this.changed += 1; + this.save_context(); + }, + "removeProp": function removeProp(item, prop_name){ + delete item[prop_name]; + this.changed += 1; + this.save_context(); }, + trigger_change_on_enter: function(e) { if (e.keyCode === 13) { this.changed += 1; @@ -195,13 +242,17 @@ this.changed += 1; this.save_context(); }, - + "unlinkProp": function unlinkProp(val) { + 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; - alert(file.img); context[file.id] = new_item; this.changed += 1; @@ -225,8 +276,7 @@ this.latest_id += 1; } var id = this.latest_id.toString(); - context[id] = schema.types[this.type].template; - console.log('NEW ONE', schema.types[this.type].template ) + context[id] = JSON.parse(JSON.stringify(schema.types[this.type].template)); context[id].name=[{"value": this.id}] this.changed += 1; this.save_context();