mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
Update
This commit is contained in:
parent
bface71503
commit
2c93f02c11
@ -95,6 +95,24 @@ def pj_corpus_analysis_query(query):
|
||||
client.status = 'ready'
|
||||
|
||||
|
||||
@socketio.on('pj_inspect-match')
|
||||
@socketio_login_required
|
||||
def pj_corpus_analysis_query(payload):
|
||||
logger.warning(payload)
|
||||
client = pj_corpus_analysis_clients.get(request.sid)
|
||||
if client is None:
|
||||
socketio.emit('query', '[424]: Failed Dependency',
|
||||
room=request.sid)
|
||||
return
|
||||
# Get more context for given match CPOS
|
||||
corpus = client.corpora.get('CORPUS')
|
||||
s = corpus.attributes.structural.get('s')
|
||||
match_context = s.export(payload["cpos"][0], payload["cpos"][1],
|
||||
context=3,
|
||||
expand_lists=True)
|
||||
socketio.emit('pj_match_context', {"payload": match_context}, room=request.sid)
|
||||
|
||||
|
||||
def pj_corpus_analysis_session_handler(app, corpus_id, user_id, session_id):
|
||||
with app.app_context():
|
||||
''' Setup analysis session '''
|
||||
|
@ -4,24 +4,6 @@ class CorpusAnalysisClient {
|
||||
this.corpusId = corpusId;
|
||||
this.displays = {};
|
||||
this.socket = socket;
|
||||
this.resultList = {}; // why do you save it here? we have a global variable results
|
||||
|
||||
// js list options and intialization
|
||||
let displayOptionsData = this.getDisplayOptions(displayOptionsFormElement);
|
||||
let resultListOptions = {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>`};
|
||||
this.resultList = new ResultList("result-list", resultListOptions);
|
||||
|
||||
// socket on event fpr corpous analysis initialization
|
||||
socket.on("pj_corpus_analysis_init", (response) => {
|
||||
@ -97,31 +79,9 @@ class CorpusAnalysisClient {
|
||||
if (this.displays.query != undefined) {
|
||||
this.displays.query.setVisibilityByStatus("waiting");
|
||||
}
|
||||
this.resultList.clear(); // empty list for new query
|
||||
nopaque.socket.emit("pj_corpus_analysis_query", queryStr);
|
||||
}
|
||||
|
||||
getQueryStr(queryFormElement) {
|
||||
// gets query
|
||||
let queryFormData;
|
||||
let queryStr;
|
||||
queryFormData = new FormData(queryFormElement);
|
||||
queryStr = queryFormData.get("query-form-query");
|
||||
return queryStr
|
||||
}
|
||||
|
||||
getDisplayOptions(displayOptionsFormElement) {
|
||||
// gets display options parameters
|
||||
let displayOptionsFormData
|
||||
let displayOptionsData;
|
||||
displayOptionsFormData = new FormData(displayOptionsFormElement);
|
||||
displayOptionsData = {"resultsPerPage": displayOptionsFormData.get("display-options-form-results_per_page"),
|
||||
"resultsContex": displayOptionsFormData.get("display-options-form-result_context"),
|
||||
"expertMode": displayOptionsFormData.get("display-options-form-expert_mode")};
|
||||
console.log(displayOptionsData);
|
||||
return displayOptionsData
|
||||
}
|
||||
|
||||
setCallback(type, callback) {
|
||||
// saves callback functions into an object. Key is function type, callback
|
||||
// is the callback function
|
||||
|
8
app/static/js/nopaque.Results.js
Normal file
8
app/static/js/nopaque.Results.js
Normal file
@ -0,0 +1,8 @@
|
||||
class Results {
|
||||
constructor(results, resultsList) {
|
||||
this.resultsJSON = results;
|
||||
this.resultsList = resultsList;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -102,7 +102,7 @@ function helperSendQuery(queryData) {
|
||||
}],
|
||||
valueNames: ["titles", "lc", "c", "rc", {data: ["index"]}],
|
||||
item: `<span></span>`};
|
||||
resultList = new ResultList('result-list', resultListOptions);
|
||||
resultList = new ResultsList('result-list', resultListOptions);
|
||||
resultList.clear(); // empty list for new query
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,11 @@ function querySetup(payload) {
|
||||
textLookupCountElement.innerText = "0";
|
||||
matchCountElement.innerText = payload.match_count;
|
||||
// always re initializes results to delete old results from it
|
||||
results = {};
|
||||
results["matches"] = []; // list of all c with lc and rc
|
||||
results["cpos_lookup"] = {}; // object contains all cpos as key value pair
|
||||
results["text_lookup"] = {}; // same as above for all text ids
|
||||
results["match_count"] = payload.match_count;
|
||||
results["query"] = client.getQueryStr(queryFormElement);
|
||||
results.resultsJSON["matches"] = []; // list of all c with lc and rc
|
||||
results.resultsJSON["cpos_lookup"] = {}; // object contains all cpos as key value pair
|
||||
results.resultsJSON["text_lookup"] = {}; // same as above for all text ids
|
||||
results.resultsJSON["match_count"] = payload.match_count;
|
||||
results.resultsJSON["query"] = getQueryStr(queryFormElement);
|
||||
}
|
||||
|
||||
function queryRenderResults(payload) {
|
||||
@ -29,27 +28,32 @@ function queryRenderResults(payload) {
|
||||
queryResultsExportElement.classList.remove("disabled");
|
||||
activateInspect();
|
||||
}
|
||||
if (payload.chunk.cpos_ranges == true) {
|
||||
results.resultsJSON["cpos_ranges"] = true;
|
||||
} else {
|
||||
results.resultsJSON["cpos_ranges"] = false;
|
||||
}
|
||||
// update progress bar
|
||||
queryResultsDeterminateElement.style.width = `${payload.progress}%`;
|
||||
// building the result list js list from incoming chunk
|
||||
resultItems = []; // list for holding every row item
|
||||
// get infos for full match row
|
||||
for (let [index, match] of payload.chunk.matches.entries()) {
|
||||
resultItems.push({...match, ...{"index": index + results.matches.length}});
|
||||
resultItems.push({...match, ...{"index": index + results.resultsJSON.matches.length}});
|
||||
}
|
||||
client.resultList.add(resultItems, (items) => {
|
||||
resultsList.add(resultItems, (items) => {
|
||||
for (let item of items) {
|
||||
item.elm = client.resultList.createResultRowElement(item, payload.chunk);
|
||||
item.elm = resultsList.createResultRowElement(item, payload.chunk);
|
||||
}
|
||||
client.resultList.update();
|
||||
resultsList.update();
|
||||
changeContext(); // sets lr context on first result load
|
||||
});
|
||||
// incorporating new chunk results into full results
|
||||
results.matches.push(...payload.chunk.matches);
|
||||
Object.assign(results.cpos_lookup, payload.chunk.cpos_lookup);
|
||||
Object.assign(results.text_lookup, payload.chunk.text_lookup);
|
||||
results.resultsJSON.matches.push(...payload.chunk.matches);
|
||||
Object.assign(results.resultsJSON.cpos_lookup, payload.chunk.cpos_lookup);
|
||||
Object.assign(results.resultsJSON.text_lookup, payload.chunk.text_lookup);
|
||||
// show user current and total match count
|
||||
receivedMatchCountElement.innerText = `${results.matches.length}`;
|
||||
textLookupCountElement.innerText = `${Object.keys(results.text_lookup).length}`;
|
||||
console.log("Results recieved:", results);
|
||||
receivedMatchCountElement.innerText = `${results.resultsJSON.matches.length}`;
|
||||
textLookupCountElement.innerText = `${Object.keys(results.resultsJSON.text_lookup).length}`;
|
||||
console.log("Results recieved:", results.resultsJSON);
|
||||
}
|
@ -118,7 +118,7 @@ RessourceList.options = {
|
||||
};
|
||||
|
||||
|
||||
class ResultList extends List {
|
||||
class ResultsList extends List {
|
||||
|
||||
createResultRowElement(item, chunk) {
|
||||
let values, cpos, token, matchRowElement, lcCellElement, hitCellElement, rcCellElement, textTitlesCellElement, matchNrElement, lc, c, rc;
|
||||
|
@ -1,3 +1,28 @@
|
||||
// ###### Helper functions ######
|
||||
|
||||
// get query as string from form Element
|
||||
function getQueryStr(queryFormElement) {
|
||||
// gets query
|
||||
let queryFormData;
|
||||
let queryStr;
|
||||
queryFormData = new FormData(queryFormElement);
|
||||
queryStr = queryFormData.get("query-form-query");
|
||||
return queryStr
|
||||
}
|
||||
|
||||
// get display options from display options form element
|
||||
function getDisplayOptions(displayOptionsFormElement) {
|
||||
// gets display options parameters
|
||||
let displayOptionsFormData
|
||||
let displayOptionsData;
|
||||
displayOptionsFormData = new FormData(displayOptionsFormElement);
|
||||
displayOptionsData = {"resultsPerPage": displayOptionsFormData.get("display-options-form-results_per_page"),
|
||||
"resultsContex": displayOptionsFormData.get("display-options-form-result_context"),
|
||||
"expertMode": displayOptionsFormData.get("display-options-form-expert_mode")};
|
||||
console.log(displayOptionsData);
|
||||
return displayOptionsData
|
||||
}
|
||||
|
||||
// ###### Download results functions ######
|
||||
// TODO: Maybe write these as class functions? For this maybe create a result class
|
||||
|
||||
@ -13,7 +38,7 @@ function createDownloadFilename() {
|
||||
today = new Date();
|
||||
currentDate = today.getUTCFullYear() + '-' + (today.getUTCMonth() +1) + '-' + today.getUTCDate();
|
||||
currentTime = today.getUTCHours() + ":" + today.getUTCMinutes() + ":" + today.getUTCSeconds();
|
||||
safeFilename = results["query"].replace(/[^a-z0-9_-]/gi, "_");
|
||||
safeFilename = results.resultsJSON["query"].replace(/[^a-z0-9_-]/gi, "_");
|
||||
resultFilename = "UTC-" + currentDate + "_" + currentTime + "_" + safeFilename;
|
||||
return resultFilename
|
||||
}
|
||||
@ -23,7 +48,7 @@ function downloadJSONRessource(resultFilename) {
|
||||
let dataStr;
|
||||
let downloadElement;
|
||||
// stringify JSON object for json download
|
||||
dataStr = JSON.stringify(results, undefined, "\t"); // use tabs to save some space
|
||||
dataStr = JSON.stringify(results.resultsJSON, undefined, "\t"); // use tabs to save some space
|
||||
// get downloadResultsElement
|
||||
downloadElement = document.getElementById("download-results-json");
|
||||
// start actual download
|
||||
@ -57,32 +82,33 @@ function activateInspect(progress) {
|
||||
}
|
||||
|
||||
//gets result cpos infos for one dataIndex to send back to the server
|
||||
function inspect(dataIndex) {
|
||||
function inspect(dataIndex, socket) {
|
||||
console.log("Inspect!");
|
||||
console.log(result["matches"][dataIndex]["c"]);
|
||||
console.log(results.resultsJSON.matches[dataIndex].c);
|
||||
contextModal.open();
|
||||
nopaque.socket.emit("inspect_match", {"cpos": result["matches"][dataIndex]["c"]});
|
||||
socket.emit("pj_inspect_match",
|
||||
{"payload": {"cpos": results.resultsJSON.matches[dataIndex].c} });
|
||||
}
|
||||
|
||||
function showMatchContext(message) {
|
||||
function showMatchContext(payload) {
|
||||
let contextResultsElement;
|
||||
let sentenceElement
|
||||
let token;
|
||||
let tokenElement;
|
||||
console.log("###### match_context ######");
|
||||
console.log("Incoming data:", message);
|
||||
console.log("Incoming data:", payload);
|
||||
contextResultsElement = document.getElementById("context-results");
|
||||
contextResultsElement.innerHTML = "<p> </p>";
|
||||
document.getElementById("context-modal-loading").classList.add("hide");
|
||||
document.getElementById("context-modal-ready").classList.remove("hide");
|
||||
|
||||
for (let [key, value] of Object.entries(message['context_s_cpos'])) {
|
||||
for (let [key, value] of Object.entries(payload['context_s_cpos'])) {
|
||||
sentenceElement = document.createElement("p");
|
||||
for (let cpos of value) {
|
||||
token = message["cpos_lookup"][cpos];
|
||||
token = payload["cpos_lookup"][cpos];
|
||||
tokenElement = document.createElement("span");
|
||||
tokenElement.classList.add("token");
|
||||
if (message["match_cpos_list"].includes(cpos)) {
|
||||
if (payload["match_cpos_list"].includes(cpos)) {
|
||||
tokenElement.classList.add("bold");
|
||||
tokenElement.classList.add("light-green");
|
||||
}
|
||||
@ -90,7 +116,7 @@ function showMatchContext(message) {
|
||||
tokenElement.innerText = token["word"];
|
||||
var expertModeSwitchElement = document.getElementById("expert-mode-switch");
|
||||
if (expertModeSwitchElement.checked) {
|
||||
expertModeOn([tokenElement], message);
|
||||
expertModeOn([tokenElement], payload);
|
||||
}
|
||||
sentenceElement.append(tokenElement);
|
||||
sentenceElement.append(document.createTextNode(" "));
|
||||
|
@ -238,7 +238,7 @@ server side -->
|
||||
var exportModal;
|
||||
// create some global variables
|
||||
var result; // will gradually be filled with JSON result chunks of a query
|
||||
var resultList; // the list.js new ResultList object displaying the results
|
||||
var resultsList; // the list.js new ResultList object displaying the results
|
||||
var queryFinished; // bool flag that shows if query is finished or not
|
||||
var analysisClientStatus; // Object holding: {<sid>: 'running'|'idle'}
|
||||
var sessionId; // the clients current session id
|
||||
|
@ -195,28 +195,54 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Context modal used for detailed information about one match -->
|
||||
<div id="context-modal" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>Match context and information</h4>
|
||||
<div id="context-modal-loading">
|
||||
<div class="progress">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="context-modal-ready" class="hide">
|
||||
<div id="context-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="left waves-effect waves-light btn">Export</a>
|
||||
<a href="#!" class="modal-close waves-effect waves-light red btn">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="{{ url_for('static', filename='js/nopaque.CorpusAnalysisClient.js') }}">
|
||||
</script>
|
||||
<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.pj_analyse_corpus.js') }}">
|
||||
</script>
|
||||
<script>
|
||||
// ###### Defining global variables used in other functions ######
|
||||
var results; // full JSON object holding match results
|
||||
var results; // results object
|
||||
var resultsJSON; // full JSON object holding match results
|
||||
var resultsList; // resultsList object
|
||||
var queryFormElement; // the query form
|
||||
var collapsibleElements; // all collapsibles on site
|
||||
var queryResultsProgressElement; // Div element holding the progress bar
|
||||
var queryResultsDeterminateElement; // The progress bar for recieved results
|
||||
var queryResultsUserFeedbackElement; // Element showing match count|total etc
|
||||
var queryResultsExportElement; // Download button opens download modal
|
||||
var exportModal;
|
||||
var exportModal; // Download options modal
|
||||
var contextModal; // Modal to open on inspect for further match context
|
||||
var initModal;
|
||||
var downloadResultsJSONElement; // button for downloading results as JSON
|
||||
var displayOptionsFormElement;
|
||||
|
||||
// ###### Initialize variables ######
|
||||
contextModal = document.getElementById("context-modal");
|
||||
exportModal = document.getElementById("query-results-download-modal");
|
||||
queryFormElement = document.getElementById("query-form");
|
||||
queryResultsProgressElement = document.getElementById("query-results-progress");
|
||||
queryResultsDeterminateElement = document.getElementById("query-results-determinate");
|
||||
@ -224,6 +250,22 @@
|
||||
queryResultsExportElement = document.getElementById("query-results-export");
|
||||
displayOptionsFormElement = document.getElementById("display-options-form");
|
||||
|
||||
// js list options and intialization
|
||||
let displayOptionsData = getDisplayOptions(displayOptionsFormElement);
|
||||
let 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>`};
|
||||
|
||||
// ###### Set some css options ######
|
||||
// get collapsibles to alter options of those
|
||||
var collapsibleElements = document.querySelector('.collapsible.expandable');
|
||||
@ -244,14 +286,18 @@
|
||||
//set accordion of collapsibles to false
|
||||
M.Collapsible.init(collapsibleElements, {accordion: false});
|
||||
// creates some models on DOMContentLoaded
|
||||
exportModal = M.Modal.init(document.getElementById("query-results-download-modal"),
|
||||
{"dismissible": true});
|
||||
initModal = M.Modal.init(initDisplayElement, {dismissible: false});
|
||||
contextModal = M.Modal.init(contextModal, {"dismissible": true});
|
||||
exportModal = M.Modal.init(exportModal, {"dismissible": true});
|
||||
initModal = M.Modal.init(initDisplayElement, {"dismissible": false});
|
||||
// Init corpus analysis components
|
||||
resultsJSON = {};
|
||||
resultsList = new ResultsList("result-list", resultsListOptions);
|
||||
results = new Results(resultsJSON, resultsList);
|
||||
initDisplay = new CorpusAnalysisDisplay(initDisplayElement);
|
||||
queryDisplay = new CorpusAnalysisDisplay(queryDisplayElement);
|
||||
client = new CorpusAnalysisClient({{ corpus_id }}, nopaque.socket);
|
||||
initModal.open();
|
||||
|
||||
// set displays visibilitys and Callback functions
|
||||
client.setDisplay("init", initDisplay);
|
||||
client.setCallback("init", () => {
|
||||
@ -272,12 +318,18 @@
|
||||
queryFormElement.addEventListener("submit", (event) => {
|
||||
// Prevent page from reloading on submit
|
||||
event.preventDefault();
|
||||
// empty list for new query
|
||||
resultsList.clear();
|
||||
// Get query string and send query to server
|
||||
let queryStr = client.getQueryStr(queryFormElement);
|
||||
let queryStr = getQueryStr(queryFormElement);
|
||||
client.sendQuery(queryStr);
|
||||
});
|
||||
|
||||
// get context of one match if inspected via socket.io
|
||||
nopaque.socket.on("pj_match_context", showMatchContext);
|
||||
});
|
||||
|
||||
|
||||
// Add onclick to open download modal wen Export Results button is pressed
|
||||
queryResultsExportElement.onclick = function() {
|
||||
exportModal.open();
|
||||
|
Loading…
Reference in New Issue
Block a user