diff --git a/backend/migrations/versions/7726477fb5da_.py b/backend/migrations/versions/7726477fb5da_.py
new file mode 100644
index 0000000..6dd045e
--- /dev/null
+++ b/backend/migrations/versions/7726477fb5da_.py
@@ -0,0 +1,28 @@
+"""empty message
+
+Revision ID: 7726477fb5da
+Revises: b60bb67d1758
+Create Date: 2021-04-25 20:46:35.627535
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '7726477fb5da'
+down_revision = 'b60bb67d1758'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('data', sa.Column('tracked_time', sa.Integer(), nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('data', 'tracked_time')
+ # ### end Alembic commands ###
diff --git a/backend/models.py b/backend/models.py
index 710a880..5c9bf95 100644
--- a/backend/models.py
+++ b/backend/models.py
@@ -46,6 +46,7 @@ class Data(db.Model):
__tablename__ = "data"
id = db.Column("id", db.Integer(), primary_key=True)
+ tracked_time = db.Column("tracked_time", db.Integer(), default=0)
project_id = db.Column(
"project_id", db.Integer(), db.ForeignKey("project.id"), nullable=False
@@ -281,7 +282,9 @@ class Segmentation(db.Model):
)
values = db.relationship(
- "LabelValue", secondary=annotation_table, back_populates="segmentations",
+ "LabelValue",
+ secondary=annotation_table,
+ back_populates="segmentations",
)
def set_start_time(self, start_time):
diff --git a/backend/routes/projects.py b/backend/routes/projects.py
index a21f6c9..6c675df 100644
--- a/backend/routes/projects.py
+++ b/backend/routes/projects.py
@@ -455,6 +455,7 @@ def get_segmentations_for_data(project_id, data_id):
response = {
"filename": data.filename,
+ "tracked_time": data.tracked_time,
"original_filename": data.original_filename,
"reference_transcription": data.reference_transcription,
"is_marked_for_review": data.is_marked_for_review,
@@ -478,6 +479,7 @@ def update_data(project_id, data_id):
return jsonify(message="Missing JSON in request"), 400
is_marked_for_review = bool(request.json.get("is_marked_for_review", False))
+ tracked_time = int(request.json.get("tracked_time", 0))
try:
request_user = User.query.filter_by(username=identity["username"]).first()
@@ -492,7 +494,8 @@ def update_data(project_id, data_id):
return jsonify(message="Unauthorized access!"), 401
data.update_marked_review(is_marked_for_review)
-
+ if tracked_time:
+ data.tracked_time = tracked_time
db.session.add(data)
db.session.commit()
db.session.refresh(data)
diff --git a/examples/upload_data/upload_data.py b/examples/upload_data/upload_data.py
index ff7f07f..a62d77d 100644
--- a/examples/upload_data/upload_data.py
+++ b/examples/upload_data/upload_data.py
@@ -65,6 +65,7 @@
"reference_transcription": reference_transcription,
"username": username,
"segmentations": segmentations,
+ "tracked_time": 0,
"is_marked_for_review": is_marked_for_review,
}
diff --git a/frontend/src/pages/annotate.js b/frontend/src/pages/annotate.js
index b887110..29e8f76 100644
--- a/frontend/src/pages/annotate.js
+++ b/frontend/src/pages/annotate.js
@@ -29,6 +29,7 @@ class Annotate extends React.Component {
this.state = {
isPlaying: false,
projectId,
+ localTrackedTime: 0,
dataId,
labels: {},
labelsUrl: `/api/projects/${projectId}/labels`,
@@ -49,7 +50,47 @@ class Annotate extends React.Component {
this.transcription = null;
}
+ handleTrackTimeChange() {
+ axios({
+ method: "patch",
+ url: this.state.dataUrl,
+ data: {
+ tracked_time: this.state.localTrackedTime,
+ },
+ })
+ .then(() => {
+ this.setState({
+ successMessage: "Tracked Time updated succesfully",
+ });
+ })
+ .catch((error) => {
+ console.log(error);
+ this.setState({
+ errorMessage: "Tracked Time not updated",
+ });
+ });
+ }
+
+ // fired, when changing to an internal page
+ componentWillUnmount() {
+ clearInterval(this.interval);
+ this.handleTrackTimeChange();
+ }
+
componentDidMount() {
+ // anytime changed to another page
+ window.onbeforeunload = function () {
+ this.handleTrackTimeChange();
+ }.bind(this);
+
+ this.interval = setInterval(
+ () =>
+ this.setState({
+ localTrackedTime: this.state.localTrackedTime + 1000,
+ }),
+ 1000
+ );
+
const { labelsUrl, dataUrl } = this.state;
this.setState({ isDataLoading: true });
const wavesurfer = WaveSurfer.create({
@@ -108,6 +149,7 @@ class Annotate extends React.Component {
is_marked_for_review,
segmentations,
filename,
+ tracked_time,
} = response[1].data;
const regions = segmentations.map((segmentation) => {
@@ -121,11 +163,16 @@ class Annotate extends React.Component {
},
};
});
-
+ if (tracked_time) {
+ this.setState({
+ localTrackedTime: this.state.localTrackedTime + tracked_time,
+ });
+ }
this.setState({
isDataLoading: false,
referenceTranscription: reference_transcription,
isMarkedForReview: is_marked_for_review,
+ localTrackedTime: tracked_time,
filename,
});
@@ -352,6 +399,7 @@ class Annotate extends React.Component {
zoom,
isPlaying,
labels,
+ localTrackedTime,
isDataLoading,
isMarkedForReview,
referenceTranscription,
@@ -510,7 +558,7 @@ class Annotate extends React.Component {
selectedSegment.data.annotations &&
selectedSegment.data.annotations[key] &&
selectedSegment.data.annotations[key][
- "values"
+ "values"
]) ||
(value["type"] === "multiselect" ? [] : "")
}
@@ -575,6 +623,10 @@ class Annotate extends React.Component {
>
Mark for review
+
+