Bug fixes

This commit is contained in:
Patrick Jentsch 2021-12-01 16:03:55 +01:00
parent 12ec6be60b
commit 82745629bc
10 changed files with 83 additions and 62 deletions

View File

@ -1,4 +1,4 @@
from app import db, socketio
from app import db, hashids, socketio
from app.decorators import socketio_login_required
from app.models import Corpus
from flask import session
@ -57,7 +57,7 @@ from .cqi import * # noqa
def connect(auth):
# the auth variable is used in a hacky way. It contains the corpus id for
# which a corpus analysis session should be started.
corpus_id = auth['corpus_id']
corpus_id = hashids.decode(auth['corpus_id'])[0]
corpus = Corpus.query.get(corpus_id)
if corpus is None:
# return {'code': 404, 'msg': 'Not Found'}

View File

@ -28,6 +28,11 @@ def ressource_after_delete(mapper, connection, ressource):
@db.event.listens_for(QueryResult, 'after_insert')
def ressource_after_insert_handler(mapper, connection, ressource):
value = ressource.to_dict(backrefs=False, relationships=False)
if isinstance(ressource, Job):
value['inputs'] = {}
value['results'] = {}
elif isinstance(ressource, Corpus):
value['files'] = {}
jsonpatch = [
{'op': 'add', 'path': ressource.jsonpatch_path, 'value': value}
]

View File

@ -544,7 +544,7 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
@property
def jsonpatch_path(self):
return f'/{self.corpus.jsonpatch_path}/files/{self.hashid}'
return f'{self.corpus.jsonpatch_path}/files/{self.hashid}'
@property
def path(self):
@ -601,6 +601,7 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
if backrefs:
dict_corpus_file['corpus'] = self.corpus.to_dict(
backrefs=True, relationships=False)
return dict_corpus_file
class Corpus(HashidMixin, db.Model):
@ -705,7 +706,7 @@ class Corpus(HashidMixin, db.Model):
backrefs=True, relationships=False)
if relationships:
dict_corpus['files'] = {
x.id: x.to_dict(backrefs=False, relationships=True)
x.hashid: x.to_dict(backrefs=False, relationships=True)
for x in self.files
}
return dict_corpus

View File

@ -65,33 +65,9 @@ class App {
}
usersPatchHandler(patch) {
let jobId;
let listener;
let match;
let operation;
let re;
let relationship;
let ressourceId;
let userId;
for (operation of patch.filter(operation => operation.op === 'add')) {
re = new RegExp(`^/users/([A-Za-z0-9]*)/corpora/([A-Za-z0-9]*)/(files)`);
if (re.test(operation.path)) {
[match, userId, ressourceId, relationship] = operation.path.match(re);
if (!(relationship in this.users[userId].corpora[ressourceId])) {
this.users[userId].corpora[ressourceId][relationship] = {};
}
continue;
}
re = new RegExp(`^/users/([A-Za-z0-9]*)/jobs/([A-Za-z0-9]*)/(inputs|results)`);
if (re.test(operation.path)) {
[match, userId, ressourceId, relationship] = operation.path.match(re);
if (!(relationship in this.users[userId].jobs[ressourceId])) {
this.users[userId].jobs[ressourceId][relationship] = {};
}
continue;
}
}
console.log(patch);
this.data = jsonpatch.apply_patch(this.data, patch);
for (listener of this.eventListeners['users.patch']) {listener(patch);}
}

View File

