mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 17:25:44 +00:00
Merge branch 'development'
This commit is contained in:
commit
903310c17f
@ -11,8 +11,3 @@ class AdminEditUserForm(FlaskForm):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.role.choices = [(x.hashid, x.name) for x in Role.query.all()]
|
self.role.choices = [(x.hashid, x.name) for x in Role.query.all()]
|
||||||
|
|
||||||
def prefill(self, user):
|
|
||||||
''' Pre-fill the form with data of an exististing user '''
|
|
||||||
self.confirmed.data = user.confirmed
|
|
||||||
self.role.data = user.role.hashid
|
|
||||||
|
@ -30,7 +30,7 @@ def index():
|
|||||||
|
|
||||||
@bp.route('/users')
|
@bp.route('/users')
|
||||||
def users():
|
def users():
|
||||||
json_users = [x.to_json(backrefs=True) for x in User.query.all()]
|
json_users = [x.to_json_serializeable(backrefs=True) for x in User.query.all()]
|
||||||
return render_template(
|
return render_template(
|
||||||
'admin/users.html.j2',
|
'admin/users.html.j2',
|
||||||
json_users=json_users,
|
json_users=json_users,
|
||||||
@ -48,15 +48,16 @@ def user(user_id):
|
|||||||
def edit_user(user_id):
|
def edit_user(user_id):
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
admin_edit_user_form = AdminEditUserForm(
|
admin_edit_user_form = AdminEditUserForm(
|
||||||
obj=user,
|
data={'confirmed': user.confirmed, 'role': user.role.hashid},
|
||||||
prefix='admin-edit-user-form'
|
prefix='admin-edit-user-form'
|
||||||
)
|
)
|
||||||
edit_general_settings_form = EditGeneralSettingsForm(
|
edit_general_settings_form = EditGeneralSettingsForm(
|
||||||
user,
|
user,
|
||||||
obj=user,
|
data=user.to_json_serializeable(),
|
||||||
prefix='edit-general-settings-form'
|
prefix='edit-general-settings-form'
|
||||||
)
|
)
|
||||||
edit_notification_settings_form = EditNotificationSettingsForm(
|
edit_notification_settings_form = EditNotificationSettingsForm(
|
||||||
|
data=user.to_json_serializeable(),
|
||||||
prefix='edit-notification-settings-form'
|
prefix='edit-notification-settings-form'
|
||||||
)
|
)
|
||||||
if (admin_edit_user_form.submit.data
|
if (admin_edit_user_form.submit.data
|
||||||
@ -83,7 +84,6 @@ def edit_user(user_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('Your changes have been saved')
|
flash('Your changes have been saved')
|
||||||
return redirect(url_for('.edit_user', user_id=user.id))
|
return redirect(url_for('.edit_user', user_id=user.id))
|
||||||
edit_notification_settings_form.prefill(user)
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'admin/edit_user.html.j2',
|
'admin/edit_user.html.j2',
|
||||||
admin_edit_user_form=admin_edit_user_form,
|
admin_edit_user_form=admin_edit_user_form,
|
||||||
|
@ -51,7 +51,7 @@ def tesseract_ocr_pipeline_models():
|
|||||||
def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
||||||
tesseract_ocr_pipeline_model = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
tesseract_ocr_pipeline_model = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
||||||
form = EditTesseractOCRPipelineModelForm(
|
form = EditTesseractOCRPipelineModelForm(
|
||||||
obj=tesseract_ocr_pipeline_model,
|
data=tesseract_ocr_pipeline_model.to_json_serializeable(),
|
||||||
prefix='edit-tesseract-ocr-pipeline-model-form'
|
prefix='edit-tesseract-ocr-pipeline-model-form'
|
||||||
)
|
)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
@ -148,7 +148,7 @@ def spacy_nlp_pipeline_models():
|
|||||||
def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
||||||
spacy_nlp_pipeline_model = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
spacy_nlp_pipeline_model = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
||||||
form = EditSpaCyNLPPipelineModelForm(
|
form = EditSpaCyNLPPipelineModelForm(
|
||||||
obj=spacy_nlp_pipeline_model,
|
data=spacy_nlp_pipeline_model.to_json_serializeable(),
|
||||||
prefix='edit-spacy-nlp-pipeline-model-form'
|
prefix='edit-spacy-nlp-pipeline-model-form'
|
||||||
)
|
)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
@ -54,7 +54,6 @@ def convert_corpus(json_corpus, user, corpus_dir):
|
|||||||
user=user,
|
user=user,
|
||||||
creation_date=datetime.fromtimestamp(json_corpus['creation_date']),
|
creation_date=datetime.fromtimestamp(json_corpus['creation_date']),
|
||||||
description=json_corpus['description'],
|
description=json_corpus['description'],
|
||||||
last_edited_date=datetime.fromtimestamp(json_corpus['last_edited_date']),
|
|
||||||
title=json_corpus['title']
|
title=json_corpus['title']
|
||||||
)
|
)
|
||||||
db.session.add(corpus)
|
db.session.add(corpus)
|
||||||
|
@ -48,16 +48,6 @@ def corpus(corpus_id):
|
|||||||
corpus = Corpus.query.get_or_404(corpus_id)
|
corpus = Corpus.query.get_or_404(corpus_id)
|
||||||
if not (corpus.user == current_user or current_user.is_administrator()):
|
if not (corpus.user == current_user or current_user.is_administrator()):
|
||||||
abort(403)
|
abort(403)
|
||||||
# cool = False
|
|
||||||
# if corpus.is_public:
|
|
||||||
# cool = True
|
|
||||||
# elif current_user.is_authenticated:
|
|
||||||
# if corpus.user == current_user or current_user.is_administrator:
|
|
||||||
# cool = True
|
|
||||||
# else:
|
|
||||||
# abort(403)
|
|
||||||
# else:
|
|
||||||
# return current_app.login_manager.unauthorized()
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'corpora/corpus.html.j2',
|
'corpora/corpus.html.j2',
|
||||||
corpus=corpus,
|
corpus=corpus,
|
||||||
@ -176,7 +166,10 @@ def corpus_file(corpus_id, corpus_file_id):
|
|||||||
abort(404)
|
abort(404)
|
||||||
if not (corpus_file.corpus.user == current_user or current_user.is_administrator()):
|
if not (corpus_file.corpus.user == current_user or current_user.is_administrator()):
|
||||||
abort(403)
|
abort(403)
|
||||||
form = EditCorpusFileForm(obj=corpus_file, prefix='edit-corpus-file-form')
|
form = EditCorpusFileForm(
|
||||||
|
data=corpus_file.to_json_serializeable(),
|
||||||
|
prefix='edit-corpus-file-form'
|
||||||
|
)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.populate_obj(corpus_file)
|
form.populate_obj(corpus_file)
|
||||||
if db.session.is_modified(corpus_file):
|
if db.session.is_modified(corpus_file):
|
||||||
|
@ -109,7 +109,7 @@ def _create_job_service(job):
|
|||||||
job.status = JobStatus.FAILED
|
job.status = JobStatus.FAILED
|
||||||
return
|
return
|
||||||
models_mount_source = model.path
|
models_mount_source = model.path
|
||||||
models_mount_target = f'/usr/local/share/tessdata/{model.filename}'
|
models_mount_target = f'/usr/local/share/tessdata/{model.id}.traineddata'
|
||||||
models_mount = f'{models_mount_source}:{models_mount_target}:ro'
|
models_mount = f'{models_mount_source}:{models_mount_target}:ro'
|
||||||
mounts.append(models_mount)
|
mounts.append(models_mount)
|
||||||
elif job.service == 'spacy-nlp-pipeline':
|
elif job.service == 'spacy-nlp-pipeline':
|
||||||
|
137
app/models.py
137
app/models.py
@ -74,17 +74,12 @@ class FileMixin:
|
|||||||
'''
|
'''
|
||||||
creation_date = db.Column(db.DateTime, default=datetime.utcnow)
|
creation_date = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
filename = db.Column(db.String(255))
|
filename = db.Column(db.String(255))
|
||||||
last_edited_date = db.Column(db.DateTime)
|
|
||||||
mimetype = db.Column(db.String(255))
|
mimetype = db.Column(db.String(255))
|
||||||
|
|
||||||
def file_mixin_to_json(self, backrefs=False, relationships=False):
|
def file_mixin_to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
return {
|
return {
|
||||||
'creation_date': f'{self.creation_date.isoformat()}Z',
|
'creation_date': f'{self.creation_date.isoformat()}Z',
|
||||||
'filename': self.filename,
|
'filename': self.filename,
|
||||||
'last_edited_date': (
|
|
||||||
None if self.last_edited_date is None
|
|
||||||
else f'{self.last_edited_date.isoformat()}Z'
|
|
||||||
),
|
|
||||||
'mimetype': self.mimetype
|
'mimetype': self.mimetype
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,19 +181,19 @@ class Role(HashidMixin, db.Model):
|
|||||||
def reset_permissions(self):
|
def reset_permissions(self):
|
||||||
self.permissions = 0
|
self.permissions = 0
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'default': self.default,
|
'default': self.default,
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'permissions': self.permissions
|
'permissions': self.permissions
|
||||||
}
|
}
|
||||||
if relationships:
|
if relationships:
|
||||||
_json['users'] = {
|
json_serializeable['users'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.users
|
for x in self.users
|
||||||
}
|
}
|
||||||
return _json
|
return json_serializeable
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def insert_defaults():
|
def insert_defaults():
|
||||||
@ -486,8 +481,8 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
return False
|
return False
|
||||||
return check_password_hash(self.password_hash, password)
|
return check_password_hash(self.password_hash, password)
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'confirmed': self.confirmed,
|
'confirmed': self.confirmed,
|
||||||
'email': self.email,
|
'email': self.email,
|
||||||
@ -497,31 +492,30 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
),
|
),
|
||||||
'member_since': f'{self.member_since.isoformat()}Z',
|
'member_since': f'{self.member_since.isoformat()}Z',
|
||||||
'username': self.username,
|
'username': self.username,
|
||||||
'settings': {
|
|
||||||
'job_status_mail_notification_level': \
|
'job_status_mail_notification_level': \
|
||||||
self.setting_job_status_mail_notification_level.name
|
self.setting_job_status_mail_notification_level.name
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['role'] = self.role.to_json(backrefs=True)
|
json_serializeable['role'] = \
|
||||||
|
self.role.to_json_serializeable(backrefs=True)
|
||||||
if relationships:
|
if relationships:
|
||||||
_json['corpora'] = {
|
json_serializeable['corpora'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.corpora
|
for x in self.corpora
|
||||||
}
|
}
|
||||||
_json['jobs'] = {
|
json_serializeable['jobs'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.jobs
|
for x in self.jobs
|
||||||
}
|
}
|
||||||
_json['tesseract_ocr_pipeline_models'] = {
|
json_serializeable['tesseract_ocr_pipeline_models'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.tesseract_ocr_pipeline_models
|
for x in self.tesseract_ocr_pipeline_models
|
||||||
}
|
}
|
||||||
_json['spacy_nlp_pipeline_models'] = {
|
json_serializeable['spacy_nlp_pipeline_models'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.spacy_nlp_pipeline_models
|
for x in self.spacy_nlp_pipeline_models
|
||||||
}
|
}
|
||||||
return _json
|
return json_serializeable
|
||||||
|
|
||||||
class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
||||||
__tablename__ = 'tesseract_ocr_pipeline_models'
|
__tablename__ = 'tesseract_ocr_pipeline_models'
|
||||||
@ -626,8 +620,8 @@ class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
current_app.logger.error(e)
|
current_app.logger.error(e)
|
||||||
db.session.delete(self)
|
db.session.delete(self)
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'compatible_service_versions': self.compatible_service_versions,
|
'compatible_service_versions': self.compatible_service_versions,
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
@ -638,11 +632,12 @@ class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
'shared': self.shared,
|
'shared': self.shared,
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
'version': self.version,
|
'version': self.version,
|
||||||
**self.file_mixin_to_json()
|
**self.file_mixin_to_json_serializeable()
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['user'] = self.user.to_json(backrefs=True)
|
json_serializeable['user'] = \
|
||||||
return _json
|
self.user.to_json_serializeable(backrefs=True)
|
||||||
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
||||||
@ -751,8 +746,8 @@ class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
current_app.logger.error(e)
|
current_app.logger.error(e)
|
||||||
db.session.delete(self)
|
db.session.delete(self)
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'compatible_service_versions': self.compatible_service_versions,
|
'compatible_service_versions': self.compatible_service_versions,
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
@ -764,11 +759,11 @@ class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
'shared': self.shared,
|
'shared': self.shared,
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
'version': self.version,
|
'version': self.version,
|
||||||
**self.file_mixin_to_json()
|
**self.file_mixin_to_json_serializeable()
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['user'] = self.user.to_json(backrefs=True)
|
json_serializeable['user'] = self.user.to_json_serializeable(backrefs=True)
|
||||||
return _json
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
class JobInput(FileMixin, HashidMixin, db.Model):
|
class JobInput(FileMixin, HashidMixin, db.Model):
|
||||||
@ -814,14 +809,15 @@ class JobInput(FileMixin, HashidMixin, db.Model):
|
|||||||
def user_id(self):
|
def user_id(self):
|
||||||
return self.job.user_id
|
return self.job.user_id
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
**self.file_mixin_to_json()
|
**self.file_mixin_to_json_serializeable()
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['job'] = self.job.to_json(backrefs=True)
|
json_serializeable['job'] = \
|
||||||
return _json
|
self.job.to_json_serializeable(backrefs=True)
|
||||||
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
class JobResult(FileMixin, HashidMixin, db.Model):
|
class JobResult(FileMixin, HashidMixin, db.Model):
|
||||||
@ -869,18 +865,19 @@ class JobResult(FileMixin, HashidMixin, db.Model):
|
|||||||
def user_id(self):
|
def user_id(self):
|
||||||
return self.job.user_id
|
return self.job.user_id
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
**self.file_mixin_to_json(
|
**self.file_mixin_to_json_serializeable(
|
||||||
backrefs=backrefs,
|
backrefs=backrefs,
|
||||||
relationships=relationships
|
relationships=relationships
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['job'] = self.job.to_json(backrefs=True)
|
json_serializeable['job'] = \
|
||||||
return _json
|
self.job.to_json_serializeable(backrefs=True)
|
||||||
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
class Job(HashidMixin, db.Model):
|
class Job(HashidMixin, db.Model):
|
||||||
@ -988,8 +985,8 @@ class Job(HashidMixin, db.Model):
|
|||||||
self.end_date = None
|
self.end_date = None
|
||||||
self.status = JobStatus.SUBMITTED
|
self.status = JobStatus.SUBMITTED
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'creation_date': f'{self.creation_date.isoformat()}Z',
|
'creation_date': f'{self.creation_date.isoformat()}Z',
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
@ -1005,17 +1002,18 @@ class Job(HashidMixin, db.Model):
|
|||||||
'url': self.url
|
'url': self.url
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['user'] = self.user.to_json(backrefs=True)
|
json_serializeable['user'] = \
|
||||||
|
self.user.to_json_serializeable(backrefs=True)
|
||||||
if relationships:
|
if relationships:
|
||||||
_json['inputs'] = {
|
json_serializeable['inputs'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.inputs
|
for x in self.inputs
|
||||||
}
|
}
|
||||||
_json['results'] = {
|
json_serializeable['results'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.results
|
for x in self.results
|
||||||
}
|
}
|
||||||
return _json
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
class CorpusFile(FileMixin, HashidMixin, db.Model):
|
class CorpusFile(FileMixin, HashidMixin, db.Model):
|
||||||
@ -1079,8 +1077,8 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
|
|||||||
db.session.delete(self)
|
db.session.delete(self)
|
||||||
self.corpus.status = CorpusStatus.UNPREPARED
|
self.corpus.status = CorpusStatus.UNPREPARED
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'url': self.url,
|
'url': self.url,
|
||||||
'address': self.address,
|
'address': self.address,
|
||||||
@ -1095,14 +1093,15 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
|
|||||||
'publishing_year': self.publishing_year,
|
'publishing_year': self.publishing_year,
|
||||||
'school': self.school,
|
'school': self.school,
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
**self.file_mixin_to_json(
|
**self.file_mixin_to_json_serializeable(
|
||||||
backrefs=backrefs,
|
backrefs=backrefs,
|
||||||
relationships=relationships
|
relationships=relationships
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['corpus'] = self.corpus.to_json(backrefs=True)
|
json_serializeable['corpus'] = \
|
||||||
return _json
|
self.corpus.to_json_serializeable(backrefs=True)
|
||||||
|
return json_serializeable
|
||||||
|
|
||||||
class Corpus(HashidMixin, db.Model):
|
class Corpus(HashidMixin, db.Model):
|
||||||
'''
|
'''
|
||||||
@ -1116,7 +1115,6 @@ class Corpus(HashidMixin, db.Model):
|
|||||||
# Fields
|
# Fields
|
||||||
creation_date = db.Column(db.DateTime(), default=datetime.utcnow)
|
creation_date = db.Column(db.DateTime(), default=datetime.utcnow)
|
||||||
description = db.Column(db.String(255))
|
description = db.Column(db.String(255))
|
||||||
last_edited_date = db.Column(db.DateTime())
|
|
||||||
status = db.Column(
|
status = db.Column(
|
||||||
IntEnumColumn(CorpusStatus),
|
IntEnumColumn(CorpusStatus),
|
||||||
default=CorpusStatus.UNPREPARED
|
default=CorpusStatus.UNPREPARED
|
||||||
@ -1210,15 +1208,14 @@ class Corpus(HashidMixin, db.Model):
|
|||||||
os.path.join(self.path, 'cwb', 'corpus.vrt'),
|
os.path.join(self.path, 'cwb', 'corpus.vrt'),
|
||||||
encoding='utf-8'
|
encoding='utf-8'
|
||||||
)
|
)
|
||||||
self.last_edited_date = datetime.utcnow()
|
|
||||||
self.status = CorpusStatus.SUBMITTED
|
self.status = CorpusStatus.SUBMITTED
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
shutil.rmtree(self.path, ignore_errors=True)
|
shutil.rmtree(self.path, ignore_errors=True)
|
||||||
db.session.delete(self)
|
db.session.delete(self)
|
||||||
|
|
||||||
def to_json(self, backrefs=False, relationships=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False):
|
||||||
_json = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
'creation_date': f'{self.creation_date.isoformat()}Z',
|
'creation_date': f'{self.creation_date.isoformat()}Z',
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
@ -1226,21 +1223,17 @@ class Corpus(HashidMixin, db.Model):
|
|||||||
'num_analysis_sessions': self.num_analysis_sessions,
|
'num_analysis_sessions': self.num_analysis_sessions,
|
||||||
'num_tokens': self.num_tokens,
|
'num_tokens': self.num_tokens,
|
||||||
'status': self.status.name,
|
'status': self.status.name,
|
||||||
'last_edited_date': (
|
|
||||||
None if self.last_edited_date is None
|
|
||||||
else f'{self.last_edited_date.isoformat()}Z'
|
|
||||||
),
|
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
'is_public': self.is_public
|
'is_public': self.is_public
|
||||||
}
|
}
|
||||||
if backrefs:
|
if backrefs:
|
||||||
_json['user'] = self.user.to_json(backrefs=True)
|
json_serializeable['user'] = self.user.to_json_serializeable(backrefs=True)
|
||||||
if relationships:
|
if relationships:
|
||||||
_json['files'] = {
|
json_serializeable['files'] = {
|
||||||
x.hashid: x.to_json(relationships=True)
|
x.hashid: x.to_json_serializeable(relationships=True)
|
||||||
for x in self.files
|
for x in self.files
|
||||||
}
|
}
|
||||||
return _json
|
return json_serializeable
|
||||||
# endregion models
|
# endregion models
|
||||||
|
|
||||||
|
|
||||||
@ -1248,8 +1241,6 @@ class Corpus(HashidMixin, db.Model):
|
|||||||
# event_handlers #
|
# event_handlers #
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# region event_handlers
|
# region event_handlers
|
||||||
|
|
||||||
|
|
||||||
@db.event.listens_for(Corpus, 'after_delete')
|
@db.event.listens_for(Corpus, 'after_delete')
|
||||||
@db.event.listens_for(CorpusFile, 'after_delete')
|
@db.event.listens_for(CorpusFile, 'after_delete')
|
||||||
@db.event.listens_for(Job, 'after_delete')
|
@db.event.listens_for(Job, 'after_delete')
|
||||||
@ -1269,7 +1260,7 @@ def ressource_after_delete(mapper, connection, ressource):
|
|||||||
@db.event.listens_for(JobInput, 'after_insert')
|
@db.event.listens_for(JobInput, 'after_insert')
|
||||||
@db.event.listens_for(JobResult, 'after_insert')
|
@db.event.listens_for(JobResult, 'after_insert')
|
||||||
def ressource_after_insert_handler(mapper, connection, ressource):
|
def ressource_after_insert_handler(mapper, connection, ressource):
|
||||||
value = ressource.to_json()
|
value = ressource.to_json_serializeable()
|
||||||
for attr in mapper.relationships:
|
for attr in mapper.relationships:
|
||||||
value[attr.key] = {}
|
value[attr.key] = {}
|
||||||
jsonpatch = [
|
jsonpatch = [
|
||||||
|
@ -96,7 +96,3 @@ class EditNotificationSettingsForm(FlaskForm):
|
|||||||
(x.name, x.name.capitalize())
|
(x.name, x.name.capitalize())
|
||||||
for x in UserSettingJobStatusMailNotificationLevel
|
for x in UserSettingJobStatusMailNotificationLevel
|
||||||
]
|
]
|
||||||
|
|
||||||
def prefill(self, user):
|
|
||||||
self.job_status_mail_notification_level.data = \
|
|
||||||
user.setting_job_status_mail_notification_level.name
|
|
||||||
|
@ -19,10 +19,11 @@ def settings():
|
|||||||
)
|
)
|
||||||
edit_general_settings_form = EditGeneralSettingsForm(
|
edit_general_settings_form = EditGeneralSettingsForm(
|
||||||
current_user,
|
current_user,
|
||||||
obj=current_user,
|
data=current_user.to_json_serializeable(),
|
||||||
prefix='edit-general-settings-form'
|
prefix='edit-general-settings-form'
|
||||||
)
|
)
|
||||||
edit_notification_settings_form = EditNotificationSettingsForm(
|
edit_notification_settings_form = EditNotificationSettingsForm(
|
||||||
|
data=current_user.to_json_serializeable(),
|
||||||
prefix='edit-notification-settings-form'
|
prefix='edit-notification-settings-form'
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,7 +49,6 @@ def settings():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('Your changes have been saved')
|
flash('Your changes have been saved')
|
||||||
return redirect(url_for('.settings'))
|
return redirect(url_for('.settings'))
|
||||||
edit_notification_settings_form.prefill(current_user)
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'settings/settings.html.j2',
|
'settings/settings.html.j2',
|
||||||
change_password_form=change_password_form,
|
change_password_form=change_password_form,
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 22 KiB |
@ -16,10 +16,12 @@ class App {
|
|||||||
this.data.promises.getUser[userId] = new Promise((resolve, reject) => {
|
this.data.promises.getUser[userId] = new Promise((resolve, reject) => {
|
||||||
fetch(`/users/${userId}?backrefs=true&relationships=true`, {headers: {Accept: 'application/json'}})
|
fetch(`/users/${userId}?backrefs=true&relationships=true`, {headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {return response.json();},
|
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {this.flash('Forbidden', 'error');}
|
if (response.status === 403) {this.flash('Forbidden', 'error'); reject(response);}
|
||||||
if (response.status === 404) {this.flash('Not Found', 'error');}
|
return response.json();
|
||||||
|
},
|
||||||
|
(response) => {
|
||||||
|
this.flash('Something went wrong', 'error');
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,6 @@ class CorpusDisplay extends RessourceDisplay {
|
|||||||
let corpus = user.corpora[this.corpusId];
|
let corpus = user.corpora[this.corpusId];
|
||||||
this.setCreationDate(corpus.creation_date);
|
this.setCreationDate(corpus.creation_date);
|
||||||
this.setDescription(corpus.description);
|
this.setDescription(corpus.description);
|
||||||
this.setLastEditedDate(corpus.last_edited_date);
|
|
||||||
this.setStatus(corpus.status);
|
this.setStatus(corpus.status);
|
||||||
this.setTitle(corpus.title);
|
this.setTitle(corpus.title);
|
||||||
this.setNumTokens(corpus.num_tokens);
|
this.setNumTokens(corpus.num_tokens);
|
||||||
@ -37,11 +36,6 @@ class CorpusDisplay extends RessourceDisplay {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'replace': {
|
case 'replace': {
|
||||||
let re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/last_edited_date$`);
|
|
||||||
if (re.test(operation.path)) {
|
|
||||||
this.setLastEditedDate(operation.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/num_tokens`);
|
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/num_tokens`);
|
||||||
if (re.test(operation.path)) {
|
if (re.test(operation.path)) {
|
||||||
this.setNumTokens(operation.value);
|
this.setNumTokens(operation.value);
|
||||||
@ -113,11 +107,4 @@ class CorpusDisplay extends RessourceDisplay {
|
|||||||
new Date(creationDate).toLocaleString("en-US")
|
new Date(creationDate).toLocaleString("en-US")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastEditedDate(lastEditedDate) {
|
|
||||||
this.setElements(
|
|
||||||
this.displayElement.querySelectorAll('.corpus-end-date'),
|
|
||||||
new Date(lastEditedDate).toLocaleString("en-US")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,13 @@ class SpaCyNLPPipelineModelList extends RessourceList {
|
|||||||
this.listjs.list.addEventListener('change', (event) => {this.onChange(event)});
|
this.listjs.list.addEventListener('change', (event) => {this.onChange(event)});
|
||||||
}
|
}
|
||||||
|
|
||||||
init (user) {
|
init(user) {
|
||||||
this._init(user.spacy_nlp_pipeline_models);
|
this._init(user.spacy_nlp_pipeline_models);
|
||||||
|
if (user.role.name !== ('Administrator' || 'Contributor')) {
|
||||||
|
for (let switchElement of this.listjs.list.querySelectorAll('.shared')) {
|
||||||
|
switchElement.setAttribute('disabled', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_init(ressources) {
|
_init(ressources) {
|
||||||
@ -96,7 +101,13 @@ class SpaCyNLPPipelineModelList extends RessourceList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (event.target.closest('.action-switch')) {return;}
|
if (event.target.closest('.action-switch')) {
|
||||||
|
let userRole = app.data.users[this.userId].role.name;
|
||||||
|
if (userRole !== ('Administrator' || 'Contributor')) {
|
||||||
|
app.flash('You need the "Contributor" or "Administrator" role to perform this action.', 'error');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
let actionButtonElement = event.target.closest('.action-button');
|
let actionButtonElement = event.target.closest('.action-button');
|
||||||
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
|
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
|
||||||
let spaCyNLPPipelineModelElement = event.target.closest('tr');
|
let spaCyNLPPipelineModelElement = event.target.closest('tr');
|
||||||
|
@ -86,6 +86,11 @@ class TesseractOCRPipelineModelList extends RessourceList {
|
|||||||
|
|
||||||
init (user) {
|
init (user) {
|
||||||
this._init(user.tesseract_ocr_pipeline_models);
|
this._init(user.tesseract_ocr_pipeline_models);
|
||||||
|
if (user.role.name !== ('Administrator' || 'Contributor')) {
|
||||||
|
for (let switchElement of this.listjs.list.querySelectorAll('.shared')) {
|
||||||
|
switchElement.setAttribute('disabled', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_init(ressources) {
|
_init(ressources) {
|
||||||
@ -96,7 +101,13 @@ class TesseractOCRPipelineModelList extends RessourceList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (event.target.closest('.action-switch')) {return;}
|
if (event.target.closest('.action-switch')) {
|
||||||
|
let userRole = app.data.users[this.userId].role.name;
|
||||||
|
if (userRole !== ('Administrator' || 'Contributor')) {
|
||||||
|
app.flash('You need the "Contributor" or "Administrator" role to perform this action.', 'error');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
let actionButtonElement = event.target.closest('.action-button');
|
let actionButtonElement = event.target.closest('.action-button');
|
||||||
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
|
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
|
||||||
let tesseractOCRPipelineModelElement = event.target.closest('tr');
|
let tesseractOCRPipelineModelElement = event.target.closest('tr');
|
||||||
|
@ -12,13 +12,14 @@ class Utils {
|
|||||||
fetch(`/corpora/${corpus.id}/build`, {method: 'POST', headers: {Accept: 'application/json'}})
|
fetch(`/corpora/${corpus.id}/build`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
|
if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);}
|
||||||
app.flash(`Corpus "${corpus.title}" marked for building`, 'corpus');
|
app.flash(`Corpus "${corpus.title}" marked for building`, 'corpus');
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
if (response.status === 409) {app.flash('Conflict', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -61,12 +62,13 @@ class Utils {
|
|||||||
fetch(`/corpora/${corpus.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
fetch(`/corpora/${corpus.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
app.flash(`Corpus "${corpusTitle}" marked for deletion`, 'corpus');
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
|
app.flash(`Corpus "${corpus.title}" marked for deletion`, 'corpus');
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -112,12 +114,13 @@ class Utils {
|
|||||||
fetch(`/corpora/${corpusId}/files/${corpusFileId}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
fetch(`/corpora/${corpusId}/files/${corpusFileId}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
app.flash(`Corpus file "${corpusFileTitle}" marked for deletion`, 'corpus');
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
|
app.flash(`Corpus File "${corpusFileTitle}" deleted`, 'corpus');
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -160,12 +163,13 @@ class Utils {
|
|||||||
fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'})
|
fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
app.flash(`SpaCy NLP Pipeline Model "${spaCyNLPPipelineModelTitle}" marked for deletion`);
|
app.flash(`SpaCy NLP Pipeline Model "${spaCyNLPPipelineModelTitle}" marked for deletion`);
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -208,12 +212,13 @@ class Utils {
|
|||||||
fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'})
|
fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
app.flash(`Tesseract OCR Pipeline Model "${tesseractOCRPipelineModelTitle}" marked for deletion`);
|
app.flash(`Tesseract OCR Pipeline Model "${tesseractOCRPipelineModelTitle}" marked for deletion`);
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -258,12 +263,13 @@ class Utils {
|
|||||||
fetch(`/jobs/${job.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
fetch(`/jobs/${job.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
app.flash(`Job "${jobTitle}" marked for deletion`, 'job');
|
app.flash(`Job "${jobTitle}" marked for deletion`, 'job');
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -279,12 +285,12 @@ class Utils {
|
|||||||
fetch(`/jobs/${job.id}/log`, {method: 'GET', headers: {Accept: 'application/json, text/plain'}})
|
fetch(`/jobs/${job.id}/log`, {method: 'GET', headers: {Accept: 'application/json, text/plain'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
resolve(response);
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
return response.text();
|
return response.text();
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -314,6 +320,7 @@ class Utils {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
modal.open();
|
modal.open();
|
||||||
|
resolve(text);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -355,13 +362,14 @@ class Utils {
|
|||||||
fetch(`/jobs/${job.id}/restart`, {method: 'POST', headers: {Accept: 'application/json'}})
|
fetch(`/jobs/${job.id}/restart`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
|
if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);}
|
||||||
app.flash(`Job "${jobTitle}" restarted.`, 'job');
|
app.flash(`Job "${jobTitle}" restarted.`, 'job');
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
if (response.status === 409) {app.flash('Conflict', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -406,12 +414,13 @@ class Utils {
|
|||||||
fetch(`/users/${user.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
fetch(`/users/${user.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
|
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||||
app.flash(`User "${userName}" marked for deletion`);
|
app.flash(`User "${userName}" marked for deletion`);
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
if (response.status === 404) {app.flash('Not Found', 'error');}
|
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -432,11 +441,12 @@ class Utils {
|
|||||||
fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
|
fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
app.flash(msg);
|
app.flash(msg);
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -455,11 +465,12 @@ class Utils {
|
|||||||
fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
|
fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||||
app.flash(msg);
|
app.flash(msg);
|
||||||
resolve(response);
|
resolve(response);
|
||||||
},
|
},
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 403) {app.flash('Forbidden', 'error');}
|
app.flash('Something went wrong', 'error');
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -48,13 +48,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="input-field">
|
|
||||||
<input class="corpus-last-edited-date validate" disabled id="corpus-last-edited-date" type="text">
|
|
||||||
<label for="corpus-last-edited-date">Last edited</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s12 m6">
|
<div class="col s12 m6">
|
||||||
<div class="input-field">
|
<div class="input-field">
|
||||||
<input class="corpus-token-ratio validate" disabled id="corpus-token-ratio" type="text">
|
<input class="corpus-token-ratio validate" disabled id="corpus-token-ratio" type="text">
|
||||||
|
@ -15,7 +15,7 @@ def user(user_id):
|
|||||||
backrefs = request.args.get('backrefs', 'false').lower() == 'true'
|
backrefs = request.args.get('backrefs', 'false').lower() == 'true'
|
||||||
relationships = (
|
relationships = (
|
||||||
request.args.get('relationships', 'false').lower() == 'true')
|
request.args.get('relationships', 'false').lower() == 'true')
|
||||||
return user.to_json(backrefs=backrefs, relationships=relationships), 200
|
return user.to_json_serializeable(backrefs=backrefs, relationships=relationships), 200
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/<hashid:user_id>', methods=['DELETE'])
|
@bp.route('/<hashid:user_id>', methods=['DELETE'])
|
||||||
|
@ -21,6 +21,7 @@ def upgrade():
|
|||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
op.add_column('transkribus_htr_models',
|
op.add_column(
|
||||||
|
'transkribus_htr_models',
|
||||||
sa.Column('transkribus_name', sa.String(length=64), autoincrement=False, nullable=True)
|
sa.Column('transkribus_name', sa.String(length=64), autoincrement=False, nullable=True)
|
||||||
)
|
)
|
||||||
|
51
migrations/versions/31b9c0259e6b_.py
Normal file
51
migrations/versions/31b9c0259e6b_.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
"""Remove last_edited_date column from all tables
|
||||||
|
|
||||||
|
Revision ID: 31b9c0259e6b
|
||||||
|
Revises: 89e9526089bf
|
||||||
|
Create Date: 2022-11-24 09:53:21.025531
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '31b9c0259e6b'
|
||||||
|
down_revision = '89e9526089bf'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.drop_column('corpora', 'last_edited_date')
|
||||||
|
op.drop_column('corpus_files', 'last_edited_date')
|
||||||
|
op.drop_column('job_inputs', 'last_edited_date')
|
||||||
|
op.drop_column('job_results', 'last_edited_date')
|
||||||
|
op.drop_column('spacy_nlp_pipeline_models', 'last_edited_date')
|
||||||
|
op.drop_column('tesseract_ocr_pipeline_models', 'last_edited_date')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.add_column(
|
||||||
|
'tesseract_ocr_pipeline_models',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
'spacy_nlp_pipeline_models',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
'job_results',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
'job_inputs',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
'corpus_files',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
'corpora',
|
||||||
|
sa.Column('last_edited_date', sa.DateTime(), nullable=True)
|
||||||
|
)
|
@ -5,7 +5,6 @@ Revises: 260b57d5f4e7
|
|||||||
Create Date: 2022-10-11 14:32:13.227364
|
Create Date: 2022-10-11 14:32:13.227364
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from genericpath import isdir
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import os
|
import os
|
||||||
from app.models import User
|
from app.models import User
|
||||||
|
@ -21,6 +21,7 @@ def upgrade():
|
|||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
op.add_column('users',
|
op.add_column(
|
||||||
|
'users',
|
||||||
sa.Column('setting_dark_mode', sa.Boolean(), nullable=True)
|
sa.Column('setting_dark_mode', sa.Boolean(), nullable=True)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user