mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-26 03:14:19 +00:00
Compare commits
3 Commits
82d6f6003f
...
cdf6f9fcfd
Author | SHA1 | Date | |
---|---|---|---|
|
cdf6f9fcfd | ||
|
268da220d2 | ||
|
84e1755a57 |
@ -5,9 +5,8 @@
|
||||
!app
|
||||
!migrations
|
||||
!tests
|
||||
!.flaskenv
|
||||
!boot.sh
|
||||
!config.py
|
||||
!docker-nopaque-entrypoint.sh
|
||||
!nopaque.py
|
||||
!requirements.txt
|
||||
!wsgi.py
|
||||
|
@ -46,7 +46,7 @@ COPY docker-nopaque-entrypoint.sh /usr/local/bin/
|
||||
COPY --chown=nopaque:nopaque app app
|
||||
COPY --chown=nopaque:nopaque migrations migrations
|
||||
COPY --chown=nopaque:nopaque tests tests
|
||||
COPY --chown=nopaque:nopaque .flaskenv boot.sh config.py nopaque.py requirements.txt ./
|
||||
COPY --chown=nopaque:nopaque boot.sh config.py wsgi.py requirements.txt ./
|
||||
|
||||
RUN mkdir logs
|
||||
|
||||
|
@ -33,6 +33,9 @@ scheduler = APScheduler()
|
||||
socketio = SocketIO()
|
||||
|
||||
|
||||
# TODO: Create export for lemmatized corpora
|
||||
|
||||
|
||||
def create_app(config: Config = Config) -> Flask:
|
||||
''' Creates an initialized Flask (WSGI Application) object. '''
|
||||
app = Flask(__name__)
|
||||
|
@ -1,6 +1,6 @@
|
||||
from flask import abort, request
|
||||
from app import db
|
||||
from app.decorators import content_negotiation
|
||||
from app import db
|
||||
from app.models import User
|
||||
from . import bp
|
||||
|
||||
|
@ -9,12 +9,12 @@ from app.users.settings.forms import (
|
||||
UpdateAccountInformationForm,
|
||||
UpdateProfileInformationForm
|
||||
)
|
||||
from . import bp
|
||||
from .forms import UpdateUserForm
|
||||
from app.users.utils import (
|
||||
user_endpoint_arguments_constructor as user_eac,
|
||||
user_dynamic_list_constructor as user_dlc
|
||||
)
|
||||
from . import bp
|
||||
from .forms import UpdateUserForm
|
||||
|
||||
|
||||
@bp.route('')
|
||||
|
@ -5,8 +5,8 @@ from flask import abort, Blueprint
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
from app import db, hashids
|
||||
from app.models import Job, JobInput, JobStatus, TesseractOCRPipelineModel
|
||||
from .schemas import EmptySchema, JobSchema, SpaCyNLPPipelineJobSchema, TesseractOCRPipelineJobSchema, TesseractOCRPipelineModelSchema
|
||||
from .auth import auth_error_responses, token_auth
|
||||
from .schemas import EmptySchema, JobSchema, SpaCyNLPPipelineJobSchema, TesseractOCRPipelineJobSchema, TesseractOCRPipelineModelSchema
|
||||
|
||||
|
||||
bp = Blueprint('jobs', __name__)
|
||||
|
@ -3,11 +3,11 @@ from apifairy import authenticate, body, response
|
||||
from apifairy.decorators import other_responses
|
||||
from flask import abort, Blueprint
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
from app import db
|
||||
from app.email import create_message, send
|
||||
from app import db
|
||||
from app.models import User
|
||||
from .schemas import EmptySchema, UserSchema
|
||||
from .auth import auth_error_responses, token_auth
|
||||
from .schemas import EmptySchema, UserSchema
|
||||
|
||||
|
||||
bp = Blueprint('users', __name__)
|
||||
|
@ -4,7 +4,7 @@ from threading import Thread
|
||||
from app import db
|
||||
from app.decorators import content_negotiation, permission_required
|
||||
from app.models import SpaCyNLPPipelineModel
|
||||
from .. import bp
|
||||
from . import bp
|
||||
|
||||
|
||||
@bp.route('/spacy-nlp-pipeline-models/<hashid:spacy_nlp_pipeline_model_id>', methods=['DELETE'])
|
||||
|
@ -8,9 +8,7 @@ from .forms import (
|
||||
CreateSpaCyNLPPipelineModelForm,
|
||||
UpdateSpaCyNLPPipelineModelForm
|
||||
)
|
||||
from .utils import (
|
||||
spacy_nlp_pipeline_model_dlc as spacy_nlp_pipeline_model_dlc
|
||||
)
|
||||
from .utils import spacy_nlp_pipeline_model_dlc
|
||||
|
||||
|
||||
@bp.route('/spacy-nlp-pipeline-models')
|
||||
|
@ -8,9 +8,7 @@ from .forms import (
|
||||
CreateTesseractOCRPipelineModelForm,
|
||||
UpdateTesseractOCRPipelineModelForm
|
||||
)
|
||||
from .utils import (
|
||||
tesseract_ocr_pipeline_model_dlc as tesseract_ocr_pipeline_model_dlc
|
||||
)
|
||||
from .utils import tesseract_ocr_pipeline_model_dlc
|
||||
|
||||
|
||||
@bp.route('/tesseract-ocr-pipeline-models')
|
||||
|
@ -1,11 +1,11 @@
|
||||
from flask import current_app
|
||||
from app import db
|
||||
from app.models import User, Corpus, CorpusFile
|
||||
from datetime import datetime
|
||||
from flask import current_app
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
import json
|
||||
import shutil
|
||||
from app import db
|
||||
from app.models import User, Corpus, CorpusFile
|
||||
|
||||
|
||||
class SandpaperConverter:
|
||||
|
@ -1,7 +1,7 @@
|
||||
from flask import abort, current_app
|
||||
from flask import current_app
|
||||
from threading import Thread
|
||||
from app import db
|
||||
from app.decorators import content_negotiation
|
||||
from app import db
|
||||
from app.models import CorpusFile
|
||||
from ..decorators import corpus_follower_permission_required
|
||||
from . import bp
|
||||
|
@ -1,6 +1,5 @@
|
||||
from flask import request, url_for
|
||||
from app.models import CorpusFile
|
||||
from ..utils import corpus_endpoint_arguments_constructor as corpus_eac
|
||||
|
||||
|
||||
def corpus_file_dynamic_list_constructor():
|
||||
|
@ -1,2 +0,0 @@
|
||||
from .container_column import ContainerColumn
|
||||
from .int_enum_column import IntEnumColumn
|
@ -1,21 +0,0 @@
|
||||
import json
|
||||
from app import db
|
||||
|
||||
|
||||
class ContainerColumn(db.TypeDecorator):
|
||||
impl = db.String
|
||||
|
||||
def __init__(self, container_type, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.container_type = container_type
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if isinstance(value, self.container_type):
|
||||
return json.dumps(value)
|
||||
elif isinstance(value, str) and isinstance(json.loads(value), self.container_type):
|
||||
return value
|
||||
else:
|
||||
return TypeError()
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return json.loads(value)
|
1
app/extensions/__init__.py
Normal file
1
app/extensions/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
|
2
app/extensions/sqlalchemy/__init__.py
Normal file
2
app/extensions/sqlalchemy/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .types import ContainerColumn
|
||||
from .types import IntEnumColumn
|
@ -1,6 +1,26 @@
|
||||
import json
|
||||
from app import db
|
||||
|
||||
|
||||
class ContainerColumn(db.TypeDecorator):
|
||||
impl = db.String
|
||||
|
||||
def __init__(self, container_type, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.container_type = container_type
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if isinstance(value, self.container_type):
|
||||
return json.dumps(value)
|
||||
elif isinstance(value, str) and isinstance(json.loads(value), self.container_type):
|
||||
return value
|
||||
else:
|
||||
return TypeError()
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return json.loads(value)
|
||||
|
||||
|
||||
class IntEnumColumn(db.TypeDecorator):
|
||||
impl = db.Integer
|
||||
|
@ -9,7 +9,7 @@ import shutil
|
||||
import xml.etree.ElementTree as ET
|
||||
from app import db
|
||||
from app.converters.vrt import normalize_vrt_file
|
||||
from app.ext.flask_sqlalchemy import IntEnumColumn
|
||||
from app.extensions.sqlalchemy import IntEnumColumn
|
||||
from .corpus_follower_association import CorpusFollowerAssociation
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ from typing import Union
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from app import db
|
||||
from app.ext.flask_sqlalchemy import ContainerColumn, IntEnumColumn
|
||||
from app.extensions.sqlalchemy import ContainerColumn, IntEnumColumn
|
||||
|
||||
|
||||
class JobStatus(IntEnum):
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
import requests
|
||||
import yaml
|
||||
from app import db
|
||||
from app.ext.flask_sqlalchemy import ContainerColumn
|
||||
from app.extensions.sqlalchemy import ContainerColumn
|
||||
from .file_mixin import FileMixin
|
||||
from .user import User
|
||||
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
import requests
|
||||
import yaml
|
||||
from app import db
|
||||
from app.ext.flask_sqlalchemy import ContainerColumn
|
||||
from app.extensions.sqlalchemy import ContainerColumn
|
||||
from .file_mixin import FileMixin
|
||||
from .user import User
|
||||
|
||||
|
@ -12,7 +12,7 @@ import re
|
||||
import secrets
|
||||
import shutil
|
||||
from app import db, hashids
|
||||
from app.ext.flask_sqlalchemy import IntEnumColumn
|
||||
from app.extensions.sqlalchemy import IntEnumColumn
|
||||
from .corpus import Corpus
|
||||
from .corpus_follower_association import CorpusFollowerAssociation
|
||||
from .corpus_follower_role import CorpusFollowerRole
|
||||
|
57
app/static/js/forms/base-form-new.js
Normal file
57
app/static/js/forms/base-form-new.js
Normal file
@ -0,0 +1,57 @@
|
||||
export class BaseForm {
|
||||
constructor(formElement) {
|
||||
this.element = formElement;
|
||||
|
||||
this.element.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
this.submit();
|
||||
});
|
||||
console.log("UsernamePostFormInitialized");
|
||||
}
|
||||
|
||||
submit() {
|
||||
let errorTextElements = this.element
|
||||
.querySelectorAll('.supporting-text[data-supporting-text-type="error"]');
|
||||
for (let errorTextElement of errorTextElements) {errorTextElement.remove();}
|
||||
|
||||
const body = new FormData(this.element);
|
||||
const headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
const method = this.element.method;
|
||||
|
||||
const fetchPromise = new Promise((resolve, reject) => {
|
||||
fetch(this.element.action, {body: body, headers: headers, method: method})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
console.log("reject", response);
|
||||
reject(response);
|
||||
return;
|
||||
}
|
||||
console.log("resolve", response);
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
|
||||
fetchPromise
|
||||
.then(
|
||||
(response) => {console.log("Hello from resolve handler");return response.json();},
|
||||
(response) => {
|
||||
console.log("Hello from reject handler 1/2");
|
||||
response.json()
|
||||
.then((errors) => {
|
||||
console.log("Hello from reject handler 2/2");
|
||||
for (let [name, messages] of Object.entries(errors)) {
|
||||
console.log(name, messages);
|
||||
const inputFieldElement = this.element[name].closest('.input-field');
|
||||
for (let message of messages) {
|
||||
const messageHTML = `<span class="supporting-text" data-supporting-text-type="error">${message}</span>`;
|
||||
inputFieldElement.insertAdjacentHTML('beforeend', messageHTML);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
@ -1,4 +1,3 @@
|
||||
from flask_login import current_user
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf.file import FileField, FileRequired
|
||||
from wtforms import (
|
||||
@ -17,7 +16,7 @@ from wtforms.validators import (
|
||||
Regexp
|
||||
)
|
||||
from app.models import User, UserSettingJobStatusMailNotificationLevel
|
||||
from app.wtforms.validators import FileSize
|
||||
from app.extensions.wtforms.validators import FileSize
|
||||
|
||||
|
||||
class UpdateAccountInformationForm(FlaskForm):
|
||||
|
2
boot.sh
2
boot.sh
@ -24,7 +24,7 @@ if [[ "${#}" == "0" ]]; then
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
python3 nopaque.py
|
||||
python3 wsgi.py
|
||||
elif [[ "${1}" == "flask" ]]; then
|
||||
flask ${@:2}
|
||||
elif [[ "${1}" == "--help" || "${1}" == "-h" ]]; then
|
||||
|
@ -1,5 +1,3 @@
|
||||
version: "3.5"
|
||||
|
||||
# The docker-compose.yml file is not meant to be modified itself.
|
||||
# Instead use the following files for configurations:
|
||||
# - .env: Environment variables for the docker-compose.yml file.
|
||||
|
@ -1,5 +1,3 @@
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
nopaque:
|
||||
environment:
|
||||
@ -13,6 +11,6 @@ services:
|
||||
- "./config.py:/home/nopaque/config.py"
|
||||
- "./docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh"
|
||||
- "./migrations:/home/nopaque/migrations"
|
||||
- "./nopaque.py:/home/nopaque/nopaque.py"
|
||||
- "./requirements.txt:/home/nopaque/requirements.txt"
|
||||
- "./tests:/home/nopaque/tests"
|
||||
- "./wsgi.py:/home/nopaque/wsgi.py"
|
||||
|
@ -1,5 +1,3 @@
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
nopaque:
|
||||
environment:
|
||||
|
@ -1,5 +1,3 @@
|
||||
version: "3.5"
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
||||
|
@ -15,7 +15,7 @@ Flask-Marshmallow==0.14.0
|
||||
Flask-Menu==0.7.2
|
||||
Flask-Migrate
|
||||
Flask-Paranoid
|
||||
Flask-SocketIO
|
||||
Flask-SocketIO==5.3.6
|
||||
Flask-SQLAlchemy==2.5.1
|
||||
Flask-WTF
|
||||
hiredis
|
||||
|
Loading…
Reference in New Issue
Block a user