Add function to import exported results and view them after the import

This commit is contained in:
Stephan Porada
2020-07-03 14:41:57 +02:00
parent a997fbe0ee
commit 1811623583
27 changed files with 880 additions and 32 deletions

View File

@ -200,7 +200,6 @@
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
</div>
</div>
@ -567,23 +566,7 @@
// checks if a change for every interactionElement happens and executes
// the callbacks accordingly
for (let interaction of interactionElements) {
if (interaction.checkStatus) {
interaction.element.addEventListener("change", (event) => {
if (event.target.checked) {
let f_on = interaction.bindThisToCallback("on");
let args_on = interaction.callbacks.on.args;
f_on(...args_on);
} else if (!event.target.checked){
let f_off = interaction.bindThisToCallback("off");
let args_off = interaction.callbacks.off.args;
f_off(...args_off);
}
});
} else {
continue
}
};
InteractionElement.onChangeExecute(interactionElements);
// eventListener if pagination is used to apply new context size to new page
// and also activate inspect match if progress is 100

View File

@ -27,13 +27,13 @@
<div class="row">
<div class="col s12 m6">
<div class="input-field">
<input disabled value="{{ corpus.creation_date.strftime('%m/%d/%Y, %H:%M:%S %p') }}" id="creation-date" type="text" class="validate">
<input disabled value="{{ corpus.creation_date.strftime('%d/%m/%Y, %H:%M:%S %p') }}" id="creation-date" type="text" class="validate">
<label for="creation-date">Creation date</label>
</div>
</div>
<div class="col s12 m6">
<div class="input-field">
<input disabled value="{{ corpus.last_edited_date.strftime('%m/%d/%Y, %H:%M:%S %p') }}" id="last_edited_date" type="text" class="validate">
<input disabled value="{{ corpus.last_edited_date.strftime('%d/%m/%Y, %H:%M:%S %p') }}" id="last_edited_date" type="text" class="validate">
<label for="creation-date">Last edited</label>
</div>
</div>

View File

@ -36,7 +36,7 @@
<div class="col s12 m6">
<div class="input-field">
<input disabled id="creation-date" type="text" value="{{ job.creation_date.strftime('%m/%d/%Y, %H:%M:%S %p') }}">
<input disabled id="creation-date" type="text" value="{{ job.creation_date.strftime('%d/%m/%Y, %H:%M:%S %p') }}">
<label for="creation-date">Creation date</label>
</div>
</div>

View File

@ -28,6 +28,7 @@
<ul class="pagination"></ul>
</div>
<div class="card-action right-align">
<a class="waves-effect waves-light btn" href="{{ url_for('services.results') }}">Show Imported Results<i class="material-icons right">folder</i></a>
<a class="waves-effect waves-light btn" href="{{ url_for('corpora.add_corpus') }}">New corpus<i class="material-icons right">add</i></a>
</div>
</div>

View File

