diff --git a/backend/routes/data.py b/backend/routes/data.py index ba0c5ec..aaf88d0 100644 --- a/backend/routes/data.py +++ b/backend/routes/data.py @@ -68,10 +68,12 @@ def generate_segmentation( values = [] for label_name, val in annotations.items(): - label = Label.query.filter_by(name=label_name, project_id=project_id).first() + label = Label.query.filter_by( + name=label_name, project_id=project_id).first() if label is None: - raise NotFound(description=f"Label not found with name: `{label_name}`") + raise NotFound( + description=f"Label not found with name: `{label_name}`") if "values" not in val: raise BadRequest( @@ -116,7 +118,8 @@ def add_data(): api_key = request.headers.get("Authorization", None) if not api_key: - raise BadRequest(description="API Key missing from `Authorization` Header") + raise BadRequest( + description="API Key missing from `Authorization` Header") project = Project.query.filter_by(api_key=api_key).first() @@ -131,7 +134,8 @@ def add_data(): segmentations = request.form.get("segmentations", "[]") reference_transcription = request.form.get("reference_transcription", None) - is_marked_for_review = bool(request.form.get("is_marked_for_review", False)) + is_marked_for_review = bool( + request.form.get("is_marked_for_review", False)) audio_file = request.files["audio_file"] original_filename = secure_filename(audio_file.filename) diff --git a/backend/routes/projects.py b/backend/routes/projects.py index f89332a..18d59c3 100644 --- a/backend/routes/projects.py +++ b/backend/routes/projects.py @@ -515,6 +515,92 @@ def update_data(project_id, data_id): ) +@api.route("/projects//neighbours/", methods=["GET"]) +@jwt_required +def neighbours_data(project_id, data_id): + """ + Returns dataId s for the next and previous data + """ + identity = get_jwt_identity() + + try: + request_user = User.query.filter_by( + username=identity["username"]).first() + project = Project.query.get(project_id) + + if request_user not in project.users: + return jsonify(message="Unauthorized access!"), 401 + + currdata = Data.query.filter_by( + id=data_id, project_id=project_id).first() + + if currdata.segmentations: + pagetype = "Annotated" + else: + pagetype = "Yet To annotate" + + # if currdata.is_marked_for_review: + # pagetype = "Review" + + + if pagetype == "Review": + data = ( + db.session.query(Data) + .filter(Data.project_id == project_id) + .filter(Data.is_marked_for_review) + .distinct() + .order_by(Data.created_at.desc())) + + elif pagetype == "Annotated": + segmentations = db.session.query( + Segmentation.data_id).distinct().subquery() + data = ( + db.session.query(Data) + .filter(Data.project_id == project_id) + .filter(Data.id.in_(segmentations)) + .distinct() + .order_by(Data.created_at.desc())) + + elif pagetype == "Yet To annotate": + data = ( + db.session.query(Data) + .filter(Data.project_id == project_id) + .distinct() + ) + + else: + raise Exception("This is not the right way of using this API") + + if currdata.id == data[-1].id: + # if currdata.id == data[0].id or currdata.id == data[-1].id: + index = list(data).index(currdata) + before, after = data[index-1], data[0] + else: + index = list(data).index(currdata) + before, after = data[index-1], data[index+1] + + app.logger.info(f"The nieghbours are: {before, after}") + + except Exception as e: + app.logger.error(f"Error searching data") + app.logger.error(e) + return ( + jsonify(message=f"Error searching data", + type="DATA_SEARCHED_FAILED"), + 500, + ) + + return ( + jsonify( + after_id=after.id, + before_id=before.id, + message=f"Data Searched", + type="DATA_SEARCHED", + ), + 200, + ) + + @api.route( "/projects//data//segmentations", methods=["POST"] ) diff --git a/frontend/src/pages/annotate.js b/frontend/src/pages/annotate.js index b887110..8a7afb8 100644 --- a/frontend/src/pages/annotate.js +++ b/frontend/src/pages/annotate.js @@ -13,6 +13,8 @@ import { faBackward, faForward, faPlayCircle, + faArrowRight, + faArrowLeft, faPauseCircle, } from "@fortawesome/free-solid-svg-icons"; import Alert from "../components/alert"; @@ -30,9 +32,13 @@ class Annotate extends React.Component { isPlaying: false, projectId, dataId, + afterId: -1, + beforeId: -1, labels: {}, labelsUrl: `/api/projects/${projectId}/labels`, + neighboursUrl: `/api/projects/${projectId}/neighbours/${dataId}`, dataUrl: `/api/projects/${projectId}/data/${dataId}`, + annotationUrl: `projects/${projectId}/data/${dataId}/annotate`, segmentationUrl: `/api/projects/${projectId}/data/${dataId}/segmentations`, isDataLoading: false, wavesurfer: null, @@ -50,7 +56,7 @@ class Annotate extends React.Component { } componentDidMount() { - const { labelsUrl, dataUrl } = this.state; + const { labelsUrl, dataUrl, neighboursUrl } = this.state; this.setState({ isDataLoading: true }); const wavesurfer = WaveSurfer.create({ container: "#waveform", @@ -96,7 +102,7 @@ class Annotate extends React.Component { }); axios - .all([axios.get(labelsUrl), axios.get(dataUrl)]) + .all([axios.get(labelsUrl), axios.get(dataUrl), axios.get(neighboursUrl)]) .then((response) => { this.setState({ isDataLoading: false, @@ -110,6 +116,8 @@ class Annotate extends React.Component { filename, } = response[1].data; + console.log("This was the reponse from the thing: ", response) + const regions = segmentations.map((segmentation) => { return { start: segmentation.start_time, @@ -122,7 +130,14 @@ class Annotate extends React.Component { }; }); + const { + after_id, + before_id + } = response[2].data; + this.setState({ + afterId: after_id, + beforeId: before_id, isDataLoading: false, referenceTranscription: reference_transcription, isMarkedForReview: is_marked_for_review, @@ -179,6 +194,26 @@ class Annotate extends React.Component { wavesurfer.skipBackward(5); } + handleNextAnnotation() { + const { history } = this.props; + const { projectId, afterId } = this.state; + const path = `/projects/${projectId}/data/${afterId}/annotate`; + history.replace({ pathname: "/empty" }); + setTimeout(() => { + history.replace({ pathname: path }); + }); + } + + handlePreviousAnnotation() { + const { history } = this.props; + const { projectId, beforeId } = this.state; + const path = `/projects/${projectId}/data/${beforeId}/annotate`; + history.replace({ pathname: "/empty" }); + setTimeout(() => { + history.replace({ pathname: path }); + }); + } + handleZoom(e) { const { wavesurfer } = this.state; const zoom = Number(e.target.value); @@ -391,6 +426,16 @@ class Annotate extends React.Component { {!isDataLoading ? (
+
+ { + this.handlePreviousAnnotation(); + }} + /> +
+
+ { + this.handleNextAnnotation(); + }} + /> +