@ -2,7 +2,11 @@ class CQiClient {
constructor(corpusId) {
this.socket = io(
'/corpora/corpus/corpus_analysis',
{auth: {corpus_id: corpusId}, transports: ['websocket'], upgrade: false}
{
auth: {corpus_id: corpusId},
transports: ['websocket'],
upgrade: false
}
);
this.connected = false;
this.corpora = new CQiCorpusCollection(this.socket);
@ -55,7 +59,8 @@ class CQiCorpusCollection {
get(corpusName) {
return new Promise((resolve, reject) => {
let args = {corpus_name: corpusName};
const args = {corpus_name: corpusName};
this.socket.emit('cqi.corpora.get', args, response => {
if (response.code === 200) {
resolve(new CQiCorpus(this.socket, response.payload));
@ -95,7 +100,8 @@ class CQiCorpus {
drop() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.name};
const args = {corpus_name: this.name};
this.socket.emit('cqi.corpora.corpus.drop', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -108,11 +114,12 @@ class CQiCorpus {
query(subcorpus_name, queryString) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.name,
subcorpus_name: subcorpus_name,
query: queryString
};
this.socket.emit('cqi.corpora.corpus.query', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -126,7 +133,8 @@ class CQiCorpus {
// nopaque specific CQi extension
paginate(page=1, perPage=20) {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.name, page: page, per_page: perPage};
const args = {corpus_name: this.name, page: page, per_page: perPage};
this.socket.emit('cqi.corpora.corpus.paginate', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -138,7 +146,8 @@ class CQiCorpus {
}
updateDb() {
let args = {corpus_name: this.name};
const args = {corpus_name: this.name};
this.socket.emit('cqi.corpora.corpus.update_db', args);
}
}
@ -152,8 +161,11 @@ class CQiAlignmentAttributeCollection {
get(alignmentAttributeName) {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name,
alignment_attribute_name: alignmentAttributeName};
const args = {
corpus_name: this.corpus.name,
alignment_attribute_name: alignmentAttributeName
};
this.socket.emit('cqi.corpora.corpus.alignment_attributes.get', args, response => {
if (response.code === 200) {
resolve(new CQiAlignmentAttribute(this.socket, this.corpus, response.payload));
@ -166,7 +178,8 @@ class CQiAlignmentAttributeCollection {
list() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name};
const args = {corpus_name: this.corpus.name};
this.socket.emit('cqi.corpus.alignment_attributes.list', args, response => {
if (response.code === 200) {
resolve(response.payload.map(x => {return new CQiAlignmentAttribute(this.socket, this.corpus, x);}));
@ -197,10 +210,11 @@ class CQiPositionalAttributeCollection {
get(positionalAttributeName) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
positional_attribute_name: positionalAttributeName
};
this.socket.emit('cqi.corpora.corpus.positional_attributes.get', args, response => {
if (response.code === 200) {
resolve(new CQiPositionalAttribute(this.socket, this.corpus, response.payload));
@ -213,7 +227,8 @@ class CQiPositionalAttributeCollection {
list() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name};
const args = {corpus_name: this.corpus.name};
this.socket.emit('cqi.corpus.positional_attributes.list', args, response => {
if (response.code === 200) {
resolve(response.payload.map(x => {return new CQiPositionalAttribute(this.socket, this.corpus, x);}));
@ -245,10 +260,11 @@ class CQiStructuralAttributeCollection {
get(structuralAttributeName) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
structural_attribute_name: structuralAttributeName
};
this.socket.emit('cqi.corpora.corpus.structural_attributes.get', args, response => {
if (response.code === 200) {
resolve(new CQiStructuralAttribute(this.socket, this.corpus, response.payload));
@ -261,7 +277,8 @@ class CQiStructuralAttributeCollection {
list() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name};
const args = {corpus_name: this.corpus.name};
this.socket.emit('cqi.corpus.structural_attributes.list', args, response => {
if (response.code === 200) {
resolve(response.payload.map(x => {return new CQiStructuralAttribute(this.socket, this.corpus, x);}));
@ -293,7 +310,10 @@ class CQiSubcorpusCollection {
get(subcorpusName) {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name, subcorpus_name: subcorpusName};
const args = {
corpus_name: this.corpus.name,
subcorpus_name: subcorpusName
};
this.socket.emit('cqi.corpora.corpus.subcorpora.get', args, response => {
if (response.code === 200) {
resolve(new CQiSubcorpus(this.socket, this.corpus, response.payload));
@ -306,7 +326,8 @@ class CQiSubcorpusCollection {
list() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name};
const args = {corpus_name: this.corpus.name};
this.socket.emit('cqi.corpora.corpus.subcorpora.list', args, response => {
if (response.code === 200) {
resolve(response.payload.map(x => {return new CQiSubcorpus(this.socket, this.corpus, x);}));
@ -330,7 +351,8 @@ class CQiSubcorpus {
drop() {
return new Promise((resolve, reject) => {
let args = {corpus_name: this.corpus.name, subcorpus_name: this.name};
const args = {corpus_name: this.corpus.name, subcorpus_name: this.name};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.drop', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -343,13 +365,14 @@ class CQiSubcorpus {
dump(field, first, last) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
subcorpus_name: this.name,
field: field,
first: first,
last: last
};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.dump', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -362,11 +385,12 @@ class CQiSubcorpus {
export(context=50) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
subcorpus_name: this.name,
context: context
};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.export', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -379,13 +403,14 @@ class CQiSubcorpus {
fdst_1(cutoff, field, attribute) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
subcorpus_name: this.name,
cutoff: cutoff,
field: field,
attribute: attribute
};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.fdist_1', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -398,7 +423,7 @@ class CQiSubcorpus {
fdst_2(cutoff, field1, attribute1, field2, attribute2) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
subcorpus_name: this.name,
cutoff: cutoff,
@ -407,6 +432,7 @@ class CQiSubcorpus {
field2: field2,
attribute2: attribute2
};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.fdist_1', args, response => {
if (response.code === 200) {
resolve(response.payload);
@ -420,13 +446,14 @@ class CQiSubcorpus {
// nopaque specific CQi extension
paginate(page=1, perPage=20, context=50) {
return new Promise((resolve, reject) => {
let args = {
const args = {
corpus_name: this.corpus.name,
subcorpus_name: this.name,
page: page,
per_page: perPage,
context: context
};
this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.paginate', args, response => {
if (response.code === 200) {
resolve(response.payload);

View File

@ -69,7 +69,7 @@ class CorpusAnalysisApp {
this.elements.initError.classList.remove('hide');
this.elements.initProgress.classList.add('hide');
if ('payload' in cQiError && 'code' in cQiError.payload && 'msg' in cQiError.payload) {
nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
}
}
);

View File

@ -71,7 +71,7 @@ class CorpusAnalysisConcordance {
this.elements.error.innerText = JSON.stringify(cQiError);
this.elements.error.classList.remove('hide');
if ('payload' in cQiError && 'code' in cQiError.payload && 'msg' in cQiError.payload) {
nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
}
this.elements.progress.classList.add('hide');
this.app.enableActionElements();
@ -166,7 +166,7 @@ class CorpusAnalysisConcordance {
let subcorpus = this.data.subcorpora[this.settings.selectedSubcorpus];
subcorpus.o.drop().then(
cQiStatus => {
nopaque.appClient.flash(`${subcorpus.o.name} deleted`, 'corpus');
app.flash(`${subcorpus.o.name} deleted`, 'corpus');
delete this.data.subcorpora[subcorpus.o.name];
this.settings.selectedSubcorpus = undefined;
for (let subcorpusName in this.data.subcorpora) {
@ -187,7 +187,7 @@ class CorpusAnalysisConcordance {
}
},
cQiError => {
nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
}
);
});

View File

@ -49,7 +49,7 @@ class CorpusAnalysisReader {
this.elements.error.innerText = JSON.stringify(error);
this.elements.error.classList.remove('hide');
if ('payload' in error && 'code' in error.payload && 'msg' in error.payload) {
nopaque.appClient.flash(`${error.payload.code}: ${error.payload.msg}`, 'error');
app.flash(`${error.payload.code}: ${error.payload.msg}`, 'error');
}
this.elements.progress.classList.add('hide');
this.app.enableActionElements();
@ -75,8 +75,12 @@ class CorpusAnalysisReader {
}
clearCorpus() {
let pAttrElement;
let pAttrElements;
// Destroy with .p-attr elements associated Materialize tooltips
for (let pAttrElement of this.elements.corpus.querySelectorAll('.p-attr.tooltipped')) {
pAttrElements = this.elements.corpus.querySelectorAll('.p-attr.tooltipped');
for (pAttrElement of pAttrElements) {
M.Tooltip.getInstance(pAttrElement)?.destroy();
}
this.elements.corpus.innerHTML = `
@ -88,8 +92,10 @@ class CorpusAnalysisReader {
}
renderCorpus() {
let item;
this.clearCorpus();
let item = this.data.corpus.p.items[0];
item = this.data.corpus.p.items[0];
this.elements.corpus.innerHTML += `
<p>${this.cposRange2HTML(item[0], item[item.length - 1])}</p>
`.trim();
@ -103,6 +109,10 @@ class CorpusAnalysisReader {
}
renderCorpusPagination() {
let i;
let page;
let paginateTriggerElement;
this.clearCorpusPagination();
if (this.data.corpus.p.pages === 0) {return;}
this.elements.corpusPagination.innerHTML += `
@ -119,7 +129,7 @@ class CorpusAnalysisReader {
</a>
</li>
`.trim();
for (let i = 1; i <= this.data.corpus.p.pages; i++) {
for (i = 1; i <= this.data.corpus.p.pages; i++) {
this.elements.corpusPagination.innerHTML += `
<li class="${i === this.data.corpus.p.page ? 'active' : 'waves-effect'}">
<a class="corpus-analysis-action pagination-trigger" ${i === this.data.corpus.p.page ? '' : 'data-target="' + i + '"'}>${i}</a>
@ -140,10 +150,10 @@ class CorpusAnalysisReader {
</a>
</li>
`.trim();
for (let paginateTriggerElement of this.elements.corpusPagination.querySelectorAll('.pagination-trigger[data-target]')) {
for (paginateTriggerElement of this.elements.corpusPagination.querySelectorAll('.pagination-trigger[data-target]')) {
paginateTriggerElement.addEventListener('click', event => {
event.preventDefault();
let page = parseInt(paginateTriggerElement.dataset.target);
page = parseInt(paginateTriggerElement.dataset.target);
this.page(page);
});
}
@ -151,10 +161,11 @@ class CorpusAnalysisReader {
}
cposRange2HTML(firstCpos, lastCpos) {
let cpos;
let prevPAttr, pAttr, nextPAttr;
let isEntityStart, isEntityEnd;
let html = '';
for (let cpos = firstCpos; cpos <= lastCpos; cpos++) {
for (cpos = firstCpos; cpos <= lastCpos; cpos++) {
prevPAttr = cpos > firstCpos ? this.data.corpus.p.lookups.cpos_lookup[cpos - 1] : null;
pAttr = this.data.corpus.p.lookups.cpos_lookup[cpos];
nextPAttr = cpos < lastCpos ? this.data.corpus.p.lookups.cpos_lookup[cpos + 1] : null;

View File

@ -5,6 +5,7 @@ class CorpusFileList extends RessourceList {
}
init(user) {
console.log(user);
this._init(user.corpora[this.corpusId].files);
}

View File

@ -65,7 +65,7 @@
<script src="{{ ASSET_URL }}"></script>
{% endassets %}
<script>
let corpusAnalysisApp = new CorpusAnalysisApp({{ corpus.id }});
let corpusAnalysisApp = new CorpusAnalysisApp('{{ corpus.hashid }}');
let corpusAnalysisConcordance = new CorpusAnalysisConcordance(corpusAnalysisApp);
let corpusAnalysisReader = new CorpusAnalysisReader(corpusAnalysisApp);
corpusAnalysisApp.init();