@ -0,0 +1,118 @@
{% extends "nopaque.html.j2" %}
{% block page_content %}
<div class="col s12">
<p>Below the metadata for the results from the Corpus
<i>{{ result.corpus_metadata.corpus_name }}</i> generated with the query
<i>{{ result.corpus_metadata.query }}</i> are shown.
</p>
<p>{{ texts_metadata }}</p>
</div>
<div class="col s12">
<div class="card">
<div class="card-content" id="results">
<table class="responsive-table highlight">
<thead>
<tr>
<th>Metadata Description</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for pair in result.corpus_metadata|dictsort %}
<tr>
<td>{{ pair[0] }}</td>
{% if pair[0] == 'corpus_all_texts'
or pair[0] == 'text_lookup' %}
<td>
<table>
{% for key, value in pair[1].items() %}
<tr style="border-bottom: none;">
<td>
<i>{{ value['title'] }}</i> written
by <i>{{ value['author'] }}</i>
in <i>{{ value['publishing_year'] }}</i>
<a class="waves-effect
waves-light
btn
right
more-text-detials"
data-metadata-key="{{ pair[0] }}"
data-text-key="{{ key }}"
href="#modal-text-details">More
<i class="material-icons right"
data-metadata-key="{{ pair[0] }}"
data-text-key="{{ key }}">
info_outline
</i>
</a>
</td>
</tr>
{% endfor %}
</table>
</td>
{% else %}
<td>{{ pair[1] }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="card-action right-align">
<a class="waves-effect waves-light btn" href="{{ url_for('services.import_results') }}">Inspect Results<i class="material-icons right">search</i></a>
</div>
</div>
</div>
<!-- Modal Structure -->
<div id="modal-text-details" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Bibliographic data</h4>
<p id="bibliographic-data"></p>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green red btn">Close</a>
</div>
</div>
<script>
var moreTextDetailsButtons;
moreTextDetailsButtons = document.getElementsByClassName("more-text-detials");
for (var btn of moreTextDetailsButtons) {
btn.onclick = () => {
let modal = document.getElementById("modal-text-details");
modal = M.Modal.init(modal, {"dismissible": true});
modal.open();
let metadataKey = event.target.dataset.metadataKey;
let textKey = event.target.dataset.textKey;
let textData = {{ result.corpus_metadata|tojson|safe }}[metadataKey][textKey];
console.log(textData);
let bibliographicData = document.getElementById("bibliographic-data");
bibliographicData.innerHTML = "";
let table = document.createElement("table");
for (let [key, value] of Object.entries(textData)) {
table.insertAdjacentHTML("afterbegin",
`
<tr>
<td>${key}</td>
<td>${value}</td>
</tr>
`);
}
table.insertAdjacentHTML("afterbegin",
`
<thead>
<th>Description</th>
<th>Value</th>
</thead>
`)
bibliographicData.appendChild(table);
}
}
</script>
{% endblock %}

View File

@ -0,0 +1,211 @@
{% extends "nopaque.html.j2" %}
{% set headline = ' ' %}
{% set full_width = True %}
{% block page_content %}
<div class="col s12" id="query-display">
<div class="card">
<div class="card-content" id="result-list" style="overflow: hidden;">
<div class="row" style="margin-bottom: 0px;">
<div class="col s12 m3 l3" id="results-info">
<div class="row section">
<h6 style="margin-top: 0px;">Infos</h6>
<div class="divider" style="margin-bottom: 10px;"></div>
<div class="col" id="infos">
<p>
Displaying
<span id="received-match-count">
</span> of
<span id="match-count"></span>
matches.
<br>
Matches occured in
<span id="text-lookup-count"></span>
corpus files:
<br>
<span id=text-titles></span>
</p>
<div class="progress hide" id="query-results-progress">
<div class="determinate" id="query-results-determinate"></div>
</div>
</div>
</div>
</div>
<div class="col s12 m9 l9" id="actions-and-tools">
<div class="row section">
<div class="col s12 m3 l3" id="display">
<h6 style="margin-top: 0px;">Display</h6>
<div class="divider" style="margin-bottom: 10px;"></div>
<div class="row">
<div class="col s12">
<form id="display-options-form">
{{ M.render_field(display_options_form.results_per_page,
material_icon='format_list_numbered') }}
{{ M.render_field(display_options_form.result_context,
material_icon='short_text') }}
{{ M.render_field(display_options_form.expert_mode) }}
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Table showing the query results -->
<div class="col s12">
<ul class="pagination paginationTop"></ul>
<table class="responsive-table highlight">
<thead>
<tr>
<th style="width: 2%">Nr.</th>
<th style="width: 3%">Title</th>
<th style="width: 25%">Left context</th>
<th style="width: 35%">Match</th>
<th style="width: 10%">Actions</th>
<th style="width: 25%">Right Context</th>
</tr>
</thead>
<tbody class="list" id="query-results">
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
</div>
</div>
</div>
</div>
<script src="{{ url_for('static', filename='js/nopaque.Results.js') }}">
</script>
<script src="{{ url_for('static', filename='js/nopaque.callbacks.js') }}">
</script>
<script src="{{ url_for('static', filename='js/nopaque.InteractionElement.js') }}">
</script>
<script>
// ###### global variables ######
var full_result_json;
var result_json;
var queryResultsDeterminateElement; // The progress bar for recieved results
var receivedMatchCountElement; // Nr. of loaded matches will be displayed in this element
var textLookupCountElement // Nr of texts the matches occured in will be shown in this element
var textTitlesElement; // matched text titles
var progress; // global progress value
var queryResultsProgressElement; // Div element holding the progress bar
var expertModeSwitchElement; // Expert mode switch Element
var matchCountElement; // Total nr. of matches will be displayed in this element
var interactionElements; // Interaction elements and their parameters
// ###### Defining local scope variables
let displayOptionsFormElement; // Form holding the display informations
let resultItems; // array of built html result items row element. This is called when results are transmitted and being recieved
let hitsPerPageInputElement;let contextPerItemElement; // Form Element for display option
let paginationElements;
// ###### Initializing variables ######
displayOptionsFormElement = document.getElementById("display-options-form");
resultItems = [];
queryResultsDeterminateElement = document.getElementById("query-results-determinate");
receivedMatchCountElement = document.getElementById("received-match-count");
textLookupCountElement = document.getElementById("text-lookup-count");
textTitlesElement = document.getElementById("text-titles");
queryResultsProgressElement = document.getElementById("query-results-progress");
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
matchCountElement = document.getElementById("match-count");
hitsPerPageInputElement = document.getElementById("display-options-form-results_per_page");
contextPerItemElement = document.getElementById("display-options-form-result_context");
paginationElements = document.getElementsByClassName("pagination");
// js list options
displayOptionsData = ResultsList.getDisplayOptions(displayOptionsFormElement);
resultsListOptions = {page: displayOptionsData["resultsPerPage"],
pagination: [{
name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1
}, {
paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1
}],
valueNames: ["titles", "lc", "c", "rc", {data: ["index"]}],
item: `<span></span>`
};
document.addEventListener("DOMContentLoaded", () => {
// ###### recreating chunk structure to reuse callback queryRenderResults()
full_result_json = {{ result_json|tojson|safe }};
result_json = {};
result_json.chunk = {};
result_json.chunk["cpos_lookup"] = full_result_json.cpos_lookup;
result_json.chunk["cpos_ranges"] = full_result_json.cpos_ranges;
result_json.chunk["matches"] = full_result_json.matches;
result_json.chunk["text_lookup"] = full_result_json.text_lookup;
// Init corpus analysis components
data = new Data();
resultsList = new ResultsList("result-list", resultsListOptions);
resultsMetaData = new MetaData();
results = new Results(data, resultsList, resultsMetaData);
results.clearAll(); // inits some object keys and values
// TODO: save metadate into results.metaData
// setting some initial values for user feedback
matchCountElement.innerText = full_result_json.match_count;
// Initialization of interactionElemnts
// An interactionElement is an object identifing a switch or button via
// htmlID. Callbacks are set for these elements which will be triggered on
// a pagination interaction by the user or if the status of the element has
// been altered. (Like the switche has ben turned on or off).
interactionElements = new Array();
let expertModeInteraction = new InteractionElement("display-options-form-expert_mode");
expertModeInteraction.setCallback("on",
results.jsList.expertModeOn,
results.jsList,
["query-display"])
expertModeInteraction.setCallback("off",
results.jsList.expertModeOff,
results.jsList,
["query-display"])
let activateInspectInteraction = new InteractionElement("inspect",
false);
activateInspectInteraction.setCallback("noCheck",
results.jsList.activateInspect,
results.jsList);
let changeContextInteraction = new InteractionElement("display-options-form-results_per_page",
false);
changeContextInteraction.setCallback("noCheck",
results.jsList.changeContext,
results.jsList)
interactionElements.push(expertModeInteraction, activateInspectInteraction, changeContextInteraction);
// checks if a change for every interactionElement happens and executes
// the callbacks accordingly
InteractionElement.onChangeExecute(interactionElements);
// eventListener if pagination is used to apply new context size to new page
// and also activate inspect match if progress is 100
// also adds more interaction buttons like add to sub results
for (let element of paginationElements) {
element.addEventListener("click", (event) => {
results.jsList.pageChangeEventInteractionHandler(interactionElements);
});
}
// render results in table imported parameter is true
queryRenderResults(result_json, true)
// live update of hits per page if hits per page value is changed
let changeHitsPerPageBind = results.jsList.changeHitsPerPage.bind(results.jsList);
hitsPerPageInputElement.onchange = changeHitsPerPageBind;
// live update of lr context per item if context value is changed
contextPerItemElement.onchange = results.jsList.changeContext;
});
</script>
{% endblock %}

View File

@ -36,6 +36,7 @@
<ul class="pagination"></ul>
</div>
<div class="card-action right-align">
<a class="waves-effect waves-light btn" href="{{ url_for('services.results') }}">Show Imported Results<i class="material-icons right">folder</i></a>
<a class="waves-effect waves-light btn" href="{{ url_for('corpora.add_corpus') }}">New corpus<i class="material-icons right">add</i></a>
</div>
</div>

View File

@ -0,0 +1,39 @@
{% extends "nopaque.html.j2" %}
{% block page_content %}
<div class="col s12 m4">
<p>Fill out the following form to upload and view Results and Sub Results
exported from the Corpus analsis Tool.</p>
<a class="waves-effect waves-light btn" href="{{ url_for('main.dashboard') }}"><i class="material-icons left">arrow_back</i>Back to dashboard</a>
</div>
<div class="col s12 m8">
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
<div class="card">
<div class="card-content">
{{ import_results_form.hidden_tag() }}
<div class="row">
<div class="col s12">
{{ M.render_field(import_results_form.file, accept='.json', placeholder='Choose your .json file') }}
</div>
</div>
</div>
<div class="card-action right-align">
{{ M.render_field(import_results_form.submit, material_icon='send') }}
</div>
</div>
</form>
</div>
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading file...</h4>
<div class="progress">
<div class="determinate" style="width: 0%"></div>
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,52 @@
{% extends "nopaque.html.j2" %}
{% block page_content %}
<div class="col s12">
<p>This is an overview of all your imported results.</p>
</div>
<div class="col s12">
<div class="card">
<div class="card-content" id="results">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-results" class="search" type="search"></input>
<label for="search-results">Search results</label>
</div>
<ul class="pagination paginationTop"></ul>
{{ table }}
<ul class="pagination paginationBottom"></ul>
<ul class="pagination"></ul>
</div>
<div class="card-action right-align">
<a class="waves-effect waves-light btn" href="{{ url_for('services.import_results') }}">Import Results<i class="material-icons right">file_upload</i></a>
</div>
</div>
</div>
<script>
var options = {page: 10,
pagination: [
{
name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1
},
{
paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1
}
],
valueNames: ['query',
'match-count',
'corpus-name',
'corpus-creation-date',
'corpus-analysis-date',
'corpus-type']
};
var resultsList = new List('results', options);
</script>
{% endblock %}