mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-26 19:34:19 +00:00
267 lines
9.8 KiB
Django/Jinja
267 lines
9.8 KiB
Django/Jinja
{% extends "nopaque.html.j2" %}
|
|
|
|
{% set headline = ' ' %}
|
|
|
|
{% set full_width = True %}
|
|
{% set imported = True %}
|
|
|
|
{% block page_content %}
|
|
|
|
<div class="col s12">
|
|
<div class="card">
|
|
<div class="card-content" style="padding-top: 5px;
|
|
padding-bottom: 0px;">
|
|
<!-- Query form -->
|
|
<div class="row">
|
|
<form id="query-form">
|
|
<div class="col s12 m10">
|
|
<div class="input-field">
|
|
<i class="material-icons prefix">search</i>
|
|
<input disabled value="{{ query_metadata.query|escape }}" id="disabled" type="text" class="validate">
|
|
<label for="disabled">Query</label>
|
|
</div>
|
|
</div>
|
|
<div class="col s12 m2 right-align">
|
|
<br class="hide-on-small-only">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- entire results div/card -->
|
|
<div class="col s12" id="query-display">
|
|
<div class="card">
|
|
<div class="card-content" id="result-list" style="overflow: hidden;">
|
|
<div class="row" id="interactions-menu">
|
|
{% include 'interactions/infos.html.j2' %}
|
|
{% include 'interactions/display.html.j2' %}
|
|
{% include 'interactions/analysis.html.j2' %}
|
|
{% include 'interactions/cite.html.j2' %}
|
|
<div class="hide">
|
|
{# Hide those because they are not needed when inspecting results.
|
|
But some of their elements are being asked for by the client. #}
|
|
{% include 'interactions/export.html.j2' %}
|
|
{% include 'interactions/create.html.j2' %}
|
|
</div>
|
|
</div>
|
|
{% include 'tables/query_results.html.j2' %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scroll to top element -->
|
|
{% include 'interactions/scroll_to_top.html.j2' %}
|
|
|
|
<!-- Modals -->
|
|
{% include 'modals/show_metadata.html.j2' %}
|
|
{% include 'modals/context_modal.html.j2' %}
|
|
|
|
|
|
<script type="module">
|
|
/**
|
|
* First Phase:
|
|
* Document content is loaded and scripts are being imported and executed.
|
|
*/
|
|
|
|
// Import Client classes. Client handles the server client communication.
|
|
import {
|
|
Client,
|
|
ClientEventListener,
|
|
ListenerCallback,
|
|
} from '../../static/js/modules/corpus_analysis/client/Client.js';
|
|
/**
|
|
* Import Client listener functions which will listen for defined socket or
|
|
* javascript events.
|
|
*/
|
|
import {
|
|
recieveQueryStatus,
|
|
recieveQueryData,
|
|
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
|
|
// Import client listener callbacks so they can be registered to the listeners.
|
|
import {
|
|
prepareQueryData,
|
|
saveQueryData,
|
|
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
|
|
// Import Results class which will be used to save results data of a query etc.
|
|
import {
|
|
Results,
|
|
} from '../../static/js/modules/corpus_analysis/model/Results.js';
|
|
/**
|
|
* Import the ResultsList which can be understood as a View class that handles
|
|
* how the data from Results is represented to the user. The ViewEventListener
|
|
* is used to register listener functions which listen for events emitred by
|
|
* the Client.
|
|
*/
|
|
import {
|
|
ResultsList,
|
|
ViewEventListener,
|
|
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
|
|
// Import listener which will be registered to the ViewEventListener class.
|
|
import {
|
|
recieveClientNotification,
|
|
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
|
|
import {
|
|
scrollToTop,
|
|
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js'
|
|
/**
|
|
* Second Phase:
|
|
* Asynchronus and event driven code.
|
|
*/
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
/**
|
|
* Initializing the results object as a model holding all the data of a
|
|
* query. Also holds the metadata of one query and results data.
|
|
* After that initialize the ResultsList object as the View handeling the
|
|
* representation of the data for the user.
|
|
*/
|
|
let results = new Results();
|
|
let resultsList = new ResultsList('result-list', ResultsList.options);
|
|
// Import results data from json file.
|
|
const resultsJson = {{ query_result_file_content|tojson|safe }};
|
|
// Import metadata from DB passed to this view
|
|
const metaDataJson = {{ query_metadata|tojson|safe }};
|
|
// Initialize the client with dynamicMode set to false.
|
|
const client = new Client({'logging': true,
|
|
'dynamicMode': false,
|
|
'fullContext': metaDataJson.fullContext});
|
|
/**
|
|
* Register needed listeners and their callbacks. But we will
|
|
* just call the attached callbacks manually. Because dynamicMode is false.
|
|
*/
|
|
const listenForQueryStatus = new ClientEventListener('corpus_analysis_query',
|
|
recieveQueryStatus);
|
|
const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
|
|
prepareQueryData,
|
|
[client, results]);
|
|
listenForQueryStatus.setCallbacks([queryStatusCallback]);
|
|
const listenForQueryData = new ClientEventListener('corpus_analysis_query_results',
|
|
recieveQueryData);
|
|
const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
|
|
saveQueryData,
|
|
[client, results]);
|
|
listenForQueryData.setCallbacks([queryDataCallback]);
|
|
// Set the event listeners
|
|
client.setSocketEventListeners([
|
|
listenForQueryStatus,
|
|
listenForQueryData,
|
|
]);
|
|
/**
|
|
* Register resultsList listeners listening to notification events emitted by
|
|
* the Client class.
|
|
*/
|
|
const listenForClientNotification = new ViewEventListener('notify-view',
|
|
recieveClientNotification);
|
|
resultsList.setNotificationListeners([listenForClientNotification]);
|
|
resultsList.loadNotificationListeners();
|
|
// Get all needed HTMLElements for the following event listeners.
|
|
resultsList.getHTMLElements([
|
|
'.add-btn',
|
|
'.pagination',
|
|
'#display-options-form-expert_mode',
|
|
'#display-options-form-result_context',
|
|
'#display-options-form-results_per_page',
|
|
'#full-results-create',
|
|
'#full-results-export',
|
|
'#inspect-results-export',
|
|
'#meta-data-modal-content',
|
|
['#meta-data-modal', {
|
|
'preventScrolling': false,
|
|
'opacity': 0.0,
|
|
'dismissible': false,
|
|
'onOpenEnd': (() => {document.querySelector(".modal-overlay").remove()})
|
|
}
|
|
],
|
|
'#query-results-table',
|
|
'#show-meta-data',
|
|
'#sub-results-create',
|
|
'#sub-results-export',
|
|
]);
|
|
// Hide buttons which are not needed when just inspecting results
|
|
resultsList.inspectResultsExport.classList.add('hide');
|
|
// Execute client event listener callbacks manually because dynamicMode is false
|
|
client.eventListeners['corpus_analysis_query'].executeCallbacks([resultsJson]);
|
|
// Save meta data to results after the init callback from line above
|
|
results.metaData = metaDataJson;
|
|
client.eventListeners['corpus_analysis_query_results'].executeCallbacks([resultsJson]);
|
|
/**
|
|
* The following listener handles what functions are called when the user
|
|
* does use the page navigation to navigate to a new page.
|
|
*/
|
|
for (let element of resultsList.pagination) {
|
|
element.addEventListener("click", (event) => {
|
|
// Shows match context according to the user picked value on a new page.
|
|
resultsList.changeContext();
|
|
// De- or activates expertMode on new page depending on switch value.
|
|
if (resultsList.displayOptionsFormExpertMode.checked) {
|
|
resultsList.expertModeOn('query-display', results);
|
|
} else {
|
|
resultsList.expertModeOff('query-display');
|
|
}
|
|
// Activates inspect buttons on new page if client is not busy.
|
|
resultsList.toggleInspectButtons(client);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The following event Listener handles the expert mode switch for the list.
|
|
*/
|
|
resultsList.displayOptionsFormExpertMode.onchange = (event) => {
|
|
if (event.target.checked) {
|
|
resultsList.expertModeOn('query-display', results);
|
|
} else {
|
|
resultsList.expertModeOff('query-display');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* The following event Listener handles the add-btn and the inspect-btn
|
|
* onclick events via bubbleing.
|
|
*/
|
|
resultsList.queryResultsTable.addEventListener('click', (event) => {
|
|
let dataIndex;
|
|
if (event.target.classList.contains('inspect-btn')) {
|
|
dataIndex = parseInt(event.target.closest('tr').dataset.index);
|
|
resultsList.inspect(client, results, [dataIndex], 'inspect');
|
|
} else if (event.target.classList.contains('add-btn')) {
|
|
dataIndex = parseInt(event.target.closest('tr').dataset.index);
|
|
resultsList.addToSubResults(dataIndex, client);
|
|
}
|
|
})
|
|
|
|
/**
|
|
* Following event listeners handle the change of Context size per match and
|
|
* the number of matches shown per page.
|
|
*/
|
|
resultsList.displayOptionsFormResultsPerPage.onchange = (event) => {
|
|
resultsList.changeHitsPerPage(client, results);
|
|
};
|
|
resultsList.displayOptionsFormResultContext.onchange = (event) => {
|
|
resultsList.changeContext();
|
|
};
|
|
|
|
/**
|
|
* The following event listener handles the show metadata button and its
|
|
* functionality.
|
|
*/
|
|
resultsList.showMetaData.onclick = () => {
|
|
resultsList.metaDataModalContent.textContent = '';
|
|
let table = resultsList.createMetaDataForModal(results.metaData);
|
|
resultsList.metaDataModalContent.insertAdjacentHTML('afterbegin', table);
|
|
resultsList.metaDataModal.open();
|
|
let collapsibles = resultsList.metaDataModalContent.querySelectorAll(".text-metadata");
|
|
for (let collapsible of collapsibles) {
|
|
collapsible.onclick = () => {
|
|
let elems = resultsList.metaDataModalContent.querySelectorAll('.collapsible');
|
|
let instances = M.Collapsible.init(elems, {accordion: false});
|
|
resultsList.createTextDetails(results.metaData);
|
|
}
|
|
}
|
|
};
|
|
// Enable scroll to Top functionality.
|
|
scrollToTop('#headline', '#menu-scroll-to-top-div');
|
|
});
|
|
</script>
|
|
{% endblock %}
|